Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery mobile .click firing multiple times on new page visit

So I am using Jquery mobile with great success except for one issue. Now every time a dynamic content page is navigated to by a user no matter what content displays, there is always a button at the bottom that when clicked emails the content to the address specified; works great. Now the first time a page is loaded, the click fires the event once. On the second visit its fired twice, third 3 times, etc. you get the point. I've scoured the net and implement every fix I could come across, such as using "pagecreate" instead of "pageinit", binding, unbinding, removing the div, turning off caching in the DOM but nothing works. The only success I've had is using .one() on the click but it needs to be fired if clicked again. Here is the structure. I have to .js files that load each with this to start

$( "#page" ).live( "pageinit", function() { 

Now I had the email function and other stuff in one file, but it makes it easier to separate them and I heard it does not matter. Now, here is the email function called in the pageinit

$('.eb').live('click', function() {
        var id = $('.eb').attr('id');
        var to = $('#recipient').val();
        var message = $('#email').html();

        var atpos = to.indexOf("@");
        var dotpos = to.lastIndexOf(".");
        if (atpos < 1 || dotpos < atpos + 2 || dotpos + 2 >= to.length) {
            alert('Please enter a valid email address!');
            return false;
        } 

        if(to.length == 0) {
            alert('Please enter a valid email address!');
            return false;
        } 

        $.mobile.showPageLoadingMsg();

        $.post('./services/service.email.php', { id: id, to: to, message: message}, function(data) {
            if(data.success == true) {
                $.mobile.hidePageLoadingMsg();
                alert('Your recipe has been sent!');
                $('#recipient').val('');
                return true;
            } 

            if(data.success == false) {
                if(data.fail == 1) {
                    alert('An error has occured sending your recipe. Try again soon!');
                    return false;
                }

                if(data.fail == 2) {
                    alert('Please enter a valid email address!');
                }
            }
        }, 'json');
            return false;
    }); 

Everything works flawlessly except the incremental firing of the .click on each new page. Can anyone lead me in the right direction?

like image 520
Naterade Avatar asked Jan 30 '12 16:01

Naterade


People also ask

Why is this jQuery Ajax click event firing multiple times?

an Event will fire multiple time when it is registered multiple times (even if to the same handler).

What is the difference between .on click function ()) and .click function?

So onclick creates an attribute within the binded HTML tag, using a string which is linked to a function. Whereas . click binds the function itself to the property element.

How do you make a button click only once in jQuery?

jQuery one() Method When using the one() method, the event handler function is only run ONCE for each element.


2 Answers

As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.

If you are using 1.7+ try to unbind the click event using .off() first.

$('.eb').off('click').on('click', function() {
 // ...
}); 

if you have to use .live() you can unbind the events with .die()

$('.eb').die('click').live('click', function() {
 // ...
});

or better use .delegate() and .undelegate() un the parent element:

$(document).undelegate('.eb', 'click').delegate('.eb', 'click', function() {
 // ...
});
like image 176
Ingemar Avatar answered Oct 12 '22 23:10

Ingemar


Simply move the click event handler code outside of the pageinit event handler code like this:

$( document ).delegate( "#page", "pageinit", function() {


});
$(document).delegate('.eb', 'click', function() {
        var id = $('.eb').attr('id');
        var to = $('#recipient').val();
        var message = $('#email').html();

        var atpos = to.indexOf("@");
        var dotpos = to.lastIndexOf(".");
        if (atpos < 1 || dotpos < atpos + 2 || dotpos + 2 >= to.length) {
            alert('Please enter a valid email address!');
            return false;
        } 

        if(to.length == 0) {
            alert('Please enter a valid email address!');
            return false;
        } 

        $.mobile.showPageLoadingMsg();

        $.post('./services/service.email.php', { id: id, to: to, message: message}, function(data) {
            if(data.success == true) {
                $.mobile.hidePageLoadingMsg();
                alert('Your recipe has been sent!');
                $('#recipient').val('');
                return true;
            } 

            if(data.success == false) {
                if(data.fail == 1) {
                    alert('An error has occured sending your recipe. Try again soon!');
                    return false;
                }

                if(data.fail == 2) {
                    alert('Please enter a valid email address!');
                }
            }
        }, 'json');
            return false;
    }); 

When you use event delegation you don't want to bind inside another event handler, because each time that event handler fires you will be re-binding (and when you delegate event handlers they are delegated for the life of the DOM).

You can also use .bind() instead of .live() (this is my preferred method):

$( document ).delegate( "#page", "pageinit", function() {
    $('.eb').bind('click', ...);
});

You will notice that both of my examples change-out .live() for .delegate() as it performs slightly faster even when delegating from the document element. .delegate()s real strength is that you can choose the root element rather than having to bind to the document element: http://api.jquery.com/delegate

like image 32
Jasper Avatar answered Oct 12 '22 22:10

Jasper