3

Working on my first jQuery Mobile app. There is a localStorage value that must have a value throughout the application, so I tapped into the pageshow event to check this value:

$(function () {
$("div[data-role='page']").on("pageshow", function (event, ui) {
    if (getValue() == null) {
        // show the dialog
        $.mobile.changePage("#dialog");
    }
});
});

This works when navigating through the various pages, but never gets called when the first page loads. I tried to copy the above If statement again below the part where I add the pageshow listener, but it has the effect of showing the dialog, hiding it, then showing it again.

On that first page, it seems like opening the dialog is triggering pageshow (which is strange, considering my selector), which in turn triggers another dialog. Does anyone have advice on how to get around this, or a better way to go about the whole thing?

UPDATE #1: I tried

$.mobile.changePage( "#mypage", { allowSamePageTransition: true, transition: "none" } );

but it had the same effect as my original problem where it launches the dialog, then hides it, then shows it again. It seems like somehow launching the dialog is firing the pageshow event, even though I tried to filter that out in my selector. Note that if you remove the transition: "none" option, the dialog does not appear at all.

UPDATE #2: I also tried to create a blank initial page, then do a simple page transition

$.mobile.changePage("#mypage");

but it still does not have the correct behavior. In this scenario, it does take me to the next page, but the pageshow event does not fire, because my dialog does not appear. I know it is not firing because I can select another page from my navigation menu and the dialog does appear.

UPDATE #3: I changed my selector where I attach the pageshow listener. Instead of selecting where data-role="page", I am selecting the specific pages by their id. Then I re-tried both of the approaches I described in my previous two updates, but it still works incorrectly. First, when I try to refresh the initial page using allowSamePageTransition, it seems that pageshow fires twice, because the dialog launches twice. Then, when I try using a blank initial page, and then do a redirect immediately after I attach the pageshow listener, nothing happens and the dialog never appears. If I navigate to any other page, the dialog works as expected. I don't understand why this first page is so troublesome.

tjc59
  • 613
  • 7
  • 24
  • I have added more details, for future reference and also explains the purpose of timeout function. – Omar Apr 10 '13 at 21:57

3 Answers3

14

Set a time interval to show the dialog, rather than call it once the page is shown.

$(document).on('pageshow', '#myPage' ,function () {
 if (getValue() == null) {
  setTimeout(function () {
   $.mobile.changePage('#dialog');
  }, 100); // delay above zero
 }
});

This way, the dialog will popup on pageshow event and only once.

update

I found this interesting jQueryMobile events diagram on this blog. It explains why a dialog or a popup is fired twice on the first page and not on the rest of the pages in case of multi-pages structure. It seems it fires once the page is ready into DOM and again when on pageshow. Setting a timeout prevents the dialog from firing on pageinit, and therefore skips that event until pageshow is triggered.

enter image description here

Image / diagram source: http://bradbroulik.blogspot.co.nz/2011/12/jquery-mobile-events-diagram.html

Omar
  • 32,160
  • 9
  • 67
  • 108
  • While this does work, I am very interested to understand why in my Update #1 (allowSamePageTransition) the pageshow event fires twice, and why in my Update #2 (blank page redirect) the pageshow event doesn't fire at all after the redirect. – tjc59 Apr 10 '13 at 18:57
  • My personal interpretation to this behavior - might not be correct - is that JQM renders all HTML within body and then focuses on the first page. Thus, the first page is shown twice. Giving an interval time makes sure that page is loaded and shown. I guess it needs at least 40ms for this operation. – Omar Apr 10 '13 at 19:09
  • @tjc59 forgot to mention that time needed to load the code differs from browser to another. But 100-200ms should be fine. – Omar Apr 10 '13 at 19:21
  • 1
    While there may be a cleaner way to accomplish this than setting a timeout, I sure can't find one for now. Bounty is yours, @Omar – tjc59 Apr 10 '13 at 20:11
  • @tjc59 I'm glad I've been of help. I'll dig more into this issue and update my answer accordingly. – Omar Apr 10 '13 at 20:39
  • 1
    @Omar +1 for the image. – Varun Nath Oct 07 '13 at 08:58
  • 1
    There should be extra points awarded for upvotes awarded after a certain amount of time has passed. Nearly a year has passed and here I am googling this issue and here I find the solution. Just picturing Omar whistlin **that** tune as he strolls along the interwebs. – rory Feb 06 '14 at 16:24
  • @omar Imma take advantage of your good mood... If I have an app with all the pages (ie `
    `) within one ``, does one of the target pages have to be visited before caching or can it be cached on initialisation of the whole DOM?
    – rory Feb 07 '14 at 08:58
  • @rory I'm always in a good mood. All pages are cached but not created, as you're using multi page model. But history will be updated once pages is visited. – Omar Feb 07 '14 at 09:23
  • @Omar Man you've saved me soooo much grief - turns out I was recalling my login dialog everytime I moved to a target page. A simple `loggedin = true/false` global variable did the trick. Easy when you know where (or in this case) where not to look ;-) – rory Feb 07 '14 at 09:35
0

Most probably is that on first page, that event is already fired when your piece of code is executed. Which explains why you get nothing only on the first page.

About your second point, it's normal since, changePage will "change" the page to the dialog, and once you close the dialog, it will return to your previous page. Thus, the if is executed 2 times.

My suggestion is that for the first time you enter the first page, you can re-transition to the same page just after you register the callback for the pageshow event.

wmfairuz
  • 984
  • 8
  • 16
  • I tried: $.mobile.changePage( "#mypage", { allowSamePageTransition: true } ); and it had the same effect as my original scenario. It launches the dialog, then hides it, then shows it again. – tjc59 Apr 08 '13 at 20:59
  • I have updated my original post to include two different updates I tried to make. Neither were successful. – tjc59 Apr 08 '13 at 21:35
0

I used "pagecreate" and that seems to solve my problem (so far...)

$(document).on('pagecreate', "#page-formyID", function () {

//whatever

});
user3163139
  • 27
  • 1
  • 5