pagecontainerbeforechange – How to use it


I have to admit that I just figured out the proper  way to use  pagecontainerbeforechange; previously known as pagebeforechange. Before I explain how to utilize this event, let me tell why it is important and handy.

This event can be used to redirect user from page to another without landing at the requested page. It also can be used to pass parameters between pages (this will be covered in a separate post).

Simply, this event fires twice, emitting four different types of data, prevPage, toPage, options and absUrl.

What are these properties?

  • prevPage: Is a jQuery object of previous page.
  • toPage: First call, it holds a URL of next page (string not an object). Second call, it holds a jQuery object of next page.
  • options: Same arguments of changePage, e.g. transition, changeHash, etc.
  • absUrl: It holds same value of toPage first call.

How to utilize these properties?

Imagine a user login session has expired or has no access to navigate to a page even if it is in DOM, what would you do? return false will ruin Navigation History, pagecontainerbeforeshow will show the page first and then jump to another page. The good thing about pagecontainerbeforechange is that you can either redirect user to URL or to a page in DOM (jQuery object).

How to do it?

First of all, you need to determine which page is being navigated to. At this stage, we can use either absUrl or toPage properties, depending on whether you want to override toPage‘s value with an object or a URL.

In case you want to override changePage, we will use options.

Redirecting to DOM page

To move to a DOM page, we need to override toPage‘s value with an object as well on second call of the event. It is possible to inject a brand new page dynamically if you want.

Demo and Code

$( document ).on( "pagecontainerbeforechange", function ( event, data ) {

    /* all properties shouldn't return "undefined" */
    var toPage = data.toPage,
        prevPage = data.prevPage ? data.prevPage : "",
        options = data.options,
        /* to determine which page (hash) the user is navigating to */
        absUrl = data.absUrl ? $.mobile.path.parseUrl(data.absUrl).hash.split("#")[1] : "",
        /* assuming the user is logged off */
        userLogged = false;

    if ( typeof toPage == "object" && absUrl == "pageX" && !userLogged ) {
        /* if user wants to access pageX but he is logged off
           move to pageY with transition "flip"
           and don't update hash in URL */
        data.toPage[ 0 ] = $("#pageY")[ 0 ];

        $.extend( data.options, {
            transition: "flip",
            changeHash: false
        });
    }
});

Redirecting to URL

The same as previous section but we will override toPage‘s value with an object as well on first call. However, note that the changes in retrieving toPage‘s value from hash to filename – you still can use hash and redirect to a hash. And toPage‘s value is a string not an object.

$( document ).on( "pagecontainerbeforechange", function ( event, data ) {

    /* all properties shouldn't return "undefined" */
    var toPage = data.toPage,
        prevPage = data.prevPage ? data.prevPage : "",
        options = data.options,
        /* to determine which page (filename) the user is navigating to */
        absUrl = data.absUrl ? $.mobile.path.parseUrl(data.absUrl).filename : "",
        /* assuming the user isn't an admin */
        admin = false;

    if ( typeof toPage == "string" && absUrl == "administrator" && !admin ) {
        /* if user wants to access pageX but he is logged off
           move to pageY with transition "flip"
           and don't update hash in URL */
        data.toPage = "http://www.****.net/noaccess.html";

        $.extend( data.options, {
            transition: "flip",
            changeHash: false
        });
    }
});
Advertisements

7 thoughts on “pagecontainerbeforechange – How to use it

  1. Note to anyone using a cordova/phonegap plugin to display native confirmations instead of the standard javascript “confirm()”: Because the plugin calls an onSuccess function rather than returning true/false, it does not stop this “pagecontainerbeforechange” from firing, and thus this event fires and the page changes before the plugin confirmation is shown to the user, resulting in not a little confusion. 🙂 Solution: Use the native confirm() when you need to block execution until an answer is given!

  2. Ah nevermind, I found your page on “redirect on startup” using mobileinit event and it explains why toPage is not a string on initial landing. Awesome.

  3. This post is great! It explains the pagecontainer events much better than JQM’s own documentation.

    Though, I couldn’t get your example to work for my situation, which is I want to redirect to a URL not in the DOM (ajax load) before the current landing page loads. I’m using JQM 1.4.5, where ui.toPage is never a string. It’s always an object. How do I set the target URL of toPage when it’s not a string?

  4. Hi Karl,

    This is true, on first load, “pagecontainerbeforechange” fires twice and returns an object of the page you’re navigating to. Because jQM creates a “fake page” once initialized and then moves to “true page” with “changeHash” set to false.

    At that stage, you should be able to retrieve toPage and options; however, prevPage and absUrl are both undefined.

    Since you’re using a Multi-Page Model, I would recommend listening to “pagecontainerbeforetransition”, it fires one time and returns toPage (object), absUrl, options and prevPage. That’s all what you need for a Multi-Page Model.

    If you want to do URL processing, check my answer and demo here using “pagecontainerbeforetransition”: http://stackoverflow.com/a/26393037/1771795

    And here is a demo of what I have said above: http://plnkr.co/edit/mMHz0wM8RW0LynFFpbBk

    If you have further questions, feel at home 🙂

    Good luck!

    Omar

  5. This post is very helpful, as your others on jQuery Mobile 1.4, so first: thank you!

    I’m trying to follow your example, but I am seeing pagecontainerbeforechange called twice as you describe, but both times toPage is an object, so I’m unable to discriminate between the two events. This is the first page loaded on my site (so there is no url after the hash), and my site is a single html page with multiple div jQM pages.

    As an example, I copied your code and output the four variables you defined to the console:
    toPage: [object Object], prevPage: , options: [object Object], absUrl:
    toPage: [object Object], prevPage: , options: [object Object], absUrl:

    Examining the toPage object shows them to be identical on both calls of the event.

    Any thoughts?

  6. Pingback: jQuery Mobile “Page” Events – What, Why, Where, When & How? | jQuery Mobile Tricks

Drop me a line or two ;)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s