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

Figure out how to handle nested hash states in nested listview #21

Closed
scottjehl opened this issue Sep 15, 2010 · 3 comments
Closed

Figure out how to handle nested hash states in nested listview #21

scottjehl opened this issue Sep 15, 2010 · 3 comments

Comments

@scottjehl
Copy link

Listview currently hogs the whole hash for state tracking, which is fine if you start on the page that contains a nested listview (like _listview.html), but not fine if you got to _listview.html through an ajax transition. If you did, the next level of the tree will be something like...
pagefoo.html#ui-listview-2

which of course doesn't exist on pagefoo.html.

Doug suggested using a slash to reach sub-page pages:
pagefoo.html#_listview.html/ui-listview-2

Another way we could try would be something like:
pagefoo.html#_listview.html&sublist=ui-listview-2

Either way, this would at least allow us to deep-link for JavaScript users. Non-JS linking is still unresolved.

@cowboy
Copy link
Contributor

cowboy commented Sep 15, 2010

I'd recommend avoiding the /-separator approach and use params, as /-separated tokens can easily end up being super limited when, down the road, you decide you need a more flexible serialization scheme, since not only is token ordering significant, but token key names are implicit and can't be specified. The reason that BBQ uses params is because it allows much, much greater flexibility at pretty much zero cost in terms of code size or performance (especially since jQuery has $.param built-in).

You could use BBQ for now, just for prototyping.. and then when you get a little time, write some very simple code that does what the $.bbq.pushState(), $.bbq.getState() and $.bbq.removeState() do, but using a simpler custom $.deparam that maybe doesn't handle deserializing deep objects.

Or just use BBQ, because it's pretty small, thoroughly documented, and unit tested.

Non-JS deep linking could be done via query strings (which BBQ also provides support for) that are progressively enhanced into fragments. For example, something like this:

HTML:

<a href="?a=1&b=2" class="jqm-internal">click me</a> ...

JS:

$('a.jqm-internal').each(function(){
  this.href.replace( /^.*\?/, '#' );
});

(or a live event handler that performs the equivalent task on click)

@scottjehl
Copy link
Author

Thanks for the advice Ben,
I agree that query strings will bring more flexibility than the slash, and I think John already started writing up a quick set/get state for that to work without BBQ.

However, the larger problem we have is with non-js bookmarking. In other words, click around a bit, paste the url into a browser that has JS disabled, it won't be able to reproduce the same state.

At the moment, we're not auto-replacing an href's ? with #, but rather just adding the whole href value into the hash and preventing the link from its default behavior. So at least with this approach, the links in the markup make fine sense for SEO and non-js, and the hash can reflect a full url, which may include its own query string values. In other words, the address could look something like this:
/pageA.html#pageB.php?a=foo&b=bar

But with either approach, the problem is that once you've clicked around a bit as a JS user, returning to that "page" again will require JS. Mainly because pageB.php doesn't exist on pageA.html (it was loaded via ajax for the JS user)

Aside from using pushState where we can, I'm not sure of any ways around this issue.
Thoughts?

@cowboy
Copy link
Contributor

cowboy commented Sep 17, 2010

I've been giving this some thought, and am actually in the middle of a big blog post about it. The direction I'm leaning right now, for maximum backwards-/forwards- compatibility is history.pushState -> location.hash -> query strings.

I know that using full paths is "all the rage" with pushState-enabled apps and demos, but by using query strings instead of full paths for both the default non-JavaScript links and enhanced pushState versions, the app can remain "single page" and not need any kind of server-side rewrites.

See the example, which I've tested in Chrome and FF4 (which support pushState) and FF2 (which doesn't), with JavaScript both enabled and disabled.

I need to spend more time with it, but this feels like a "best of both worlds" approach: it uses the latest technologies in a cool way, degrades well, and is very easy to implement.

This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants