7

jQuery Mobile v1.4, we are february 2014.

So, I've read here (gihub) that we are supposed to make an if statement on catched pagecontainer events to assume if the page loaded is the one intended.

Here is a little scenario trying to understand the intended behavior of the new pageContainer widget and it's intended use.

Simple as that, a login page, pre-fetch a welcome page programatically, then switch to welcome page on succesful login. Welcome page have some JS script to animate the page, must be launched only when page is visible. How do we do that ?

Here are the results I got while investigating the pagecontainer events through the console. My goal here is to find a way to detect that my welcome (any page in fact) page is active/visible.

I used this format as query for the sake of understanding:

$( 'body' ).on( 'pagecontainerbeforeload', function( event, ui ) {
    console.log("beforeload");
    console.log(event);
    console.log(ui);
});

So fresh start, when I load a page & JQM for the first time (ie. /Users/login)

Events usable :

  • pagecontainercreate => empty ui
  • PCbeforetransition => ui.toPage usable
  • PCshow => only get a ui.prevPage (which is empty in that case)
  • PCtransition => ui.toPage usable

Now, these are always launched even if you disabled the transition effects ( See api )


Ok, then I want to programatically load a page (pre-fetch it), I do : (I want /Users/welcome)

$("body").pagecontainer("load", "/Users/welcome");

I get these event launched (the page is not yet visible):

  • PCbeforeload => I get a url which I could use to identify the page..
  • PCload => pretty much the same data as PCbeforeload

All right, now I go change my page : (to /Users/welcome)

$("body").pagecontainer("change", "/Users/welcome");

I get these events triggered:

  • PChide => ui.nextPage is the same as a ui.toPage...
  • PCbeforetransition => ui.toPage usable
  • PCshow => only gives ui.prevPage
  • PCtransition => ui.toPage present as expected

Fine, now I'm pretty sure the only pagecontainer event I want to use to be sure that this page is loaded is pagecontainertransition. Here is what I implemented on every page that needs to launch JS :

Set id of the page container (PHP)

<div data-role="page" data-theme='a' id="<?php echo $this->id_url()?>">

...at the end of the page (JS)

$( 'body' ).on( 'pagecontainertransition', function( event, ui ) {
    if(ui.toPage[0] == $('#'+id_url )[0] ) {
        functionToLaunchWhenPageShowUp();
    }
} );        

Now, as you can see, I'm referring to ui.toPage 1st child [0] to compare it to $('.selector') 1st child [0] . Is that the right way to do that ? I mean, the intended way by the new API. Thanks to share your knowledge ;)

