properly using jQuery Mobile event handling in version 1.7.1 - jquery-mobile

I am at my wits end with jQuery Mobile events. I do not understand them, despite following the docs to the T. I am using the following code to initialize my pages. The problem is that some seem to fire multiple times and occasionally when I go back to a page nothing will appear, as though .live pageinit simply doesn't fire at all. I am quite confused. Is pageinit the way to go? is .live best practice? Do I need to clean up after myself and use something like pagehide to remove stuff from the DOM? Please help me understand. Thanks!
// page number 1
<header>
includes and stuff
<header>
<body>
<div data-role="page" data-theme="a" id="dashboardPage">
$('#dashboardPage').live('pageinit',function() {
});
// somewhere in here a page transition to anotherPage.html (not necessarily the id of the new page in the <div data-role-"page data-theme...> declaration
$.mobile.changePage("anotherPage.html",{transition : "slide"});
</div>
</body>
// page number 2
<header>
includes and stuff
<header>
<body>
<div data-role="page" data-theme="a" id="specialsPage">
$('#specialsPage').live('pageinit',function() {
});
</div>
</body>

You could try something like this:
<html>
<header>
<!-- BASIC INCLUDES -->
<link rel="stylesheet" href="./css/jquery.structure-1.1.0.min.css" />
<link rel="stylesheet" href="./css/jquery.mobile-1.1.0.min.css" />
<link rel="stylesheet" href="./css/jquery.mobile.theme-1.1.0.min.css" />
<script type="text/javascript" src="./js/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="./js/jquery.mobile-1.1.0.min.js"></script>
<!-- END - BASIC INCLUDES -->
</header>
<body>
<!-- PAGE 1 -->
<div data-role="page" data-theme="a" id="dashboardPage">
<script>
// INITIALIGE PAGE 1 - dashboardPage
$("#dashboardPage").live('pageinit',function(event){
alert( '"initializing" page 1: dashboardPage');
});
</script>
HERE YOU ARE AT PAGE 1 (dashboardPage)!!!<br><br>
CLICK HERE TO GO TO PAGE 2 (specialsPage)
</div>
<!-- PAGE 2 -->
<div data-role="page" data-theme="a" id="specialsPage">
<script>
// INITIALIGE PAGE 2 - specialsPage
$("#specialsPage").live('pageinit',function(event){
alert( '"initializing" page 2: specialsPage');
});
</script>
HERE YOU ARE AT PAGE 2 (specialsPage)!!!<br><br>
CLICK HERE TO GO TO PAGE 1 (dashboardPage)
</div>
</body>
</html>
Hope it helps.

When using JQuery mobile you should consider you have a single page which content is updated dynamically. You do not navigate from one page to the other as you normally would.
Because of this, any code present in a page you navigate to with JQM simply be ignored (tyr changing the header of page number 2, and navigate to this page from page number 1 with changepage, you will not see any difference).
Because of that, all your js code should be directly available within the page in which your user will arrive.
If you add the following code in the scripts of page 1, you will proeperly detect the initialization of of page2 when it is loaded with changepage.
$("#specialsPage").live('pageinit',function(event){
alert( '"initializing" page 2: specialsPage');
});
An important thing to keep in mind is that you user might also directly access your page2, which means that all the code should also be available for page 2. Because of this I would strongly recommend including all your code in a js file referenced in the headers of all your page, and NOT directly in script tags within your pages.

Related

jQuery mobile - Multiple page loads on change page

I am using a multiple page format with a persistent header. I can successfully change page either with a straight hyperlink or using $(':mobile-pagecontainer').pagecontainer('change'
The code works fine but it seems to "load" the page an additional time each time I click on the buttons to change page.
In this code the button changes the page and outputs a console.log message.
On click I would expect the page to change and to see one "#btn - page x" console.log message.
What happens is the page changes and I get a console message for each time I've loaded the page, not just one.
Even though my code is working, this can't be right - this will just go up and up with normal user usage.
What am I not understanding here?
I've created a jsfiddle to show what I mean. For example, if I click the "goto page x" button 6 times (that's 3 times for each page), I get an output of 3 "#btn - page x" messages, not just one.
Same with the header button - each time I change the page, number of responses from the header button goes up.
the html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>problem</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<div data-role="header" data-position="fixed" data-theme="a">
header button
</div>
<div data-role="page" id="page1" data-title="Page 1">
<div data-role="content">
<h1>I am page 1</h1>
goto page2
</div>
</div>
<div data-role="page" id="page2" data-title="Page 2" data-theme="b">
<div data-role="content">
<h1>I am page 2</h1>
goto page1
</div>
</div>
<script src="problem.js"></script>
</body>
</html>
and the js:
$(document).on('pagebeforeshow','#page1',function(){
console.log('#page1 pagebeforeshow');
$('#btntest1').click(function(){
console.log('#btn - page1');
//$(':mobile-pagecontainer').pagecontainer('change', '#page2', { reloadPage: false});
});
});
$(document).on('pagebeforeshow','#page2',function(){
console.log('#page2 pagebeforeshow');
$('#btntest2').click(function(){
console.log('#btn - page2');
//$(':mobile-pagecontainer').pagecontainer('change', '#page1', { reloadPage: false});
});
});
$(function() {
$("[data-role='header']").toolbar();
});
$(document).on('pagebeforeshow',function(){
console.log('pagebeforeshow');
$('#headerbtn').click(function(){
console.log('headerbtn click');
});
})
UPDATE:
So I've been trying all sorts of things to try to fix this, including removing data-rel="back", trying data-ajax="false" (which defeats the point of what I'm trying to do), changing page with
$(':mobile-pagecontainer').pagecontainer('change', '#page2');
or
$(':mobile-pagecontainer').pagecontainer('change', '#page2', { reloadPage: false});
but no joy. Obviously, I've tried googling but can't find anything to help.
In the full app code the buttons communicate with a database, so as the clicks increase, I'm sending and retrieving the same data to the db multiple times on each click.
I really would appreciate some guidance if anyone has any ideas what I could do?
The problem is that each time you're entering the page, you are binding a listener on the element again. So you're binding multiple listeners. The listener should not be written inside the pagebeforeshowhandler.
Take it out like this:
$(document).on('pagebeforeshow','#page1',function(){
console.log('#page1 pagebeforeshow');
});
$('#btntest1').click(function(e){
e.preventDefault();
console.log('#btn - page1');
$(':mobile-pagecontainer').pagecontainer('change', '#page2', { reloadPage: false});
});
And for page 2 likewise.

JqueryMobile loading external script in body does not solve my ajax navigation issue

I see some others (e.g. this post) have had trouble using external javascript scripts in JQuery Mobile - as of today I have joined their ranks.
I have a single external js script (controllers.js) which contains code that affects several pages on the site. It is loaded on every page of the site. I put the js file just before the tag it works fine on the initial page load. However when I navigate thereafter (using the JQM Ajax methods) all functions in the script stop working. I would have thought the script would remain in cache - but heyho. Anyhow there's an FAQ which answers this question and I've implemented their suggestion which is: "...to reference the same set of stylesheets and scripts in the head of every page." I have done this but when I do even on the first page load the js doesn't fire. There aren't page specific scripts - so the remainder of that FAQ does not apply.
My cut down html looks like this:
<!doctype html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="/static/jquery-ui-1.10.3.custom.min.css">
<link rel="stylesheet" href="/static/jquery-mobile/css/themes/default/jquery.mobile-1.3.2.min.css">
<script src="/static/jquery-1.9.1.min.js"></script>
<script src="/static/jquery-ui/jquery-ui-1.10.3.custom/js/jquery-ui-1.10.3.custom.min.js"></script>
<script src="/static/jquery-mobile/js/jquery.mobile-1.3.2.min.js"></script>
<!-- CSS: implied media="all" -->
</head>
<body>
<div data-role="page" id = "main-page">
<div data-role="header" style="overflow:hidden;">
</div>
<div id = "home" data-role="content">
<input type ='button' id = "some_btn" value="press me">
</div>
</div>
<script type="text/javascript" src="/static/js/controllers.js"></script>
</body>
</html>
and within the javascript file
controllers.js
$('#some_btn').click(function()
{
alert('button pressed');
});
Any ideas on what I may be doing wrong here?
Since the content in the #page is loaded dynamically via ajax, click will not work, since it only works on elements that are on the page when the script is called.
You need to use the .on() method:
$('body').on('click','#some_btn',function()
{
alert('button pressed');
});

jquery mobile splash screen with javascript

