Pre-render JQM pages in the background - jquery-mobile

I have a mobile web app built with jQuery Mobile. It is using a multi-page template, with most of the content being created dynamically with javascript. The first time the app is loaded it shows a splash screen and then sends the user to an "index" page. From there the user can navigate to different parts of the app via # links. Each page's content is created dynamically with javascript and then inserted into the DOM on the "pageshow" event.
This works very well with one little problem that I haven't been able to solve. The first time a page is loaded it takes several seconds for the content to be generated and inserted into the DOM. Subsequent loads are fine since the previously rendered content is already in the DOM and is only replaced if there is new data. What I want to do is pre-render each page's DOM so that there is no noticeable delay when a page is loaded for the first time. I can achieve this by calling $.mobile.changePage() on each page. The problem is that I want this to be done in the background without the pages or any page transitions being shown to the user. Is there any way to do this?
P.S.: Worst-case scenario, I'd just keep the splash screen on top of everything while the pages are pre-rendered, but I can't even do this since JQM does the transition and changes the page whenever I call $.mobile.changePage().

All you have to do is use the $.mobile.loadPage. In the example below I show how to initialize a single page by hash URL upon the showing of #one. You could list out all of them if you wanted or create a fancy script to find all the [data-role] elements that do not have a class of ui-page, grab it's ID, and call a load on in the same way I have here.
$("#one").live("pageshow",function(){
$.mobile.loadPage("#two");
});
You can see the example in action on this jsfiddle..

I stumbled upon your question since I was looking into somewhat the same issue. What I ended up with is a _preloadPages() function in my project basically instantiating the page widgets which normally are done internally. Since this is not documented please keep in mind this can break anytime when upgrading JQM.
To control which pages to preload and which not I've introduced a class 'preload' which I place on the page containers I want to preload. This _preloadPages() function I call during splash screen and to not stress the initialization of my app to much the preloading is done in a 300ms interval. Still playing with these numbers though.
function _preloadPages()
{
// Execute the page() widget call on all pages that haven't yet been initialized, we do this
// to prevent a slight delay when initially loading a page
//
var $pages = $( "[data-role='page'].preload:not(.ui-page)" )
, index = 0
, pageCount = $pages.length
;
var preloadTimer = setInterval( function()
{
var page = $pages[ index ]
, $page = $( page )
;
$page.page();
index++;
if ( index === pageCount )
{
clearTimeout( preloadTimer );
}
}, 300 );
}

Related

Previously visited pages are continually added to the background

As I click through my JQM site the page i visit is fine and I click through to the next and that is fine but displayed underneath is the previous page, and not only, as I keep visiting pages the previous pages keep getting added to this second, 'background' layer. (at the bottom, even twice if i visit the page twice!)
Why is this occuring? What settings have I not set properly? Is it related to cache or pageremove?
Notes
It is version 1.4 (latest stable JQM)
All new pages are accessed via SUBMIT (ie from a form) not links
All pages except the index are dynamic php pages
If you feel any particluar part of the code that is being used now is relevant, let me know, but i doubt it is.
Jquery Mobile removes pages as it keeps updating the DOM, except in two cases.
1 All pages that are referenced directly, eg the index/arrival page (ist page loaded), are NOT removed (the doctype and head are kept you see).
2 All pages that are loaded via AJAX are removed, except FORMS.
So a site that navigates via forms will not have the pages removed.
So pages that are forms should be removed by inserting a new page. In effect reloading the jquery mobile. So doctype, head etc need to be included, as if each page is a landing page.
How to make a form create a new page?
use
data-ajax="false"
in the form properties.
Downside:
Now you are basically leaving the jqm structure you will not be able to use the nice loading page spinning wheel...
Added advantage
This does mean that external js files are reloaded directly too
If there is a solution which also allows the site to 'stay inside' JQM please post and I will accept it as the answer.
try setup your jquery mobile using this setting
$(document).bind("mobileinit", function() {
$.mobile.ajaxEnabled = false;
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
// Remove page from DOM when it's being replaced
$('div[data-role="page"]').live('pagehide', function(event, ui) {
$(event.currentTarget).remove();
});
});
check my sample code here: https://github.com/datomnurdin/service-finder-mobile