DColl
  • 185
  • 2
  • 14
  • I opened this [ticket](https://github.com/jquery/jquery-mobile/issues/6865) after announcing that `pageshow` is deprecated. There's no right or wrong way, it depends on you. e.g. when do you want to execute functions and for which pages. Unfortunately, `pagecontainer` events can only be bound to document. – Omar Feb 04 '14 at 09:26
  • I want a global method, the intended one, to launch code specific to a page, when this page is activated. Actually, my last formula isn't working while navigating, first page will load ok, but second/3rd... will keep the first functionToLaunchWhenPageShowUp() :/ – DColl Feb 04 '14 at 10:15
  • you to run `ToLaunchWhenPageShowUp()` once per page, or whenever page is shown no matter how many times? – Omar Feb 04 '14 at 10:22
  • Maybe if I call that function functionToLaunchWhenPageShowUp_PageID(), it would be better to see ^^ Anyway, I want "something" to be launched every time the page is activated (i'll control if it's already been loaded elsewhere) – DColl Feb 04 '14 at 11:09
  • note that `pagebeforeshow` isn't deprecated so you can use it as well as bind it to page id. – Omar Feb 04 '14 at 11:12
  • Do you have a concrete example, or a link on how to use this in a descriptive way ? I got the feeling these events we're all gonna get deprecated, most of what I could read on the api were pointing to that pageContainer widget. Who knows. – DColl Feb 04 '14 at 12:26
  • check my answer here http://stackoverflow.com/a/20459433/1771795 if you need more explanation, i'll write an answer. – Omar Feb 04 '14 at 12:39

1 Answers1

6

I managed to do something that works, is relatively simple, and as close I could to the DRY principle (don't repeat yourself).

In the order they are "loaded" :

JS script in < head > of document

<script type="text/javascript" src="/js/jquery-2.1.0.min.js"></script>
<script type="text/javascript">
  (function(){
  //Global settings for JQM 1.4.0
  $( document ).on( "mobileinit", function() {
        //apply overrides here
         $.mobile.defaultPageTransition = 'flip'; 
  });
  // The event listener in question !
  $( document ).ready(function () { //..only launched once the body exist
    // The event listener in question :
    $( 'body' ).on( 'pagecontainertransition', function( event, ui ) {
        //gets the id you programatically give to your page
        id_url = $( "body" ).pagecontainer( "getActivePage" )[0].id;
        //compare the actual event data (ui.toPage) 
        if( ui.toPage[0] == $('#'+id_url )[0] ) {
            // failsafe
            if ( typeof( window[ id_url ].initPage ) === "function" ) {   
                // call the dynamically created init function
                window[ id_url ].initPage();
            }
        }
    } );
  });

  document.loadPage = function( url ){
    $( "body" ).pagecontainer( "load", url  , options);
  };
  document.changePage = function( url ){
    $( "body" ).pagecontainer( "change", url  , options);
  };
 })();    
</script>
<script type="text/javascript" src="/js/jquery.mobile-1.4.0.min.js"></script>

Start of every returned page

<div data-role="page" data-theme='a' id="<?php echo $this->id_url()?>">
<div data-role="content">
<script type="text/javascript">
// we create dynamically a function named after the id you gave to that page
// this will bind it to window
this[ '<?php echo $this->id_url() ?>' ].initPage = function(){
    // put anything you want here, I prefer to use a call 
    // to another JS function elsewhere in the code. This way I don't touch the 
    // settings anymore
    NameOfThisPage.launchEverythingThatNeedsTo();
};
</script>
...

Here's the description for this code. First, I get one place for all those global query, JQM already forced me to put stuff in-between jquery.js & jquery.mobile.js, so let's use that.

Along with the global JQM settings, I use only one event listener bind to the body/document/(whatever it'll be in the future). It's only launched once the body exist.

Now, here's where the fun begins. I programatically give an id to every pages the server returns (namely the script route with _ instead of / ). You then create a function named after that id, it's attached to the window, (I suppose you could put it elsewhere..).

Then back to the event listener, on transition, you get that id you've set through pagecontainer( "getActivePage" ) method, use that id to grab the page jQuery style, then compare it with the data returned by the event listener.

If success, use that id to launch the init function you've putted in your page. There's a failsafe in case you don't put an init script in page.

Bonus here, are those document.loadPage / changePage . I've putted them there in case the methos to change page changes. One place to modify, and it'll apply to the entire app. That's DRY ^^

All in all, if you have comment on a way to improve this method, please share. There's a big lack of example for v1.4 methods (along with a bit of confusion with v1.3 examples). I've tried to share my discoveries the best I could (ps. I need those rep points :P )

DColl
  • 185
  • 2
  • 14
  • Nice answer. Unfortunately, you'll get no rep from _wiki_ answers/questions. – Omar Feb 04 '14 at 21:02
  • Well, I mistakenly posted this answer as a community wiki, so feel free to improve the recipe ;) – DColl Feb 05 '14 at 09:46
  • you can deleted it and add a normal answer without ticking _wiki_ option. – Omar Feb 05 '14 at 09:47
  • seriously, I dont care anymore about the rep on this site.. If a JQM guru wonder by here and wants to edit this piece of code, I believe it would be a great addition to the community ^^ – DColl Feb 05 '14 at 17:28