I included an external javascript file on a jquery mobile page. The javascript file modifies some html and css snippet generated at the server. I've tried putting the jquery code that modifies the markup in the following jquery mobile events -
pageinit, pagecreate, pageshow, pagebeforecreate
But the script doesn't modify the loaded markup on page load, but on page refresh, it works perfectly. So I'm trying to find a way to make the modification take place before the page renders.
Any suggested will be gratefully valued.
I've solved my problem. I included all the external javascript and css files on the index page, and it worked well.
This is because jquery mobile loads subsequent pages through ajax, after loading the first page.
Related
I have used $.mobile.changepage to do the redirect in my phonegap+jquerymobile projects. However what makes me confused is that I need to put the script of all the pages to the same file index.html. If not, the redirect page can not execute the function in its header.
for example, my index.html seem to be
$(document).bind("deviceready",function(){$.mobile.changepage("test.html");})
then, my device will redirect to test.html which seem to be
$("#btnTest").click(function(){alert("123");})
<button id="btnTest">Test</button>
However, the script will never execute in test.html. Then I put the script to index.html, what I expect to be is done. Whatever, if I put all the script to the same page, the project will become harder and harder to be preserved. Appreciated for your help.
Intro
This article can also be found HERE as a part of my blog.
How jQuery Mobile handles page changes
To understand this situation you need to understand how jQuery Mobile works. It uses ajax to load other pages.
First page is loaded normally. Its HEAD and BODY is loaded into the DOM, and they are there to await other content. When second page is loaded, only its BODY content is loaded into the DOM. To be more precise, even BODY is not fully loaded. Only first div with an attribute data-role="page" will be loaded, everything else is going to be discarded. Even if you have more pages inside a BODY only first one is going to be loaded. This rule only applies to subsequent pages, if you have more pages in an initial HTML all of them will be loaded.
That's why your button is show successfully but click event is not working. Same click event whose parent HEAD was disregarded during the page transition.
Here's an official documentation: http://jquerymobile.com/demos/1.2.0/docs/pages/page-links.html
Unfortunately you are not going to find this described in their documentation. Ether they think this is a common knowledge or they forgot to describe this like my other topics. (jQuery Mobile documentation is big but lacking many things).
Solution 1
In your second page, and every other page, move your SCRIPT tag into the BODY content, like this:
<body>
<div data-role="page">
// And rest of your HTML content
<script>
// Your javascript will go here
</script>
</div>
</body>
This is a quick solution but still an ugly one.
Working example can be found in my other answer here: Pageshow not triggered after changepage
Another working example: Page loaded differently with jQuery-mobile transition
Solution 2
Move all of your javascript into the original first HTML. Collect everything and put it inside a single js file, into a HEAD. Initialize it after jQuery Mobile has been loaded.
<head>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=no; target-densityDpi=device-dpi"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="index.js"></script> // Put your code into a new file
</head>
In the end I will describe why this is a part of a good solution.
Solution 3
Use rel="external" in your buttons and every elements you are using to change page. Because of it ajax is not going to be used for page loading and your jQuery Mobile app will behave like a normal web application. Unfortunately this is not a good solution in your case. Phonegap should never work as a normal web app.
Next
Official documentation, look for a chapter: Linking without Ajax
Realistic solution
Realistic solution would use Solution 2. But unlike solution 2, I would use that same index.js file and initialize it inside a HEAD of every possible other page.
Now you can ask me WHY?
Phonegap like jQuery Mobile is buggy, and sooner or later there's going to be an error and your app will fail (including loaded DOM) if your every js content is inside a single HTML file. DOM could be erased and Phonegap will refresh your current page. If that page don't have javascript that it will not work until it is restarted.
Final words
This problem can be easily fixed with a good page architecture. If anyone is interested I have wrote an ARTICLE about good jQuery Mobile page architecture. In a nut shell I am discussing that knowledge of how jQuery Mobile works is the most important thing you need to know before you can successfully create you first app.
Unlike normal ordinary HTML pages, jQuery Mobile uses ajax technology when navigating between pages. So make sure to import all your JS files and libraries in all your html pages.
If you notice closely you will see that JS files from previous page is taken into consideration when loading the second page. But if you force rrefresh the current page then the js files of the current page will be effective.
So as I said earlier make sure to import the js files in all the html files.
Also no need to call deviceready, use following syntax to call your page specific js functions
$(document).on('pageshow', '#YourPageID', function(){
// Your code goes here
});
Jquery Mobile uses ajax to load a "page". A "page" here is a div with data-role=page. If you load a physical page index.html, you can navigate using changePage to any "page" div inside that page.
However, if you want to load a "page" from other physical page, jQM will only load the first "page" div from that page. What actually happen is you do not change page, jQM just load that particular "page" div using ajax and inject it to your current page.
You have two possible architecture where you put all your "pages" in a html page and navigate from there. Or you can have multiple page architecture. You can always mix this.
To physically change page, you need to add rel=external to your link.
I have one larger .js file loaded in the head of the app. entry point (index.html) instead of loading page-specific scripts inside their data-role="page" div.
So i have all the page specific scripting in one js that is loaded once from the index.html which always remains in the DOM.
So for example i have handlers like:
$(document).on('pageshow', '#page_Albums', function()
{
// code for the albums.html page
});
..etc
This is my problem:
When you start navigating the app everything is okey until you hit f5 or browsers refresh button.
This so called full-refresh won't load my central js file, also the needed jquery-mobile resources from the head of index.html (js & css) are lost.
Due to this it's obvious where the problem lies. When i hit refresh from index.html then everything works fine.
How to fix this?
thx
On the navigation links try use data-ajax="false" it will re-command your js...
For example,
<a href="#xyz" data-ajax="false>Link</a>
I am following Ray Camdens post on ajax calls in coldfusion. I have the whole page wrapped with jquerymobile and themeroller. If I put the content on the main page, its styled properly, but if I use ajax to return the content, its unstyled.
I have tried including jquery and jquerymobile scripts in the ajax page, but then I end up getting weird loops and double submit buttons. In firebug I can see that it loads the js files in the ajax return. I also loose my focus on the submit button which is a big deal in this particular app.
Is there a way to only have the jquery a jquery mobile js files linked in the main page and then have the styling refresh after the ajax content is loaded? or will i run into a FOUC?
Fixed. used $("#result").html(data).trigger("create"); as mentioned in the comments on this page
In jqueryMobile, only the first page section seems to be loaded. When the user is redirected to a second page, the of that page is added to the first page, no headers are loaded.
If that is correct, how do we manage CSS files in jQueryMobile? Do I need to specify ALL the website classes in just one file? or is there any way to tell jquerymobile to load the css required for each page?
Thanks!
jQuery Mobile will hijax all the links on the page by default, loading the content via ajax, and only add the <body> of the response to the DOM. So, yes the easiest way is to load your required CSS up front in the first page. Bundle it and minify it to reduce the impact on the client.
I have 2 application layouts: application.html.haml and application.mobile.haml. But when I switch from mobile to the non-mobile version the mobile layout is still used for the first load. In Firebug console I see that the non-mobile view was properly returned, however the browser and the Firebug HTML tab show the mobile layout. Any idea what's going? It's fine after a refresh.
The issue turned out to be caused by JQuery Mobile.
I found the answer here: http://jquerymobile.com/demos/1.0a3/docs/pages/docs-pages.html
JQuery Mobile doesn't do full page reloads unless it's told to, so although the full html was returned, JQuery Mobile just replaced the page portion.
The key portion from the docs is:
"It's important to note if you are linking from a mobile page that was loaded via Ajax to a page with multiple internal pages, you need to add a rel="external" or data-ajax="false" to the link. This tells the framework to do a full page reload to clear out the Ajax hash in the URL. This is critical because Ajax pages use the hash (#) to track the Ajax history, while multiple internal pages use the hash to indicate internal pages so there will be a conflicts."
Recently, I encountered a similar problem.
In my case, Rails4's turbolinks suffered. Similarly as JQuery Mobile, turbolinks only updates the body part of a full page without updating the head part of the html when an intra-site link is clicked. I simply removed the require line for turbolinks in my application.js and the problem disappeared.