I'm seeking to avoid using this for the splash screen, because it does not work on all devices and for other reasons:
<link rel="apple-touch-startup-image" href="img/splash.png" />
So I'm trying to use this instead and it works fine until it slides into a new page, which is then treated like the splash screen again (e.g. it goes blank when the timer expires - in this case 4 seconds). How can I stop/restrict this behavior, so that changePage remains contained in splash page only?
<body>
<div data-role="page" id="splash">
<div class="splash">
<img src="startup.jpg" alt="startup image" />
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$(function() {
setTimeout(hideSplash, 4000);
});
function hideSplash() {
$.mobile.changePage("#home", "fade");
}
});//]]>
</script>
</div>
</div>
<div data-role="page" id="home">
<div data-role="header" data-backbtn="false">
<h1></h1>
</div>
<div data-role="content">
</div>
</div>
</body>
Good idea here is what I'm thinking. Use single pages instead of multi page(multiple data-role=page). For index.html or index.php or whatever. Put your splash page. The reason for this I will explain later on.
index.html
<head>
<!-- First include all jquery stuff -->
<script src="app.js"></script><!-- external script because we can just include it in every page -->
</head>
<body>
<div data-role="page" id="splash">
<div class="splash">
<img src="startup.jpg" alt="startup image" />
</div>
</div>
</body>
app.js
$(document).on('pageinit','#splash',function(){ // the .on() method does require jQuery 1.7 + but this will allow you to have the contained code only run when the #splash page is initialized.
setTimeout(function(){
$.mobile.changePage("home.html", "fade");
}, 4000);
});
Ok so I did it this way because lets say you have navigation menu and you want to send people back to home page. You won't have to show the splash page again. You can just link to home.html. Also splitting up your pages helps keep the dom leaner. I hope this helps.
<link rel="apple-touch-startup-image" href="img/splash.png" />
Is indeed only for apple mobile devices.
A real splashscreen should only be there to show you a nice picture while you're waiting. Its goal is not to make you wait for real reason. In your case it's taking 4seconds out of the life of your users just to make it look cool.
I have modified your code and put it in this jsfiddle : you'll see it works now. For the splashscreen to take the full width/height edit the css to remove the margins. I've set the timer to 2s, that's more than enough I think.

jQueryMobile script runs twice on each pageload

I've been trying to get a script that inserts a div of text after the first and second paragraph of an article to work in jQueryMobile. It works on the first pageload, but on the second it loads the content twice, and the third time it's loaded three times, and so on.
The jQueryMobile libraries and my script is loaded in the head:
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="myscript.js">
<script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
Then I have
<body id="mobile">
<div id="wrapper" data-role="page">
And then the content of the page
My script is executed as documented on jquerymobile.com
$("#wrapper").live('pageinit', function() {
Am I missing something? Any help will be deeply appreciated.
try adding data-dom-cache="false" it should look like this
<body id="mobile">
<div id="wrapper" data-role="page" data-dom-cache="false">
As Clarence commented, a better solution is to move the <script> tag outside of the <div> with data-role="page"
<body id="mobile">
<div id="wrapper" data-role="page">
<!-- stuff -->
</div>
<script>
$("#wrapper").live('pageinit', function() {
// more stuff
});
</script>
</body>

Very weird behavior of $.mobile.changePage in a very simple jQuery Mobile page

I'm writing a Html 5 application for mobile devices using jQuery mobile (and Phonegap, but the following is device independent), using one html page that contains various <div data-role="page"... > elements as subpages. To change between one subpage and another I use $.mobile.changePage. Everything works well unless I place a div tag into one of the <div data-role="content"> containers!
Working example:
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.mobile.changePage($('#page2'), {
transition : 'slideup',
reverse : false,
changeHash : true
});
});
</script>
</head>
<body>
<div data-role="page" id="page1" data-theme="a">
<div data-role="content">
Page1
</div>
</div>
<div data-role="page" id="page2" data-theme="a">
<div data-role="content">
Page2
</div>
</div>
</body>
</html>
Now, after adding something as simple as a closed div tag behind Page1
Page1 -> Page1<div />
$.mobile.changePage still fires - one can see the page2 content for a second - but then shows a blank screen.
This happens in desktop browsers as well as in a smartphone (using Phonegap and adjusting the code).
I really appreciate any kind of idea or hint. Narrowing down this problem and making it reproducible alone cost me hours a valuable livetime because it seemed to unlikely....
Change
Page1<div />
to
Page1</div>
...
Page1<div>test</div>
works too.
Not sure why jqm is having a problem with the trailing / on the empty div.

Resources