JQM 1.4 - What is the preffered way to use pagecontainer event on a specific page/selector?

StackOverflow https://stackoverflow.com/questions/21546097

  •  06-10-2022
  •  | 
  •  

Domanda

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 ;)

È stato utile?

Soluzione

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 )

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top