azicchetti / jquerymobile-router

A router/controller for jquery mobile. Also adds support for client-side parameters in the hash part of the url. The routes handles regexp based routes. This plugin can be used alone or (better) with Backbone.js or Spine.js, because it's originally meant to replace their router with something integrated with jQM.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

page show being fired multiple times

drewda opened this issue · comments

Hello @azicchetti Thanks again for the great library.

I'm running into problems that I think must be due to jquerymobile-router. My routes trigger on pageshow using the following routing table (in CoffeeScript):

window.masterRouter = new $.mobile.Router [
  { "#open-project": { events: "s,i,c", handler: "openProject" } }
  { '#show-count-schedule(?:[?](.*))?': { events: "s", handler: "showCountSchedule" } }
  { "#start-count(?:[?](.*))?": { events: "s", handler: "startCount" } }
  { "#enter-count(?:[?](.*))?": { events: "s", handler: "enterCount" } }
  { "#validate-count(?:[?](.*))?": { events: "s", handler: "verifyCount" } }

I can navigate between all the different routes in my single-page app successfully the first time. But when I return to previously visited pages, the pageshow event is triggered multiple times. Each time I return to the route, it is called more times than it was before.

I thought this might be related to #37 or #31, but neither seem to describe the problem.

I am using jquerymobile-router 0.9, JQM 1.1.0, and Backbone 0.9.2. The problem still occurs when I roll back to JQM 1.0.1.

Do you have any suggestions for how to debug this or to localize the problem? Is there some way I may need to clean or un-cache each page after visiting it?

Thank you!

Hi!
The double-trigger issues were related mostly to the back button but the issue seems fixed at the moment.

In your case I think there's something deeper, as if the handlers are installed twice.
Which jquery version are you using, by the way?

Is there a way I can see the faulty code or a brief example of that?

Thanks for the quick response!

I'm using jQuery 1.7.1. I know more recent versions can cause problems.

I'm not seeing signs that the handlers are being installed multiple times.

The problem seems to be specific to when I use $.mobile.changePage. There are no problems when I click on a link.

This is part of a pretty large application that also involves Backbone, Rails, and a number of other client- and server-side pieces. Not sure how I can show you more code without using up too much of your time.

Do you have any suggestions for how I can trace the path of calls made by $.mobile.changePage and see if there is a place where it repeats?

So you're having problems with changePage() when manually invoked.
I cannot reproduce the issue at the moment, but you should be able to write a small test file using your app as a model.

A couple of places in the jqm router-dev where you can put some debug code:
line 55, after nextUrl=u;
console.log("pagebeforechange evt: " + nextUrl);

line 249, after } while(url.length==0 && retry<=1);
console.log("process "+e.type);

Please keep me informed about your findings!

Thanks

Hi @azicchetti and thx for your plugin.

I am encountering the same bug with my app.
The router is keeping firing all the routes and some of them got executed many times.
Do you have any idea how to fix this?

Thx in advance.

Hi @manekinekko, interesting to hear that you're having the same problem. I've been trying to fix it in my system, but I have not yet had any success.

What versions of jQuery and jQM are you using? Are you using any additional jQM plugins?

Hi @drewda here's my conf:

  • jQuery 1.7.2
  • jQuery Mobile 1.1.0
  • jQuery Mobile Router 0.81
  • Backbone 0.9.2 + Backbone.dualstorage plugin + underscore.

I'm also calling changePage() method manually in my code to switch between pages.

I'm having a lot of headache trying to debugg this problem but no success :)

Hi guys,
I've tried a couple of simple examples with manual changePage calls but I wasn't able to reproduce the problem.

I'm pretty sure at this point that there's something wrong somewhere, but I need some faulty code to properly debug this issue.

Is there anyone who can write a test case?

Thank you

@manekinekko those are pretty much the same versions as I'm using...

@azicchetti , I haven't been able to write a test case that captures the problem. If you have time to look at some production code that exhibits the problem, I can e-mail you a private URL and password.

@drewda Sure, hopefully I'll be able to find some time to debug the issue in the next few days. Thanks

@azicchetti Thanks very much!

@azicchetti Here is my custom changePage() function that I am calling each time to switch between pages:

/**
 * @param page : A backbone View object or a string of a page's ID
 */
