

Backbone.js 0.5.0 Released (with pushState) - jashkenas
http://blog.documentcloud.org/blog/2011/07/code-release-backbone-js-0-5-0/

======
jashkenas
I'd be curious to hear from anyone who thinks that this sort of parallel
hashchange/pushState support is a _bad_ idea. It should prove to be
controversial at the least.

* <http://www.documentcloud.org/public/#search/guantanamo>

* <http://www.documentcloud.org/public/search/guantanamo>

People who don't care much about Internet Explorer support often say to just
use pushState, and let IE users endure full page refreshes ... but that's not
really an acceptable way to build a responsive web app.

Hopefully, having the same structure for pushState and hash-based URLs, with
transparent upgrades in both directions, is a sane way to bridge these sort of
applications to the future.

~~~
masklinn
> People who don't care much about Internet Explorer support often say to just
> use pushState, and let IE users endure full page refreshes ... but that's
> not really an acceptable way to build a responsive web app.

Why not? It's responsive for those with a modern browser (and may get the IE
team to integrate the history API in IE10), and is less responsive for those
with an older browser. That _can be_ an acceptable tradeoff.

~~~
jashkenas
Sure -- it depends where you draw the line for "acceptable", and how much you
care about the experience of your IE users. In any single-page web app of
significant size, I'd argue that it's _never_ acceptable to do a full page
refresh. Would you really want to go back to a GMail that refreshed when you
clicked around between labels?

Regarding (2): hash-based URLs also work perfectly well for older browsers.

~~~
catshirt
you're right, "acceptable" is subjective. but it doesn't seem unreasonable
that if you are using an outdated version of a program, it will not perform
optimally. to that end, managing both pushState and hashchange adds overhead
and complexity. personally, i don't think enhancing old browsers is worth said
overhead.

 _that said_ , if it was part of a framework i was using anyway, overhead and
complexity are much less of an issue, so the question becomes "why not".

------
johnbender
For those of you looking to use pushState in your apps, its also broken in iOS
4.2.x.

More information here:

[http://stackoverflow.com/questions/6161701/is-history-api-
br...](http://stackoverflow.com/questions/6161701/is-history-api-broken-on-
ios-location-bar-doesnt-update-on-pushstate)

------
MatthewPhillips
Right now I'm doing pushState manually and I have a bug that I can't figure
out. popstate happens whenever history changes, including when the user types
my URL in and hits enter. There doesn't appear to be a way to differentiate
between hitting the back button and going to my URL directly. Which is a
problem because if they type it in directly I want to render on the server, if
they hit the back button I want to do xhr. What am I doing wrong?

As for Backbone, I really need to switch to this rather than manually handling
click events and feeding jquery tmpl. Backbone seems to be a much better way
to do it but there also appears to be a learning curve that I'm fighting
against going through.

~~~
masklinn
> Which is a problem because if they type it in directly I want to render on
> the server

Why? What difference does the precise way they navigated to the URL make?

> if they hit the back button I want to do xhr.

Most back buttons have a popup menu which let users go to a completely
arbitrary url they've already seen, they're not limited to the very last page.
They can also hit the button several times to go back to the same page.

> What am I doing wrong?

You're adding arbitrary separations between two instances of the same event:
your users going from your site to your site.

~~~
MatthewPhillips
They are not arbitrary separations, they are very real. When a user navigates
from the URL bar or from a link on another site the browser requests a
specific location from my server. Since I'm already serving the browse HTML it
makes sense to render my templates at the same time. It doesn't make sense to
send only a generic template and then have the popstate trigger an XHR request
for some JSON which gets rendered by a javascript template library. That's
extra and unnecessary.

What are you suggesting? That I request the entire html doc at every popstate
event?

~~~
masklinn
> When a user navigates from the URL bar or from a link on another site the
> browser requests a specific location from my server. Since I'm already
> serving the browse HTML it makes sense to render my templates at the same
> time. It doesn't make sense to send only a generic template and then have
> the popstate trigger an XHR request for some JSON which gets rendered by a
> javascript template library. That's extra and unnecessary.

Wait, I might have misunderstood something here: do you mean `popstate` is
triggered when users _arrive on your site from an other one or from nowhere_?
On initial loading? As in, it's triggered by navigation between different
domains, not just in-domain navigation?

~~~
MatthewPhillips
Correct.

~~~
masklinn
Would you happen to be using Chrome?

edit: Try checking the `state` attribute of your event object, it should only
be set (therefore truthy) for history entries created via pushState, urls
being navigated will not have a state.

~~~
MatthewPhillips
Yep. Chrome bug?

~~~
masklinn
May be a chrome bug[0] or a spec bug/weirdness[1].

See edit, try checking for the state attribute on your event object to filter
out spurious popstate events.

An other option would be to use a shim library (History.js) handling that kind
of crap (and smoothing out implementation details issues) for you.

[0]
[http://www.google.com/support/forum/p/Chrome/thread?tid=28ed...](http://www.google.com/support/forum/p/Chrome/thread?tid=28edce84cd40d581&hl=en)
[1] [http://hacks.mozilla.org/2011/03/history-api-changes-in-
fire...](http://hacks.mozilla.org/2011/03/history-api-changes-in-firefox-4/)

~~~
MatthewPhillips
Yep, I was doing it wrong. You're supposed to pass a state object as the first
parameter, I was passing null. So this fixes 2 things, prevents me from having
to do XHR on initial page load AND I don't need to do an XHR on back/forward
navigation either, I can just use the state object to store my data. Awesome!

~~~
masklinn
Good to hear.

------
DrHankPym
I read somewhere that Backbone was being dropped for Spine.

<http://maccman.github.com/spine/>

Anyone else know anything about this?

~~~
jashkenas
Hah, that might be what Spine would like you to think ;)

In all seriousness, Spine is Alex MacCaw's rewrite/re-imagining of Backbone
for his O'Reilly book: <http://jswebapps.heroku.com/>

The broad strokes are roughly the same, but the internals work differently.
I'd suggest you look at what both libraries have to offer, and pick whichever
suits your fancy. The benefits accrued by your application should be similar
in both cases.

Spine doesn't depend on Underscore.js, but also doesn't benefit from
Underscore's rich collection functions. If you'd like to each, map, filter,
find, reject, every, some, invoke, include, sortBy, without, or pluck over
your models, try Backbone.

If Backbone looks too bewildering at first glance, Spine may be easier to
start with: the documentation is certainly better geared for beginners.

------
nikcub
I can now scrap my pushState fork :)

------
azrealus
Hey Jeremy! Thanks for releasing the new version!

------
Hipchan
<http://stackoverflow.com/questions/6193858/pushstate-and-seo>

pushState's SEO issues.

~~~
odiroot
Or you could use progressive JavaScript, AFAIK. Make your every link a first
class citizen (with it's own view) and for supported browsers replace links'
default action with content switching (without reloading) using JS requests.

Of course that's a bit harder since your views need to respond in a different
manner to casual GETs and AJAX requests.

~~~
encoderer
Which really should be trivial using most modern 3-Tier frameworks. They
universally have a concept of "layout" vs "template" so in a pseudocode logic,
all you need to do is tap into the render method and swap out an empty layout
when responding to an XHR request.

~~~
odiroot
Exactly, however one can argue the number of your test cases (and cache
entries) doubles. Still I think it's an elegant solution.

