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

pagebeforechange #25

Closed tkw722 closed 12 years ago

tkw722 commented 12 years ago

Hi there!

I'm working on a project where we are needing to do dynamic page injection in the DOM to dynamically build pages to navigate to. My initially when I was working with mobile router I thought the 'bc' event was bound to pagebeforechange which is what the jquery mobile documentation recommends to work with in order to dynamically inject pages. In fact though bc maps to pagebeforecreate which is run much later in the page lifecycle than pagebeforechange. Do you know of any way to work with the router to have a controller method be fired on pagebeforechange?

Thanks for your time!

azicchetti commented 12 years ago

Il 22/02/2012 22:39, tkw722 ha scritto:

Hi there!

I'm working on a project where we are needing to do dynamic page injection in the DOM to dynamically build pages to navigate to. My initially when I was working with mobile router I thought the 'bc' event was bound to pagebeforechange which is what the jquery mobile documentation recommends to work with in order to dynamically inject pages. In fact though bc maps to pagebeforecreate which is run much later in the page lifecycle than pagebeforechange. Do you know of any way to work with the router to have a controller method be fired on pagebeforechange?

Hi, the documentation doesn't exactly recommend to work with pagebeforechange. In fact, the purpose of that event is usually to hijack change parameters and modify the normal behavior of the framework.

The example on the jquery mobile website uses that event just to support parameters in the hash part of the url and the router itself uses pagebeforechange to implement the routing.

It should be noted that, in an ajax application, you can't inject nodes in the DOM using pagebeforechange because the page may not be available yet.

Don't worry about the timing, the difference between beforechange and beforeshow, for instance, is a few milliseconds.

Cheers, Andrea

tkw722 commented 12 years ago

Hi Andrea,

I'm referencing this page of the jquery mobile documentation:

http://jquerymobile.com/demos/1.0.1/docs/pages/page-dynamic.html

The reason they recommend the pagebeforechange method is so you can dynamically modify the page in the DOM before its transitioned to. The reason pagebeforechange is more helpful than pagebeforecreate is because you can get e.preventDefault() the $.mobile.changePage execution, do your page modifications, then call $.mobile.changePage with the actual page jquery object rather than the url string to navigate to. If you strictly bind to pagebeforecreate the e.preventDefault() you end up doing in the controller method is too late to stop $.mobile.changePage(). This being the case $.mobile.changePage() will end up running through and completing. In my case it ends up transitioning you to an empty page because I haven't built it yet. Although before $.mobile.changePage() ends it does a call to enhancePage() which within it triggers pagebeforecreate and subsequently the controller method via $.mobile.Router. Since I build the page then issue my own call to $.mobile.changePage() the end result is a transition to an empty page followed almost simultaneously to a transition to the correctly built page. If however there are any ajax requests or timeouts of any sort in the controller method the difference between the two page transitions is even more pronounced. Adding the ability to bind to pagebeforechange within $.mobile.Router would then allow the ability to e.preventDefault() the execution of $.mobile.changePage() then allowing you to do whatever dynamic work necessary followed by your own execution of it. I hope that makes sense. I've been digging very deeply into this issue all day and it's been a loong day. :-)

Let me know what you think or if you have any ideas around it. I'm thinking at this point the best solution is to add the feature of binding to that event within $.mobile.Router which I'm going to take a stab at. It has its own complexity to it though since pagebeforechange is actually triggered on the page container and not the page itself like the other methods that $.mobile.Router makes available. I'm going to keep playing!

Thanks!

azicchetti commented 12 years ago

Oh I get it, you don't have an empty skeleton page in the DOM, you want to create it from scratch, inject it in the dom, then navigate to the newly inserted page.

Although it's possible, I wouldn't recommend anything like that, for a couple of reasons:

However, even if you need to inject pages in the dom from scratch, the best event would probably be pagebeforeload (you need to invoke preventDefault here, then resolve the deferred once you've finished with your dom manipulation).

Please make sure that you really need to build your app that way, because you're probably adding a useless layer of complexity. I've done a lot of websites and apps using just pageinit, pagebeforecreate and pagebeforeshow events.

I'll try to add support for beforechange or beforeload events when I have a little time.

Cheers

azicchetti commented 12 years ago

I've found that little time before going to sleep...

I've pushed on the git a -dev version of the router, with support for pagebeforechange (bC) and pagebeforeload (bl). There are also a couple of super-ugly examples to inject a page using two different techniques.

The code may still need to be polished and tested but it seems to work.

Hope this helps a little!

Cheers

tkw722 commented 12 years ago

Andrea,

Thank you for pushing the update! I'm going to take a look at it right now and see how it goes. I'll let you know how things go!

Cheers!

yurtaev commented 12 years ago

It's works for me, many thanks.