jQuery mobile finds elements from first page when on second page

I've got a two page jQuery mobile app, and within the init function, the following code..
Call to the init function
$(document).on('pageinit', function(){
MyPages.init();
});
init: function() {
$('td[id$="drops"]').each(function() {
console.log("Element: " + $(this).attr('id'));
}),
};
I have elements in page one that match the above, such as '#early_drops', '#late_drops', etc. These elements do not exist on page 2, but when page 2 loads, the elements are displayed in the console just like when page 1 is loaded. What am I missing here?
Thanks very much,
-Adam vonNieda
By default jQuery loads pages using AJAX into the existing page in order to allow the animated transitions. If you don't want this you just need to 'turn off' the AJAX loading.
See description here: http://view.jquerymobile.com/1.3.2/dist/demos/widgets/links/
Links that point to other domains or that have rel="external", data-ajax="false" or target attributes will not be loaded with AJAX. Instead, these links will cause a full page refresh with no animated transition. Both attributes (rel="external" and data-ajax="false") have the same effect, but a different semantic meaning: rel="external" should be used when linking to another site or domain, while data-ajax="false" is useful for simply opting a page within your domain from being loaded via AJAX.
You can also disable AJAX across the entire app by default using global configuration: http://api.jquerymobile.com/global-config/

Custom changePage on jquery mobile causes c.data("page") is undefined on second call

