3

There's quite a bit that goes into this question so I'll try and keep it as simple as I can. basically I have a jQuery tooltip on a column of td's in a table. I do an ajax request to pull some data out and display it... I display a loading gif while im waiting for the callback to complete. once that finishes the contents are replaced with what is returned... i'll show some code in a sec to help clarify. I use javascript to return a HTML table back. the table can have either 1, 2 or 3 rows depending on what is returned back from the ajax request. all of this works just fine.

the issue i have is once the gif is replaced with the table, its size is bigger which causes a problem with the spacing. I recorded a video of it for you to see what happens... when i hover over the td a second time the tooltip displays correctly (above the td) instead of covering it. its doing this because its going off of a top position (built in jQuery method to set an offset). THIS VIDEO

any help on this would be really appreciated!


HTML IN JAVASCRIPT PORTION

var setWhateverData = function(sent){
    if(sent){
        var $finishThisShitStr ="";
            if(thingy['type'] =="whatever"){
                var $whateverStr = '<table>' +
                    '<tr>' +
                        '<td><div><img src="my-logo.png"></div></td>' +
                        '<td>' + thingy.whatever + '</td>' +
                    '</tr>' +
                '</table> ';
            }
            else if (thingy['type'] == "maybe") {
                var $maybeStr = '<table>' +
                    '<tr>' +
                        '<td><div><img src="my-logo.png"></div></td>' +
                        '<td>' + thingy.maybe + '</td>' +
                    '</tr>' +
                '</table> ';

            }
            else if (thingy['type'] == "haha"){
                var $hahaStr = '<table>' +
                    '<tr>' +
                        '<td><div><img src="my-logo.png"></div></td>' +
                        '<td>' + thingy.haha + '</td>' +
                    '</tr>' +
                '</table> ';
            }
            else{
                $finishThisShitStr = '<span>YOU DUN GOOFED</span>'
            }
        };
        if($whateverStr){   // add strings of html to final string to return
            $finishThisShitStr = $finishThisShitStr + $whateverStr;
        }
        if($maybeStr){
            $finishThisShitStr = $finishThisShitStr + $maybeStr;
        }
        if($hahaStr){
            $finishThisShitStr = $finishThisShitStr + $hahaStr;
        }
        return $finishThisShitStr;
    }
}

JQUERY TOOLTIP PORTION

$('td').tooltip({ 
    items: "[data-whatever]",
    content: function(){
        var el = $(this),
            content = el.data('ajax-stuff');
        if(content)
            return content;    
        return '<img src=mySpinnerGif.gif>';
    },
    open: function(){
        var elem = $(this),
            info = elem.data('ajax-stuff');
        if (info) {
          elem.tooltip('option', 'content', info);
        } else {
          var id = elem.data('whatever');
            $.ajax('/echo/html/' + id).always(function(result)  {
                var $data = setWhateverData(result)
                elem.tooltip('option', 'content', $data);
                elem.data('ajax-stuff', $data);
            });
        }
    }
});

as you can see i call the function to set the data and pass it whats returned... I am just not really familiar with the tooltip and how to check for whats returned..

ADDITIONAL NOTES:

should I even return html in javascript like this ( i usually don't like to, but didn't see another option)?

is there a way to tell it to anchor off of the bottom of the tooltip and not the top?

EDIT: this is a jsfiddle duplicating a similar case.. the problem is when the data is updated it doesn't reposition itself - rather goes off of the top of the location. so I need to like recall the position function or something like that. http://jsfiddle.net/gF3sG/2/

SOLVED FOR OTHERS TO USE ---- FINAL SOLUTION:

$('td').tooltip({ 
    items: "[data-whatever]",
    content: function(){
        var el = $(this),
            content = el.data('ajax-stuff');
        if(content)
            return content;    
        return '<img src=mySpinnerGif.gif>';
    },
    open: function(){
        var elem = $(this),
            info = elem.data('ajax-stuff');
        if (info) {
          elem.tooltip('option', 'content', info);
        } else {
          var id = elem.data('whatever');
            $.ajax('/echo/html/' + id).always(function(result)  {
                var $data = setWhateverData(result)
                elem.data('ajax-stuff', $data);
                elem.tooltip("close");
                elem.tooltip("open");
            });
        }
    }
});
John Ruddell
  • 25,283
  • 6
  • 57
  • 86
  • You can always add html dynamically i.e. `var txt = "

    InnerHTML

    "`==`var txt = $("

    ").text("InnerHTML")`==`var txt = document.createElement("p"); txt.innerHTML="InnerHTML"`. Also, have you tried destroying the tooltip after the content is returned, set the content, then calling `open` again afterwords?
    – em_ May 13 '14 at 19:04
  • @ElliotM how would I do that? i tried destroy and open but couldn't get it to work.. just got the error that it was trying to call it before instantiated. – John Ruddell May 13 '14 at 20:25
  • It'd be extremely helpful if you made a jsfiddle to simulate this situation. – em_ May 14 '14 at 14:38
  • @ElliotM ok i just added a fiddle that replicates the issue.. its not an ajax call but the idea is the same. – John Ruddell May 14 '14 at 15:10
  • 1
    It seems you already have a bug filed: http://bugs.jqueryui.com/ticket/9018 – Abhitalks May 14 '14 at 15:29
  • I noticed that after I asked this question... :/ do you know of a way to manually tell it to reposition? if you put the tooltip below then its just fine because it adds to the bottom. kinda frustrating lol – John Ruddell May 14 '14 at 15:33

