22

I have a jQuery plugin that I am using:

$(document).ready(function(){
    $('.elements').fancyPlugin();
});

This works great until I start adding new elements:

$.get('ajax.html', function(data){
    $('#container').html(data);
});

I could call the plugin function again like this:

$.get('ajax.html', function(data){
    $('#container').html(data).find('.elements').fancyPlugin();
});

...except that the AJAX is happening inside another jQuery plugin that shouldn't have to know about the fancyPlugin().

How can I apply this plugin to all current and future elements?

Paul
  • 139,544
  • 27
  • 275
  • 264
Andrew
  • 227,796
  • 193
  • 515
  • 708
  • ok ok ok I know this one...... hrmmmm... ok maybe not completely but you should use an event listener. I would bind DOMNodeInserted on the document and call your function then. – Joseph Marikle Jul 21 '11 at 19:40

7 Answers7

15

I think this will work in all browsers except IE:

document.body.addEventListener("DOMNodeInserted", function(event){
    var $elementJustAdded = $(event.target);
    if ($elementJustAdded.hasClass('elements')) {
        $elementJustAdded.fancyPlugin();
    }
}, false);
Andrew
  • 227,796
  • 193
  • 515
  • 708
Paul
  • 139,544
  • 27
  • 275
  • 264
12

Another way of doing this is creating your own event :

var container=$('#container');
$.get('ajax.html', function(data){   
   container.html(data);
   $('.elements',container).trigger('added.yourns');    
});

container.on('added.yourns','.elements',function(){
  $(this).fancyPlugin();
});

Then, when adding ellements, simply trigger the event with the trigger method!

var aDiv=$('div');
aDiv.appendTo(someNode);
aDiv.trigger('added.yourns');

Doing so will enable you to attach any behaviour in any javascript file !

programaths
  • 891
  • 1
  • 11
  • 23
  • You answered a question for me that stuck in my head for months...and today I just needed this. You made someone happy, cheers :)))))))))))))))) – Lamis Jun 27 '13 at 15:48
  • This is great, helped solve something I was building. Thanks! – Alec Menconi Jul 15 '14 at 15:13
  • What does this solve? If I have to eventually call `aDiv.trigger('added.yourns');`, why couldn't I just call `.fancyPlugin()` on the newly loaded node? We need to NOT have to call anything each time a new node is added; that's the whole point of this question, or am I missing something? – Ifedi Okonkwo Jun 11 '15 at 07:20
  • If you modify the same DOM element in many places, you are seeking for problems ! What it does solve is that you can listen on the event to call any plugins you need and not only one! You may have other handlers to read the new value or do other fancy stuff. As you can see, it has its uses cases otherwise other people wouldn't have thanked me ;-) – programaths Jun 11 '15 at 07:36
2

If those elements are added with AJAX you could use the .ajaxSuccess() method:

$('#container').ajaxSuccess(function(result) {
    $('.elements').fancyPlugin();
});

And here's a live demo.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Be careful: "As of jQuery 1.8, the .ajaxSuccess() method should only be attached to document." http://api.jquery.com/ajaxsuccess/ – jacekll Jun 19 '15 at 08:28
0

Have your AJAX handler trigger some custom event like contentAdded, and bind fancyPlugin to that event.

Alternatively, you can use DOM mutation events to call fancyPlugin for any change in the container. Native browser support isn't quite there yet, but there are plugins which should take care of that.

Tgr
  • 27,442
  • 12
  • 81
  • 118
  • I wish you could show **how** to use the DOM mutation events! – Ifedi Okonkwo Jun 11 '15 at 07:09
  • Mutation events have been since then replaced by the [Mutation Observer](http://www.w3.org/TR/dom/#mutation-observers) which has [decent support](http://caniuse.com/#search=mutation). MDN has [a code example](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#Example_usage). – Tgr Jun 11 '15 at 14:39
0

Interesting. Essentially, you'd like something like:

$('selector').ready( ... do something ... );

The problem is that kind of logic isn't available. Elements loading on the page don't trigger any specific events I'm aware of, they just inherit CSS from the DOM nodes above them. What I would do is just, from the $.get success function, trigger a custom event. The rest of your code can hook into that event to do any plugin reloading work that may be needed. You can pass a list of relevant selectors with the event, and use that to invoke the appropriate plugins (you can keep a set of selector -> plugin refresh function relationships in a hashtable)

Milimetric
  • 13,411
  • 4
  • 44
  • 56
-1

Have you looked at the jQuery .live event handler? It automatically binds when a new item is added to the dom if it meets the specified requirements.

http://api.jquery.com/live/

William
  • 8,007
  • 5
  • 39
  • 43
  • 1
    As you can see, the `load` event is not implemented in jQuery's live function: http://stackoverflow.com/questions/3196404/jquery-live-with-the-ready-or-load-event – Milimetric Jul 21 '11 at 19:45
-1

What if you make something like this?

$(document).ready(function(){
    $('.elements').live('load', function () {
        $(this).fancyPlugin();
    })
});

The events are not re-binded after ajax calls or within the content they return. live() attaches a handler to the event now and in the future."

spliter
  • 12,321
  • 4
  • 33
  • 36
  • 1
    As you can see, the `load` event is not implemented in jQuery's live function: http://stackoverflow.com/questions/3196404/jquery-live-with-the-ready-or-load-event – Milimetric Jul 21 '11 at 19:45