Adding my bindings to the pageinit event like so:
$('#mypage').on("pageinit", function () {
$('#login-sumbit').on('click', function () {
console.log('button clicked');
});
});
I would expect pageinit to bind the click event once only. But what happens in my single page app is that the button is binding every time the page is loaded even when clicking back.
This results in undesirable multiple duplicate binds. Any ideas on what event to use to bind only once in my single page app, so that loading the page again (back button, loading inline page) in the same session doesn't re-bind?
Looks like I found the answer myself, turns out quite rightly pageinit fires every time the page is loaded even though it's not reloading from the server, otherwise what would fire when a new page is shown.
pageinit is the right event but I need to use .one not .on, .one will bind one time only.
$('#mypage').on("pageinit", function () {
$('#login-sumbit').one('click', function () {
console.log('button clicked');
});
});
Now everything works as expected. Better still I've found you can use .one with the pageinit event for even more control over your bindings and data loads perfect for my requirements.
http://api.jquery.com/one/
You could use:
$('#login-sumbit').off('click').on('click', function(e) {
console.log('button clicked');
});
Related
I'm using jquery mobile v1.3.2
For some reasons I want to set an global pagechange event to prepare all of my pages :
var Front = {
initDom : function($dom) {
// here i can bind some events in my page
$(".someButton",$dom).bind("tap",function(){
alert("some actions");
});
// etc.....
});
}
$(document).on("pagechange", function(event, data) {
Front.initDom($(data.toPage));
});
This works well. But it is triggered at each page change. And some times it will init the same event twice and that will lead to some bugs.
Now i have tested to do it with the event pageinit or pagecreate but both are triggered before the page is ready and $("ui-page-active"); is empty.
I have though about some setTimeout, but that's definitively a bad idea.
I have also though to init everything at the first pageinit and unbind it. But ajax called page wont be bound.
It there some good workarround ?
You can use pageinit and then get the id of the page from the event target object:
$(document).on("pageinit", function(e){
alert(e.target.id);
});
DEMO
I fill list dynamically, and after that on click I have multiple calls of event. 1st time it is repeated 1 time, 2nd time 2 times, 3rd time 3 times, etc...
First, more about this problem can be found in my other answer: jQuery Mobile: document ready vs page events
Prevent multiple event binding/triggering
Because of interesting jQM loading architecture, multiple event triggering is a constant problem. For example, take a look at this code snipet:
$(document).on('pagebeforeshow','#index' ,function(e,data){
$(document).on('click', '#test-button',function(e) {
alert('Button click');
});
});
Working jsFiddle example: http://jsfiddle.net/Gajotres/CCfL4/
Each time you visit page #index click event will is going to be bound to button #test-button. There are few ways to prevent this problem:
Solution 1:
Remove event before you bind it:
$('#index').live('pagebeforeshow',function(e,data){
$('#test-button').die().live('click', function(e) {
alert('Button click');
});
});
Working jsFiddle example: http://jsfiddle.net/Gajotres/K8YmG/
In case you have different events bound to an object:
$('#index').live('pagebeforeshow',function(e,data){
$('#test-button').die('click').live('click', function(e) {
alert('Button click');
});
});
Solution 2:
Use a jQuery Filter selector, like this:
$('#carousel div:Event(!click)').each(function(){
//If click is not bind to #carousel div do something
});
Because event filter is not a part of official jQuery framework it can be found here: http://www.codenothing.com/archives/2009/event-filter/
In a nutshell, if speed is your main concern then Solution 2 is much better then Solution 1.
Solution 3:
A new one, probably an easiest of them all.
$(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;
}
});
});
Working jsFiddle example: http://jsfiddle.net/Gajotres/Yerv9/
Tnx to the sholsinger for this solution: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/
More info
If you want to find more about this problem take a look at this article, working examples are included.
I tested on the Apple device, and when I click on the screen when there is no effect. This is my code. Click on the events of this writing there are questions?
<script>
$(function() {
$('#test').tap(function() {
$('#menuNum').text('1');
})
})
</script>
You need to change few things.
Do not use $(function() { or classic document ready to check for a correct state, they can cause problems with jQuery Mobile. Instead use jQuery Mobile alternative called page events.
Then don't bind tap event like that, use proper modern way of doing that. In your case element must be loaded into the DOM for that kind of binding to work. And because of $(function() { sometimes it can happen that element is still loading when binding is executed. So use it like this:
$(document).on('tap','#test',function() {
$('#menuNum').text('1');
});
This method don't care if element exist or not, it will even work if element is loaded into the DOM after binding process.
Working example: http://jsfiddle.net/Gajotres/SQ7DF/
In the end you want something like this:
$(document).on('pagebeforeshow', '#index', function(){
$(document).on('tap','#test',function() {
alert('Tap');
});
});
In my jquery-mobile (1.0RC2) application, I have two pages: test1.html, test2.html
The first page, test1.html, includes an collabsible-set, where I expand one collabsible item via script in the pageinit event listener (tried both pageshow and pageinit):
$('#page1').live( 'pageinit', initPage);
function initPage() {
alert('initPage!'); // this line seems to be always getting executed
$('#my_expandable').trigger('expand'); // ... but this line doesn't when coming back via a back link!
}
This works fine on the first call of the page.
Then I have a link that leads me to the second page test2.html, as follows:
<script>
function goPage2(criteria) {
$('#page1').die( 'pageinit', initPage);
$.mobile.changePage( "test2.html", {reverse: false, reloadPage: true} );
}
</script>
page 2
When I then go back to the first page via
<script>
function goPage1() {
$.mobile.changePage( "test1.html", { reverse: true, reloadPage: true} );
}
</script>
test
only the alert message in the pageinit event listener of test1.html is executed, but the collapsible is not being expanded through the
You can see the sample in action here: http://bit.ly/rr0dq3
How to reproduce the problem:
load test1.html at http://bit.ly/rr0dq3
you will get an alert message, and the collapsible will be expanded
click on the button 'GoTo page2' and you will come to the second page test2.html
on this second page, click on the gray button 'test', and you will come back to the first page test1.html
the problem now: as you can see, the alert command of the pageinit event of test1.html is being executed, but expanding the collapsible isn't - why not? Obviously the pageinit event listener method is being entered properly, but only the collapsible seems to have a problem here.
I think it might be a bug (filed a report here https://github.com/jquery/jquery-mobile/issues/2791), but maybe somebody else has an idea for that.
Workaround:
Both the alert and the collapsible expanding is being executed when I use a different way to to open the second page test2.html, using
window.location.href = "test2.html";
instead of
changePage(...);
But it's not very satisfying. Why does it not work properly if I use the the page injection way? I already call the die() method when I open the different pages in order not to have multiple pageinit event listeners keeping hanging around.
Have you tried using the data-attribute for collapsible content areas that makes them load expanded:
data-collapsed="false"
Here is a link to the docs for this behavior: http://jquerymobile.com/demos/1.0rc2/docs/content/content-collapsible.html
I have a JQuery Mobile Multi-Page layout and I want to trigger a function when a select menu on my site is changed.
Currently when the menu is changed three events fire.
I have put together an example that should show you what i'm facing.
From the main menu click Web Settings
Change the Theme option on the page
Notice the three alerts
Here is my code to register the event
$(document).bind("pagecreate", function() {
$("#settings-theme").bind("change", function(event) {
alert(event.target);
});
});
Things I have tried:
Changing the data-native-menu="false" to true removed one of the event firings.
Removed all other pages except web settings and that also reduced the number of events firing to two.
In JSFiddle, Framework Options > Head (nowrap) changed to DomReady also removed a event fire.
Update
It appears that pagecreate is fired every time a page is 'first-viewed' as well as twice when the homepage is loaded.
So by the time the settings page is loaded the event has been binded three times.. still no solution.
$(document).bind("ready", function() {
$("#settings-theme").live("change", function() {
alert("changed");
});
});
or
$(document).bind("ready", function() {
$("#pg-settings").delegate("#settings-theme", "change", function() {
alert("changed");
});
});