2 Answers2

2

I was able to accomplish what was described by first closing the tooltip, re-adding the positioning and content, the opening it back up. It seems rather redundant, but it works.

$("#trigger").tooltip({
position: {
    my: "center bottom-20", // the "anchor point" in the tooltip element
    at: "center top" // the position of that anchor point relative to selected element
},
items: '#trigger',
content: function(response) {

    setTimeout( function() {

      doIt();

    }, 1500);
    return 'Testing.<br>testing<br>testing<br>testing<br>testing<br>';
}
});

function doIt(){

$("#trigger").tooltip("close");

 var html = '';
for ( var i = 0; i < 10; i++ ){
     html += 'Hello ' + i + '<br />';
}

$("#trigger").tooltip({
position: {
    my: "center bottom-20", // the "anchor point" in the tooltip element
    at: "center top" // the position of that anchor point relative to selected element
},
items: '#trigger',
content: html
});

$("#trigger").tooltip("open");
}

http://jsfiddle.net/fenderistic/W6x83/

em_
  • 2,134
  • 2
  • 24
  • 39
  • Awesome! I had to make some changes to get it working with mine. but the logic is what I was confused on. theres one thing thats a little strange though, it refreshes it to the correct spot and then reloads it a second time. the function call doIt() is in an ajax callback. the reason is because thats in an `open:` function which gets called after you reopen the tooltip (which in turn calls the doIt() function again) thoughts? – John Ruddell May 14 '14 at 17:47
  • basically the doIt() function gets called twice because its in the open: function().. and the open function gets called every time the tooltip gets instantiated. heres a fiddle replicating that. http://jsfiddle.net/W6x83/19/ – John Ruddell May 14 '14 at 18:09
  • Nvm I solved it. i had to set my checker inside the doIt function... basically where i set `data('ajax-stuff')` is how I check to see if its been instantiated before or not. so I had to set that in the doIt function instead of right after calling the function. Thanks again for your help!! im going to give you a few extra +1's :) – John Ruddell May 14 '14 at 18:23
  • I edited my answer with the final solution if you want to see what I did and also so others that come by can replicate this :) thanks again! – John Ruddell May 14 '14 at 18:28
1

In your ajax method or setTimeout you can get a reference to the tooltip using the widget function. Once you have the reference to the "loading" tooltip you can close it before you set the ajax data. Once the new data is set the tooltip is reopened using the new height.

$('#trigger').tooltip();
//Get refrence to the tooltip widget
var w = $('#trigger').tooltip('widget');
w.tooltip('close');

Forked fiddle: http://jsfiddle.net/smurphy/wqH22/2/

Scott Murphy
  • 448
  • 2
  • 12
  • so this is not what I was asking for because it refreshes the tooltip to the bottom of the div instead of anchoring off of the top to keep it up there – John Ruddell May 14 '14 at 17:41
  • It refreshes at the bottom because there isn't enough room at the top... Same issue I ran into when testing with my implementation. Just add more `
    `s and it works.
    – em_ May 14 '14 at 18:14
  • adding br's doesnt work with his still lol.. i edited my comment with a fiddle on your answer ElliotM – John Ruddell May 14 '14 at 18:17
  • It uses the tooltip logic to re-render the tooltip. If there is room at the top it renders there if there is room at the bottom it renders there. You can set the collision logic to fit which will force it to stay at what you have specified. It defaults to flip. http://jsfiddle.net/smurphy/wqH22/3/ – Scott Murphy May 14 '14 at 18:57
  • I had no idea there was that collision option. I just found the source to see some more options with that. very nice. i dont need to do the doIt() function anymore I tested with just closing and then opening it and it works. – John Ruddell May 14 '14 at 19:23