Open rbu opened 11 years ago
Hi, I think this use case should be handled with the pagebeforeload event.
You just have to disable push state ($.mobile.pushStateEnabled=false) and install a route for the beforeload event. Remember to strip the "#" from your internal links (for instance, your "#foo" page will become "foo" or "foo.html". Don't worry if the foo.html file doesn't exist, you've disabled push state for this exact reason).
Once you've injected the (full) page into the DOM, just resolve the deferred provided by jQuery Mobile itself. There's no need to play with autoInitializePage since jQM already knows what to do when the deferred is resolved.
With 'beforeload', do you mean pagebeforeload (bl)?
When I create an empty jQM site with a router and $.mobile.autoInitializePage = false; $.mobile.pushStateEnabled = false;
, I do not get such an event and the page stays empty.
What do you mean by "the deferred provided by jQuery Mobile itself"? My idea was to call changePage with the dom fragment that I generated, but there may be a better way?
Taking a step back, am I doing something completely unintended with the router here? My understanding was that it allows for dynamic content generation. What I want is this scenario:
http://mysite/app -- renders the index http://mysite/app#index -- renders the index (explicitly / backlink) http://mysite/app#detail?id=23 -- renders a detail editor for item number 23
Once one page is loaded, the router will trigger navigation just fine -- I can go from the index to a detail editor and back. I just want the router to handle the load case as well. If this should already be possible, maybe it would help to have an example that comes with no initial page and just a few render functions.
I have a very minimized example at http://jsfiddle.net/pGe3s/6/ Note, to escape the iframe surrounding the fiddle and actually experiment with hashtags, you can directly open http://fiddle.jshell.net/pGe3s/6/show/light/
In the example, note that http://fiddle.jshell.net/pGe3s/6/show/light/#edit does not load the edit page.
I think you might be overcomplicating things with your current approach (which is perfectly fine, but it's quite messy in jQM. I guess you've already realized that :D).
When you want to dynamically inject pages into my jQM applications, there are basically two ways to achieve such a thing:
1) using the pagebeforechange event. This one may be tough, it's been somehow buggy in the past and not consistent across different jQM versions. However, you retain "hash" pages / urls. With this approach, your internal links will look like #foo?bar=baz
2) using the pagebeforeload event. This is the "official" way to inject ajax things in jQM. If you're content is not really ajax but comes from a template in a js file, it's absolutely the same
I've played with both approaches and I prefer the latter, because I get a minimal cache management which may be fine in most cases (and when it needs to be tweaked, jQM provides a couple of useful events that are not available with the former), because I don't want my DOM to be bloated with a lot of pages.
Back to your example, I would simply keep a "skeleton" page in my DOM for the first page only (and add the content during the pagebeforechange event at startup), then inject the details using the pagebeforeload event and its deferred magic (http://api.jquerymobile.com/pagebeforeload/).
Urls would be in the form:
If you really want to use pagebeforechange, I suggest you put at least the first
<div data-role="page"> ... </div>
skeleton into the DOM to avoid this jQM madness. Then you can inject whatever you want using the router deferred mechanism.
Hello, I am having a similar problem as rbu, but do not understand how to implement your option 2. Could you explain in more detail via an example?
To give you some background, I originally coded my app with Backbone and jQM by disabling the jQM page navigation by disabling linkBindingEnabled, ajaxEnabled, hashListeningEnabled, and pushStateEnabled. In doing so, as part of calling Backbone.View.Render() I would append 'pages' to the DOM dynamically.
I would like to implement your router in my app, but also maintain how I dynamically inject pages into the DOM.
Regardless of the above, I'm also having an issue with the routing. I am initializing the router like so in my custom AppRouter class:
__init__: function() {
var self = this
new $.mobile.Router(self.routes, self.handlers.self.options);
}
routes: {
"" : { handler: "dashboard", events: "bs" }
"#sessions" : { handler: "sessions", events: "bs" }
}
dashboard: function(type, match, ui, page, evt) {
require(['views/pages/DashboardView'], function(DashboardView) {
(new DashboardView()).render() // dynamically attaches to the body tag
})
},
sessions: function(type, match, ui, page, evt) {
require(['views/pages/SessionsView'], function(SessionsView) {
(new SessionsView()).render() // dynamically attaches to the body tag
})
}
The problem I'm having is that no matter what url I put in the browser, it always goes to 'dashboard'. If I change the first route from "" to #dashboard
no pages will load at all.
It does not seem to be possible to load the first page via a JS handler when no page with that id already exists in the DOM. If it is, it's not documented well.
Here's how I have this set up:
$.mobile.autoInitializePage = false
$.mobile.initializePage()
by handI have any number of pages, that are generated completely in JS. The router looks like this:
Ideally, I want my HTML body to be empty, the index rendered by default and the detail page should be loaded when the site is accessed with /#detail?id=23
Unfortunately, this does not work because jQM requires at least one page to be present in the DOM when initializePage is called. If it is not, the body will be made into a page. This page could be the index (which is a sane default), however when I add the index page to the DOM, jQM will set a wrong data-url to this page (...detail... instead of index) and call changePage to this page. jQM Router will not call its JS handlers to render a page at all, because jQM already hands over a page (albeit a wrong one). The relevant code path in jQM is this (from initializePage):
This code path is triggered because hashPage is null -- there is no page with that id yet. It surely must be possible not to have dummy HTML elements for every single path that I support. And if it's not -- jQM Router should create them for me.