changePage : function(page) {

            var pageId = '';
            var transition = $.mobile.defaultPageTransition;

            if( typeof page === 'string') {
                pageId = page;
            } else {
                pageId = '#' + $(page.el).attr('id');
                $(page.el).attr('data-role', 'page');
                page.render();
            }

            // We don't want to slide the first page
            if(this._firstPage) {
                transition = 'none';
                this._firstPage = false;
            }
            $.mobile.changePage(pageId, {
                transition : transition
            });

        }

Also, this is an example of a route i'm using:

     ...
     '#poll(?:[?](.*))?' : function(eventType, matchObj, ui, page, evt) {
            var poll_id = matchObj !== null ? matchObj[1].split('=')[1] : 0;
            changePage(new PollView({
                'poll_id' : poll_id
            }));
      },
     ...

So, I really don't know if the problem comes from the changePage() function or the router itself.
Please find below an example of a log from my app which indicates that the page is really called many times:

...
1. routing to #pollsList
2. loading templates "polls/pollsList" [bypassCache: true]
3. rendering #pollsList
4. changing to page #pollsList
5. routing to #pollsList
6. loading templates "polls/pollsList" [bypassCache: true]
7. rendering #pollsList
8. changing to page #pollsList
...

As you can see, from line 1 to 4, this is a normal behavior: we route using jqmRouter, load template, render it using _ and changePage using jqm. But, It looks like the same hash (url) is routed again, from 5 to 8.
I know this log is not going to help you debugging the problem. But it helps illustrate my issue.

Thx again for your time and help.

@manekinekko It would be really useful to have that snippet of your code to illustrate the problem. Would it be possible to have a zipfile with that faulty example, maybe privately sent to my email?

Since I understand this may be a work project or something, I promise I won't disclose the code and just use it to debug the library.

Thanks

@azicchetti Ok no problem. But I'll need some time to package a clean copy of the app which is quite complex.

Il 03/05/2012 11:19, manekinekko ha scritto:

@azicchetti Ok no problem. But I'll need some time to package a clean copy of the app which is quite complex.

Great, thank you!

Hi @azicchetti I've sent you an email with the package as you asked.

Have you two been able to make any progress on this? If not, I'd be glad to show you some of my code, @azicchetti. If you have a few minutes, maybe we can do a Skype call and I can screen share to demonstrate the problem.

@drewda As far as I know the behavior of the router is fine.
Unfortunately, jquery mobile is a wild beast and it's quite easy to do something "wrong" that leads to these kind of problems (and much worse).

I'll be glad to help you debug your code, but I think I'll need a packaged version of your app in order to be of some help. Even a wget-ted version of a couple of pages that exhibit the problem may be enough.

Just a couple of things to check:

  • be sure that you're not instantiating the router multiple times. Putting the code in the "pageinit" event is not a good idea because it's triggered at least one time for each page of your application
  • if you're using a single-page template with multiple 'ajax' pages, you don't have to set the id or data url of the page container
  • if you're transitioning from page A to page B, don't call $.mobile.changePage with B as the destination page during the transition (jqm does crazy things in such a case)
  • it's easy to write a wrong regular expression. If I have two pages, #news and #newsList, and I use the route "#news", both pages will match. Use the $ operator when necessary

@azicchetti, thank you again for such a thorough response! I will try to check the items you mentioned before sending you any code.

  • Is it alright to have my JS instantiation begin on a $(document).ready(handler)? Or could that be running multiple times?
  • Yes, I am doing a single-page template with AJAX-style pages. I have the ID set for each of the page containers, like this: <div data-role="page" id="show-count-schedule"> For which my route matcher is: { '#show-count-schedule(?:[?](.*))?': { events: "s", handler: "showCountSchedule" } } Should I be doing this differently?
  • document ready is fine, but I'm sure it's too late to get the first route dispatched when the application boots (but you probably don't need it)
  • It depends on how you've structured your application. If you have a lot of files that will be loaded 'on demand' and injected in the dom as jqm pages, it's best to use "/path/to/file.html"-style routes, but it's not mandatory, you just have to pay attention to a couple of things.

Don't worry and send me a zip where I can see the issue, I'll be more than glad to help if I can (it goes without saying that I won't disclose your code with anyone and use it just for debug purposes).

@azicchetti: More in your inbox...