This is one of the most interesting jQuery errors. It is not commonly known when jQuery is used in normal web development but pair it with the jQuery Mobile and all hell breaks loose. Through recent years jQuery provided us with several functions meant for an event binding:
 
 
Update: This page used to have embedded working examples, unfortunately, iframes heavily prolonged page loading so I moved the here. Or you can access them directly via below examples.
 
None of them will check if given an event is already binded. jQuery Mobile works in a different way than classic web applications. Depending on how you managed to bind your events each time you visit some page it will bind events over and over. This is not an error, it is simply how jQuery Mobile handles its pages. For example, take a look at this code snippet:
 
$(document).on('pagebeforeshow','#index' ,function(e,data){    
    $(document).on('click', '#test-button',function(e) {
        alert('Button click');
    });    
});
 
Each time you visit page #index click event will is going to be bound to button #test-button. Test it by moving from page 1 to page 2 and back several times.
 
Error Example
 
Several solutions exist to prevent this from happening.
 
Before we continue make sure that you know how and when to bind events when working on jQuery Mobile application. This is very important, first avoid using document ready when working with jQuery Mobile. This is because jQuery Mobile requires additional execution time during page markup enhancement process and document ready will usually trigger before this process can end. This way you will try to bind an event to something that still don’t exist inside the DOM.
 

Solution 1

 
Easiest solution would be to use pageinit for event binding. If you take a look at an official documentation you will find out that pageinit will trigger only once, just like document ready, so there’s no way events will be bound again. Unfortunately, there’s one little thing not mentioned in the official documentation.
 
Pageinit will trigger only once if used in multipage template, if multi-HTML is used pageinit will trigger every time page is loaded into the DOM (more information can be found here and here).
 
$(document).on('pageinit', '#index', function(){       
    $(document).on('click', '#test-button',function(e) {
        alert('Button click');
    }); 
});
 
Working Example 1
 

Solution 2

 
Second solution requires is also an easy one. Before an event is bind you should try to unbind it. Every function used for even binding has a similar function used for event removal (you will find them enumerated at the beginning of this article, every binding function is coupled with a related removal function). Use this solution if first one is not suitable, mostly because it more complex and demanding.
 
$(document).on('pagebeforeshow', '#index', function(){       
    $(document).off('click', '#test-button').on('click', '#test-button',function(e) {
        alert('Button click');
    }); 
});
 
Working Example 2
 

Solution 3

 
Third solution uses nifty jQuery plugin called “Event filter”. Use it like this:
 
$('#carousel div:Event(!click)').each(function(){
    //If click is not bind to #carousel div do something
});
 
This filter can be found here: http://www.codenothing.com/archives/2009/event-filter/
 

Solution 4

 
This is almost easiest solution to implement.
 
$(document).on('pagebeforeshow', '#index', function(){       
    $(document).on('click', '#test-button',function(e) {
        if(e.handled !== true) // This will prevent event triggering more then once
        {
            alert('Clicked');
            e.handled = true;
        }
    }); 
});
 
Javascript is used to check if an event is already been triggered. I don’t prefer this solution because it will not stop event binding process, it will just prevent multiple even execution.
 
Working Example 4
 
Note Solution found here: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/
 

16 COMMENTS

  1. Wow.. nice one.

    I’ve had this error before, don’t remember ho I handled it, but I know it was tricky.
    I even tried using the native javascript “onload” to wrap my jquery events, but It still happened anyway.

    This is a really good way to work around it.

    Thanks Dragan.

  2. Keven

    Solution 2 worked for great for me! Thank you!!

  3. Kamil

    Thanks for this! I used second solution and it works great! Your post is a fantastic collction of useful solutions.

  4. thank you very much, you save my day, i was looking the solution for my multiple firing problems, working great..

  5. amine

    Very very useful. My day is saved. Thank you

  6. Janou

    I used Solution #4 which was perfect for my needs. I couldn’t figure out for the life of me why my submit button within my partial view was executing twice. This solution solved my problem easy. Thanks!

  7. Mayank

    Thanks For this ..this is really great..

  8. Steve

    You are a hero!!!

  9. Terence

    Excellent article. Saved my day even a year after you wrote it. Thanks

  10. Terence

    Thanks for this nice article. Still saved my day even a year after you wrote it. thanks

    • This is only a partial solution (thou still valid one). It is viable only if we don’t mind that handler is unbound after its first invocation.

  11. Said Moshref

    Whats about $(“#button”).unbind(“click”).on(“click”,function(e){ return false));

    • off() should be used with on() :

      $(“#button”).off(“click”).on(“click”,function(e){ return false));

      Take from the official jQuery website:

      As of jQuery 1.7, use of .die() (and its complementary method, .live()) is not recommended. Instead, use .off() to remove event handlers bound with .on()

LEAVE A REPLY


four − 4 =