8

I'm using the jQuery Tools tooltip plugin, which is initialized with $('selector').tooltip(). I'd like to call this on any current or future .tooltipper element. I figured that the following would work:

$('.tooltipper').live('ready', function(){
  $(this).tooltip()
}

But it was unsuccessful---the ready event did not fire. The same for load. I've read that livequery can produce the result of I'm looking for, but surely there is a way to use jQuery .live() to pull it off, considering the documentation says that it works for all jQuery events, of which I believe ready is one.

Steven
  • 17,796
  • 13
  • 66
  • 118
  • If the element exists on ready, why use `.live()` ? I think you would probably be better off trying to bind it to the event that would potentially create new `selector`'s. Not directly an answer but it seems like sort of a shotgun approach to use `.live()` on `ready`. Just my $.02. – HurnsMobile Jul 07 '10 at 15:49
  • I think of it this way. Certain elements should always exhibit certain behaviours. For instance, links with a `href` attribute should always take you to a URL when clicked. Most elements with a `title` attribute should display the parameter as a tooltip on mouse over. It only makes sense to me to enable this sort of functionality to higher-order behaviours, like custom tooltipping. – Steven Jul 07 '10 at 16:36
  • 1
    I ended up simply using `$('.tooltipper').livequery(function(){$(this).tooltip()})`, which makes the most semantic sense to me (as opposed to the next best solution, which is to add the callback to the function that creates the tooltip element) in that the tooltip behaviour is associated with the element---it has nothing to do with the process by which it is created. – Steven Jul 07 '10 at 16:39
  • Steven - valid points on all accounts. +1 for an all around informative question and answers. – HurnsMobile Jul 07 '10 at 16:55

3 Answers3

12

Quoted from the jQ API (http://api.jquery.com/live/):

In jQuery 1.3.x only the following JavaScript events (in addition to custom events) could be bound with .live(): click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, and mouseup.

As of jQuery 1.4 the .live() method supports custom events as well as all JavaScript events.

As of jQuery 1.4.1 even focus and blur work with live (mapping to the more appropriate, bubbling, events focusin and focusout).

As of jQuery 1.4.1 the hover event can be specified (mapping to "mouseenter mouseleave").

.live() does not appear to support the ready event.

Community
  • 1
  • 1
HurnsMobile
  • 4,341
  • 3
  • 27
  • 39
5

To add to HurnsMobile's excellent answer; Looking at bindReady(), which is the internal call that jQuery makes to bind to the document load event every time you call $(some_function) or $(document).ready(some_function) we see why we cannot bind to "ready":

bindReady: function() {
        if ( readyBound ) {
            return;
        }

        readyBound = true;

        // Catch cases where $(document).ready() is called after the
        // browser event has already occurred.
        if ( document.readyState === "complete" ) {
            return jQuery.ready();
        }

        // Mozilla, Opera and webkit nightlies currently support this event
        if ( document.addEventListener ) {
            // Use the handy event callback
            document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

            // A fallback to window.onload, that will always work
            window.addEventListener( "load", jQuery.ready, false );

        // If IE event model is used
        } else if ( document.attachEvent ) {
            // ensure firing before onload,
            // maybe late but safe also for iframes
            document.attachEvent("onreadystatechange", DOMContentLoaded);

            // A fallback to window.onload, that will always work
            window.attachEvent( "onload", jQuery.ready );

            // If IE and not a frame
            // continually check to see if the document is ready
            var toplevel = false;

            try {
                toplevel = window.frameElement == null;
            } catch(e) { //and silently drop any errors 
                    }
                    // If the document supports the scroll check and we're not in a frame:    
            if ( document.documentElement.doScroll && toplevel ) {
                doScrollCheck();
            }
        }
    }

To sum it up, $(some_function) calls a function which binds to:

  • DOMContentLoaded
  • onreadystatechange (DOMContentLoaded)
  • window.load / onload

Your best bet would be to bind to those actions that might create new .tooltipper elements, rather than trying to listen for the ready event (which happens only once).

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • Excellent! Thanks for the additional detail Sean! – HurnsMobile Jul 07 '10 at 16:03
  • Thanks for the thought-out answer. I've bound jQuery tools calls to 'constructors' in your manner before, but the idea of this line of inquiry is to try to avoid doing that entirely. My reasoning behind that is that the tooltippiness of a tooltip has nothing to do with the tooltip being constructed, and rather intrinsic in the tooltip itself. – Steven Jul 07 '10 at 17:21
1

HurnsMobile is right. JQuery live does not support the ready-event.

This is why I created a plugin that combines the two. You register your callback once, and then you will need to call the plugin once for content you add manually.

$.liveReady('.tooltipper', function(){
  this.tooltip()
});

Then when creating new content:

element.html(somehtml);
element.liveReady();

or

$('<div class="tooltipper">...').appendTo($('body')).liveReady();

A demo is available here: http://cdn.bitbucket.org/larscorneliussen/jquery.liveready/downloads/demo.html

Check out the introductory post here: http://startbigthinksmall.wordpress.com/2011/04/20/announcing-jquery-live-ready-1-0-release/


Also have a look at http://docs.jquery.com/Plugins/livequery, which listenes for changes on the dom.

Lars Corneliussen
  • 2,513
  • 2
  • 26
  • 36