0

This is some code of JQuery plugin.

...    
return this.each(function(index, el) {
        var $this = $(this), data = $this.data('control');

        $(el).on('click',el, function(){
            alert('hello world!');
        }); 
    });
...

I use it so:

$('.mybutton').myPlugin();

Click function normaly work for all elements on page who have .mybutton class, but don't work on ajax loaded elements. Guys, how i can bind click function in JQ plugin for dinamic created elements? Many thanks!

hcuser
  • 51
  • 1
  • 3
  • 9
  • does if help if you make your original method call: $('.mybutton').myPlugin(); also after every ajax call? – jyrkim Nov 18 '14 at 14:45
  • Instead of `$(el).on('click', el, function(){} );` have you tried something like `$(document).on( 'click', el, function(){} );`? In the first case you're binding to the elements themselves, which may or may not exist at that time. In the second case you're binding to the document, which definitely exists. – Mike Willis Nov 18 '14 at 14:48
  • 1
    $(document).on( 'click', el, function(){} ); ← this code dont work, because 'el' not is selector, its object. 8-( – hcuser Nov 18 '14 at 14:59
  • @jyrkim That will add multiple click-handlers to the existing elements. – Martin Ernst Nov 18 '14 at 15:31
  • Maybe you can combine what I suggested with the answer here to get the selector used in the call to the plugin, and replace `el` with the selector? http://stackoverflow.com/questions/5477394/getting-initial-selector-inside-jquery-plugin – Mike Willis Nov 18 '14 at 15:37
  • @Zilog You have to perform `.myPlugin()` on each newly created element and add it then to the existing collection, which must be stored before. For a practical solution we would need to see the code that creates the elements. – Martin Ernst Nov 18 '14 at 15:37
  • @MartinErnst cheers, I'm not very familiar that particular plugin, so thanks for helping out :-) – jyrkim Nov 18 '14 at 15:41
  • @Martin Some elements already exist on the page. Other elements loaded by ajax as html code. – hcuser Nov 18 '14 at 15:51

2 Answers2

0

Based on our comment discussion, this should do the trick.

  1. bind to document
  2. bind using the element selector, not the element itself

Some code:

$.fn.myPlugin = function () {
    $(document).on("click", this.selector, function (event) {
        event.preventDefault();
        alert("document(myButton) has been clicked");
    });
}
$(document).ready(function (event) {
    $(".myButton").myPlugin();
    $("#addMoreButtons").click(function (event) {
        event.preventDefault();
        $("<a/>").attr({
            "href": "javascript:void(0);",
            "class": "myButton"
        }).text("Button").appendTo("#buttons");
        $("#buttons").append("<br>");
    });
});

working fiddle here: http://jsfiddle.net/p2bwryj1/

Mike Willis
  • 1,493
  • 15
  • 30
0

1) If you want a common event-handler for existing and newly created elements use event-delegation. The handler is bound to an element higher up in the DOM that always exists, or to the document. Each time an event bubbles up the DOM and reaches the document, the handler looks if the event comes from an element that matches the given selector and only then executes.

2) You should set up the handler separately outside your plugin. Otherwise each time you call the plugin a new event-handler is attached, and you get multiple events on one click.

// this handler executes whenever an element with class 'mybutton' is clicked
// and works for existing and newly added elements
$(document).on('click', '.mybutton', function (event) {
    console.log('A class "mybutton" was clicked');
    /* whatever to do on click here */
});

// your plugin code without the click-handler
$.fn.myPlugin = function() {
    return this.each(function(i, el) { /* whatever your plugin has to do */ });
};

3) If you now use your plugin store the returned object in a variable. If you need it later you don't have to create it a second time, just refer to it by var name.

var buttons = $('.mybutton').myPlugin();

4) But note this call gets only the buttons that exists in the DOM when its run. If you later get a new element inserted in the DOM and want it added to the buttons-collection you have to do that manually.

// example for a new element on which you call your plugin
var newbutton = $('<button class="mybutton">Mynewbutton</button>').myPlugin();
$('body').append(newbutton); // insert the new element in the DOM
buttons.add(newbutton); // this adds the new element to the existing collection

If you absolutely want to attach the click-handler inside your plugin it has to look like:

$.fn.myPlugin = function() {
    return this.each(function(index, el) {
    var $this = $(this), data = $this.data('control');
    // attach a click handler to each element with class 'mybutton'
    if ($this.hasClass('mybutton')) $this.on('click', function(){
        alert('hello world!');
    });
    /* more code */
});

But note now you have to call your plugin on each newly created button.

Martin Ernst
  • 3,199
  • 1
  • 12
  • 12