Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Dynamic Page Generation & Page Refresh #5085

Closed
milantopalov opened this issue Sep 25, 2012 · 23 comments
Closed

Dynamic Page Generation & Page Refresh #5085

milantopalov opened this issue Sep 25, 2012 · 23 comments

Comments

@milantopalov
Copy link

Trying to generate a dynamic page.

I've followed the instructions (http://goo.gl/e9RPr) and it works just fine when flicking between pages.

The problem appears when user lands on the page containing some parameters (or refreshes it; i.e. not by clicking a link within the app, but say from an external website)...

e.g. if users was to land on this page

http://www.domain.com/jqueryapp#page?msg=hello

not only would "pagebeforechange" event not fire, but JS would break - console would display:
"Uncaught Error: Syntax error, unrecognized expression: #page2?msg=hello"

Is there a way around this?

Cheers!

@azicchetti
Copy link

Hi,
seems the same as #5080 (or at least directly related to), quite annoying bug

@jaspermdegroot
Copy link
Contributor

@milantopalov

You said you followed the instructions on this page, but I don't see the issue you mentioned when I test our working example.

We need a test page to see if this is a bug or a problem with your code. See Contributing Guidelines for a link to our JS Bin template.

@azicchetti
Copy link

Hi,
a straight link to:

http://jquerymobile.com/test/docs/pages/dynamic-samples/sample-reuse-page.html#category-items?category=animals

reveals the problem.
Instead of #category-items the #home page is shown.

@jaspermdegroot
Copy link
Contributor

@azicchetti

If I click that link I get to see the category overview page ("Select a Category Below"), as expected.
The category "animals" is only generated and injected in the category overview page when the link is clicked. So even when the url says ?category=animals you won't land at a page that shows this category.

I am not sure what you mean by #home page in this case.

Also, I don't get a "Uncaught Error: Syntax error, unrecognized expression:" error as you mentioned and the pagebeforechange event is fired.

@azicchetti
Copy link

Uhm, no, that's not the expected behavior.
The purpose of the whole javascript pagebeforechange handler was to let the user land on the destination page even if it's generated on the fly.

If we have a multipage template, with two pages (#onw and #two), it's possible to deep link the second page and make it work as a straight url.
For instance:
http://jquerymobile.com/demos/1.1.1/docs/pages/multipage-template.html#two
Even if #one is the first page, the second one is shown thanks to the #two hash in the url.

Similarly, we need a way to do the same thing with parameters that are appended to the hash, such as #two?foo=bar or #category-items?category=animals.

Until 1.1.1 we could bind to the pagebeforechange event, parse the data.toPage property and do some "magic" (e.preventDefault, trigger a programmatic changePage to a certain page div, etc).

The bug described by @milantopalov is strictly related to #5080.

To further prove the point, take the previous example with jQM 1.1.1:

http://jquerymobile.com/demos/1.1.1/docs/pages/dynamic-samples/sample-reuse-page.html#category-items?category=animals

vs

http://jquerymobile.com/test/docs/pages/dynamic-samples/sample-reuse-page.html#category-items?category=animals

The same page leads to different results, the first (w/ 1.1.1) being the right one.

Hope everything is clear now, it's a kinda diffucult topic ;)

@gabrielschulhof
Copy link

AFAIK we don't support deep-linking to pages (dynamically generated or otherwise) with query parameters. The reason it worked in 1.1.1 is because an old version of jQuery would accept a faulty selector ("#page2?msg=hello"). Newer versions of jQuery no longer accept such a selector, and, as a result, that which accidentally worked before has now stopped working.

Nevertheless, the current behaviour is what's intended. The docs mention two plugins which allow you to pass query parameters between pages (bottom of the docs page). Try those.

@johnbender is the authority on this topic.

@gabrielschulhof
Copy link

Mentioning #4777 because that one also deals with query parameters.

@azicchetti
Copy link

Hi @gabrielschulhof ,
I'm the author of one of those plugins, so I have a good understanding of this topic.

I'm aware that jQM won't support query parameters natively, since the previous behavior was more of a bug than an intended feature.

But the sample-reuse-page contains a certain pagebeforechange handler technique, which is the basis on which we can develop routing plugins.

Unfortunately, with 1.2.0-rc* versions, we don't have the first pagebeforechange with the string url anymore and thus we can't add support for query parameters to deep links (see #5080).

@ghost ghost assigned johnbender Sep 26, 2012
@johnbender
Copy link
Contributor

@azicchetti

We'll have to address this in the first point release but we've got some other things to deal with there as well, so it's likely to be released fairly quickly.

@azicchetti
Copy link

Great, thank you!

@johnbender
Copy link
Contributor

@azicchetti I'm working on this in a branch. I may just end up addressing the original issue but I have to have a chat with @jblas first.

@johnbender
Copy link
Contributor

This will get merged after the release.

@azicchetti
Copy link

Thank you.
I've briefly tested the patch and it works, however I've a couple of questions because I think there's still something strange around and I want to have the full picture of the subject before updating the plugin.

  • if I've understood correctly, parameters are now handled by default by the framework (it won't get confused by the "?parameters" part since it gets stripped before looking for the destination page), and so the technique shown here:
    http://jquerymobile.com/test/docs/pages/dynamic-samples/sample-reuse-page.html#category-items?category=animals
    is now obsolete and unnecessary (I'm talking about binding to pagebeforechange, preventing the default behavior and performing the programmatic changePage)

  • we can assume that jQM will pass the pagebeforechange handler a full string representation of the destination url in a consistent way for both the following scenarios:
    1) the user types a straight link to a certain inner page in his browser (i.e: file.html#innerPage?parameters)
    2) the user clicks on a link that points to #innerPage?parameters

    The full url string mentioned above is in the data.toPage property when data.toPage is a string, and in data.options.target when data.toPage is the jQuery object wrapping the destination page.

  • it seems that the parameters get stripped from the url when I click on a link.
    However, they are left untouched when I use a straight link to: file.html#innerPage?parameters.
    Is it possible to keep them in the url in some way? The "old" technique used data.options.dataUrl but I think it doesn't work anymore.

  • "same page" transitions: we need a way to enable or add support for them (I got a lot of requests to enable them automatically).
    If I'm on #page?foo=bar and click on a link to: #page?bar=baz, I can see that pagebeforechange gets triggered but no transitions are performed, and page events (beforeshow and such) are not triggered.
    I guess this is the intended behavior, right?
    I'm still able to enable them by setting data.options.allowSamePageTransition=true in the pagebeforechange handler, is this the "official" way?

Thank you very much for your help.

@johnbender
Copy link
Contributor

@azicchetti

Let me address each in turn:

  1. The framework will now retain the original url and query params from the hash. So there's no need to do that manually.
  2. The goal is to pass the full resolved url. If this is failing then I'll have to take another look at why. I'd like the property to be consistent across pagebeforechange calls and I'm still thinking about where it should be and what it should be called. This may involve deprecating other older params.
  3. I'll address this directly (re-opening)
  4. Yes this is the "official way", I would bind to pagebeforechange and set that option where necessary, and you can obviously set it when calling changePage directly:
$.mobile.changePage( "#foo", {samePageTransition: true});
@johnbender
Copy link
Contributor

@azicchetti

Most importantly, thank you for all your help. It makes it much easier to get this right early when application developers participate as you have!

@johnbender
Copy link
Contributor

@azicchetti

On number 1 I'd like to change my response :)

We've got a lot of code that makes url's absolute for different circumstances (links, forms, etc) and then a fallback in loadPage that deals with relative urls that come from programmatic changePage or loadPage calls. I'll have to think about push this up the stack a bit for consistency's sake.

@johnbender
Copy link
Contributor

@azicchetti

I'm going to move the attribute up to the the data object, it doesn't makes sense (and I knew this when I started) as an option value. Thinking about data.url. Simple enough.

@johnbender
Copy link
Contributor

@azicchetti

I pushed a change that will push our resolution of the absolute url on the data object as the .url property. Let me know if this works for you.

@azicchetti
Copy link

Thank you very much for your quick answers, I'm gonna test the patch in the next few hours.

In the meanwhile, let me check if I got this right:

  • the full url (or something like that) will be in data.toPage property when data.toPage is a string, and in data.url when data.toPage is the jQuery object wrapping the destination page.
  • pagebeforechange will usually be triggered two times for each transition, the first one with a string as the data.toPage argument, and the last one with a jQuery object. There is only one exception to this rule: a programmatic changePage with a jQuery object as the first argument
  • with these two premises, we can say that in order to get the "full" url under any possible circumstance (including straight links, standard anchors, back buttons, programmatic changePages with strings or jQuery objects as the first argument, etc), you just have to bind to pagebeforechange, test when data.toPage is not a string, then examine the data.url property.

I've just another question (even if I don't think that I'll use this trick if data.url works as described above, but it's useful to know anyhow):

