Jquerymobile – $.mobile.changepage

When jQM loads another page through AJAX it only pulls in anything within your div[data-role=”page”] and nothing else, like the head

So you can if you wanted to, include any JS/CSS within this div, the problem is that if this page is accessed multiple times any CSS will accumulate, but the problem is much worse for JS.

You are basically getting every page appended to the DOM, so the JS runs on the entire DOM (every page you loaded) if you use a global selector like $(‘div.someClass’), even using an ID isn’t a perfect solution because if you can link to the same page twice.

For Smaller Sites

I’ve solved this by moving all the CSS into one file and for JS code that I want to run each time the page is loaded, I bind to the pageinit and pageshow jQM events:

<script type="text/javascript">         
$("div:jqmData(role="page"):last").bind('pageinit', function(){
          //your code here - $.mobile.activePage not declared
    });

    $("div:jqmData(role="page"):last").bind('pageshow', function(){
          //your code here - $.mobile.activePage works now
    });
</script>

The pageinit event runs when the page is loaded, only ever once (after it’s loaded it stays in memory if you navigate back to it, even via a back button this isn’t fired again), pageshow on the other hand fires everytime the page is shown, even when you navigate back to it via the back button on the browser for example.

The pageinit runs when the DOM is there, the pageshow event is only if you have some code that depends on the DOM being rendered and you need a quick reference to the active page through $.mobile.activePage or some data changed and you need to refresh this back everytime it’s shown. For most purposes I only use the pageinit as a document.ready for jQM and bind my events there. Use bind for static elements, and on instead of live for dynamic elements, because live events listen at the document root, you want to listen at the page div.

For Larger Sites

For larger sites there are advantages to binding a live event to any pages and handling types of pages, this way js code isn’t loaded more than once.

If you have external js files with say helper functions that you only need once put that in the head of all your pages (if there aren’t too many), if you had a very big site you could probably do better by tracking which JS files have been loaded server side.

All this can be avoided by just not using AJAX to load new pages, so think about whether that transition/loading effect is worthwhile

*Here’s how I handle large jQM sites: *

  1. bind a live event to all pages/dialogs pageinit and pageshow events:

$(document).on('pageinit pageshow', 'div:jqmData(role="page"), div:jqmData(role="dialog")', function(event){

  1. I reference each page with a name: <div data-role="page" data-mypage="employeelist">
  2. In this live event you can basically have a switch statement for each page “name”, and then check event.type for pageinit/pageshow or both and put your code there, then every time a page is created/shown this event will be fired, it knows what page triggered it and then calls the corresponding code

  3. I eventually had too much code, so I built a handler object where each page’s js is included in a separate js file and can register handlers with the live event

The drawback is that all your js for your entire site is loaded on the first page the user reaches, but minified even a large site is smaller than jQuery or jQM so this shouldn’t be a concern. The advantage is you are no longer loading all your JS for each page through AJAX each time the user navigates to a new page.

*note: now RequireJS can make this even more manageable

Leave a Comment