Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attaching jQuery plugin calls to dynamically loaded elements via jQuery,on()

I have a portion of code that is dynamically loaded via an AJAX call by appending the result to a parent element, similar to this:

<div class="parent">
     <!-- Inner content loaded dynamically -->
     <div class="child">
     </div>
     <div class="child">
     </div>
     <!-- ... -->
</div>

Now, in order to hook up a mouseover event, I would do something like this:

$(".parent").on("mouseenter", ".child", function(){
 //Do fun stuff here
}

$(".parent").on("mouseleave", ".child", function(){
 //Undo fun stuff here
}

This works well enough for standard functions, but I want to attach this to a third-party plugin (in my case, HoverIntent, but really any plugin) -

The syntax for attaching the HoverIntent plugin is as so:

$(".child").hoverIntent( makeTall, makeShort )

... but I want this to work for my dynamic content that was not available at the time the document initially loaded, and something like $(".parent").on("hoverIntent", ".child", function(){}); doesn't seem to be the right way to do this.

What is the correct approach to applying a plugin to elements loaded after the initial $(document).ready()?

like image 589
Evan Avatar asked Dec 31 '11 21:12

Evan


3 Answers

jquery .on works by monitoring events on a parent object and then calling the handler if the event originated from a matched child selector. In your case, however, the event you want to monitor is that the element changed

Browsers fire the onchange event for input elements only (because they can be changed by a user).

If any other element changes, it must be because of javascript, hence you can call functions after created new content.

$(".child", parentElementContext).hoverIntent( makeTall, makeShort )

There are 2 practical solutions

1) What i typically do is create an init method that takes a context (such as the document).

MyPage.init = function(context) {
    $('.selector', context).hoverIntent();
    $('.other', context).dialog(); // any other plugins
};

Then I manually call init when I update the DOM (because i dont always need to call init when I update the dom)

$.ajax({
  url: url,
  data: data,
  success: function(data){ 
     var context = $('.parent'); 
     context.html(data);
     MyPage.init(context); //calls hoverIntent and other plugins
  }
});

2) If you really need to monitor everything, you can use this plugin http://james.padolsey.com/javascript/monitoring-dom-properties/

and then $('.parent').on('valuechange', function() { /* init plugins*/}

like image 179
jermel Avatar answered Nov 12 '22 08:11

jermel


I have used the jQuery Livequery plugin in the past to do this

like image 4
Ken Keenan Avatar answered Nov 12 '22 07:11

Ken Keenan


You can use live to attach event to element that will be in the DOM right now or in the future.

$(".parent .child").live("mouseover", function(){
    //Do fun stuff here
}).live("mouseout", function(){
    //Undo fun stuff here
});

so your plugin could look like this

$.fn.hoverIntent = function(mouseover, mouseout) {
    this.live("mouseover", mouseover).live("mouseout", mouseout);
    return this;
};

and you can call this plugin

$(".parent .child").hoverIntent(makeTall, makeShort).load("other_page.php");
like image 1
jcubic Avatar answered Nov 12 '22 07:11

jcubic