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?
an Event will fire multiple time when it is registered multiple times (even if to the same handler).
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.
jQuery one() Method When using the one() method, the event handler function is only run ONCE for each element.
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() {
// ...
});
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With