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.
GNU General Public License v2.0
402 stars 69 forks source link

pagebeforecreate handler always called twice #51

Closed dwt closed 11 years ago

dwt commented 11 years ago

With a route configured like this:

var mainController = new MainController();
new $.mobile.Router([
    { "#nonExistingPage": { handler: "nonExistingPage", events: 'bC' } }
], mainController);

And a handler like this

var MainController = klass({

    nonExistingPage: function() {
        console.log('nonExistingPage')
        $('body').append('<div data-role="page" id="nonExistingPage" data-url="nonExistingPage"><h1>Hello World</h1></div>')
    }

});

I see that the nonExistingPage handler is always called twice when navigating to this page.

I can of course account for that, but it seems like a bug none the less.

azicchetti commented 11 years ago

Il 10/07/2012 10:33, Martin Häcker ha scritto:

With a route configured like this:

{ "#nonExistingPage": { handler: "nonExistingPage", events: 'bC' } }

And a handler like this

  nonExistingPage: function() {
      console.log('nonExistingPage')
      $('body').append('<div data-role="page" id="nonExistingPage" data-url="nonExistingPage"><h1>Hello World</h1></div>')
  }

I see that the nonExistingPage handler is always called twice when navigating to this page.
I can of course account for that, but it seems like a bug none the less.

Hi, using the pagebeforechange event is not recommended because you have to properly know how jquery mobile internals work, since this is the main routing event used by the framework. This event is always fired twice, but with different arguments.

There's an example here: examples/test-bC.html. The key points are: * call e.preventDefault() * check the .toPage property

If you really want to inject pages in the dom by hand (remember that jquery mobile does this automatically with an ajax call), you may want to consider using pagebeforeload instead of pagebeforechange (see examples/testbl.html). You'll just simulate the "ajax" behavior of the framework without actually performing the ajax call.

Hope this clears things up a bit, but I know that this advanced jquery mobile usage seems really crazy at first (mainly because it wasn't designed to do this, to begin with).

Cheers, Andrea

dwt commented 11 years ago

pagebeforeload seems like a good idea, but I didn't get it to trigger if for me. That is just changing the event to { "#nonExistingPage": { handler: "nonExistingPage", events: 'bl' } } didn't work for me - the handler is never called.

dwt commented 11 years ago

As per the example, it would be my understanding that this should result in the handler getting called when navigating to that page:

var mainController = new MainController();
new $.mobile.Router([
    { "#nonExistingPage": { handler: "nonExistingPage", events: 'bl' } }
], mainController, { ajaxApp: true });

However that also doesn't seem to work.

dwt commented 11 years ago

Still back to the handler: Regardless of how the underlying handlers work in jQuery Mobile, wouldn't it make a lot of sense that if I register a handler for the pagebeforechange event for a specific page, I only get the handler called once?

azicchetti commented 11 years ago

Il 10/07/2012 11:32, Martin Häcker ha scritto:

Two quick notes:

  • e.preventDefault from the handler is not possible, as you don't get access to the event
  • same for the toPage property - it's not available from the handler.

You have access to all these elements in the handler.

See the test-bC example

                 testDocEvts: function(type,match,data,scope,e){
                         console.log("document event! "+type);
                         e.preventDefault();
                         if (typeof(data.toPage)!=="string") return;
                         $.mobile.changePage( $('<div data-role="page" 
data-url="localpage4"><div data-role="header"><h1>title</h1></div><div 
data-role="content">page4content<a data-role="button" href="#index">back 
to index</a></div></div>').appendTo("body") );
                 }
azicchetti commented 11 years ago

Il 10/07/2012 11:32, Martin Häcker ha scritto:

Two quick notes:

  • e.preventDefault from the handler is not possible, as you don't get access to the event
  • same for the toPage property - it's not available from the handler.

That being said, pagebeforeload seems like a good idea, but I didn't get it to trigger if for me. That is just changing the event to { "#nonExistingPage": { handler: "nonExistingPage", events: 'bl' } } didn't work for me - the handler is never called.

If you switch to the pagebeforeload event, you're basically changing the way your application works.

When you switch from a single-file multipage template (hash based pages) to the ajax paradigm (required for the pagebeforeload to work), you need to: * change your links from #nonExistingPage to nonExistingPage * add ajaxApp: true during the router initialization

Use the test-bl.html file as an example.

dwt commented 11 years ago

Well, many thanks for the help, it helped a lot!