How to bind event for element inner JQuery plugin?

1.7k views Asked by At

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!

2

There are 2 answers

0
Martin Ernst On BEST ANSWER

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.

0
Mike Willis On

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/