in previous jQM releases, I was storing a certain property in data.options (during the pagebeforechange event) in order to "mark" the current page transition and be sure that I wasn't processing the same "route" multiple times.
This custom option was preserved across the multiple pagebeforechange events that were triggered (first one with data.toPage as string, then as an object).
Is this a "supported" feature?

Thank you very much for your time!

@johnbender
Copy link
Contributor

@azicchetti

I simplified things so that the absolute url will always be provided in both the page loading and page changing events on the data object at data.absUrl. This way you don't have to do anything crazy to get the value.

To be clear, if changePage is called with a string you'll have access to the absolute URL both times when pagebeforechange is fired. If changePage is called with a jquery object there's nothing to be done as we can't manufacture a url for it so the value will be undefined. I may consider defaulting it to the data url.

$( document ).one( "pagebeforechange", function( event, data ) {
        // NOTE! this will be triggered twice but the value will be the same
    console.log( data.absUrl );
});

$( document ).one( "pagechange", function( event, data ) {
    console.log( data.absUrl );
});

$( document ).one( "pagechangefailed", function( event, data ) {
    console.log( data.absUrl );
});

$.mobile.changePage( "#bar?foo=baz" );

As to your last question the options will be preserved across them, but we reserve the right to steal your object property for our own use in the options object. To be safe I would namespace it with something we're not likely to override data.options.mydatayoucanttouch.foo.

@jamespdean
Copy link

Hi there.

I tried the patch above and it worked great for reenabling the ability to enter a site to a dynamic page ie: #animals?category=cats

However now when browsing the site and clicking a url ie: href="#animals?category=cats" the site goes to the page but the history hash ends up as #animals . This messes up the history and the ability to bookmark a page.

my "ugly fix" is to keep the old convertUrlToDataUrl and create a convertUrlToDataUrlNew (patch version) only for use by initializePage process.

Hope this helps someone and hopefully this is all fixed up soon in a point release.

Cheers
James Dean

@berkayunal
Copy link

The above path fixes the problem (Convert url params to data params) but it does not work on refresh as it used to be in the past (jqm 1.1).

So when you have #animals?category=cats it converts category to data.param and url becomes #animals but on refresh it does not as it used to be.

Does any one have a fix for that?

@johnbender
Copy link
Contributor

This is a first pass at solving the issue. We're attempting to allow linking to embedded pages with extra information attached.

If you guys would like to see the params preserved, please open a separate issue with the feature request and make sure to reference this one.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.