I'm trying to build some custom navigation in a dynamic application, all screens are obtained from the server and thus I registered the pagebeforechange event and execute my own function.
Everything works as I expected except when I refresh the data I destroy the dynamic pages and try to call the page I was in again using the page Id, but this second time, although my code creates the HTML for the page, jQuery Mobile throws an "c.data("page") is undefined" error.
I bind the pagebeforechange event:
$(document).bind('pagebeforechange', function(e, data) {
if(typeof data.toPage === 'string') {
appobj.dynamicPage(data.toPage, data.options);
}
});
Then in the dynamicPage method I create the HTML for my page based on Underscore.js templates and let jQuery continue changing the page:
$.get('templates/page.tpl.html', function (data) {
html = _.template(data, { /* several template parameters */});
});
page = $(html);
page.appendTo('body').page();
The idea was to use as much of jQM as possible since I'm creating the destination page and injecting it into the DOM.
When I need to update the supporting data, that I store in localStorage, I just find all dynamic pages and destroy them:
var current = $.mobile.activePage.attr('id');
$('.dynamicpage').remove();
$.mobile.changePage('#' + current
When running the application I can easily navigate between various screens/pages, even for pages that don't exist when the application starts but if the data needs to be updated (because the user added elements in the application of data in the database changed) then the removal code is executed but the old page is not regenerated ending in a white page with all the DOM contents hidden, but the page I wanted to navigate too seems to be in the DOM (at least firebug tells me so).
If I were to restart development I would probably use Backbone.js to handle my model updates and view changes but for now I'll have to use only jQM. Any suggestions? I understand that jQM is not finding my page but I don't see why since my event should be called and the page regenerated, even with the allowSamePageTransition flag set.
Regards,
Sérgio Lopes

how can I call data when jQueryMobile page changed

Im building a browser-based app by jQueryMobile and facing a problem: Now I have a single HTML contains multiple "data-role=page" sections each of them will call backend to grab content once activated.
$('body').bind('pagechange',function(event){
//grab content base on page id here, working!!!
});
However, if user reload the page by press "refresh" button on browser how can I detect and call backend page?
Thanks
Use the pageshow event. Something like this:
$("[data-role=page]").live('pageshow',function(event, ui){
var myId = $.mobile.activePage.attr('id');
// do something
});

jQuery Mobile Page refresh mechanism

I'm having a lot of pain understanding how jQuery Mobile handles pages refresh after an ajax update.
I'm having a two pages - unique file site: a search engine.
First page is a search field. Submit triggers a JSON call and parser which updates the second page: results.
for now i'm using: $.mobile.changePage( $('#result') ); which does the job great from search field to result page.
However:
If I reuse it from result page for next/prev pages ( new json call, new parse, new added nodes in the DOM );
Jquery Mobile just don't "paint" the newly added nodes.
can anyone explain, please the use and distinction of
1- $.mobile.page()
2- $.mobile.changePage()
3- $.mobile.refresh()
or give me a hint on how I should handle page changes.
thanks!
function refreshPage()
{
jQuery.mobile.changePage(window.location.href, {
allowSamePageTransition: true,
transition: 'none',
reloadPage: true
});
}
Taken from here http://scottwb.com/blog/2012/06/29/reload-the-same-page-without-blinking-on-jquery-mobile/ also tested on jQuery Mobile 1.2.0
Please take a good look here: http://jquerymobile.com/test/docs/api/methods.html
$.mobile.changePage() is to change from one page to another, and the parameter can be a url or a page object. ( only #result will also work )
$.mobile.page() isn't recommended anymore, please use .trigger( "create"), see also: JQuery Mobile .page() function causes infinite loop?
Important:
Create vs. refresh: An important distinction
Note that there is an important difference between the create event and refresh method that some widgets have. The create event is suited for enhancing raw markup that contains one or more widgets. The refresh method that some widgets have should be used on existing (already enhanced) widgets that have been manipulated programmatically and need the UI be updated to match.
For example, if you had a page where you dynamically appended a new unordered list with data-role=listview attribute after page creation, triggering create on a parent element of that list would transform it into a listview styled widget. If more list items were then programmatically added, calling the listview’s refresh method would update just those new list items to the enhanced state and leave the existing list items untouched.
$.mobile.refresh() doesn't exist i guess
So what are you using for your results? A listview? Then you can update it by doing:
$('ul').listview('refresh');
Example:
http://operationmobile.com/dont-forget-to-call-refresh-when-adding-items-to-your-jquery-mobile-list/
Otherwise you can do:
$('#result').live("pageinit", function(){ // or pageshow
// your dom manipulations here
});
I posted that in jQuery forums (I hope it can help):
Diving into the jQM code i've found this solution. I hope it can help other people:
To refresh a dynamically modified page:
function refreshPage(page){
// Page refresh
page.trigger('pagecreate');
page.listview('refresh');
}
It works even if you create new headers, navbars or footers. I've tested it with jQM 1.0.1.
I found this thread looking to create an ajax page refresh button with jQuery Mobile.
#sgissinger had the closest answer to what I was looking for, but it was outdated.
I updated for jQuery Mobile 1.4
function refreshPage() {
jQuery.mobile.pageContainer.pagecontainer('change', window.location.href, {
allowSamePageTransition: true,
transition: 'none',
reloadPage: true
// 'reload' parameter not working yet: //github.com/jquery/jquery-mobile/issues/7406
});
}
// Run it with .on
$(document).on( "click", '#refresh', function() {
refreshPage();
});
I solved this problem by using the the data-cache="false" attribute in the page div on the pages I wanted refreshed.
<div data-role="page" data-cache="false">
/*content goes here*/
</div>
In my case it was my shopping cart. If a customer added an item to their cart and then continued shopping and then added another item to their cart the cart page would not show the new item. Unless they refreshed the page. Setting data-cache to false instructs JQM not to cache that page as far as I understand.
Hope this helps others in the future.
This answer did the trick for me http://view.jquerymobile.com/master/demos/faq/injected-content-is-not-enhanced.php.
In the context of a multi-pages template, I modify the content of a <div id="foo">...</div> in a Javascript 'pagebeforeshow' handler and trigger a refresh at the end of the script:
$(document).bind("pagebeforeshow", function(event,pdata) {
var parsedUrl = $.mobile.path.parseUrl( location.href );
switch ( parsedUrl.hash ) {
case "#p_02":
... some modifications of the content of the <div> here ...
$("#foo").trigger("create");
break;
}
});

Resources