Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a hash anchor for location/zoom persistence #378

Closed
wants to merge 8 commits into from
Closed

Use a hash anchor for location/zoom persistence #378

wants to merge 8 commits into from

Conversation

jfirebaugh
Copy link
Member

Using a hash that updates as the map is panned and zoomed is
a direct and obvious way to persist the map state across refreshes,
to bookmark particular locations, and to share links with other
users.

Given the numerous existing ways that the initial state of the
map can be determined, this will require tweaking and refinement.
I'm submitting this PR in very early stages to get feedback and
suggestions.

The current behavior is to add a #zoom/lon/lat hash, and to redirect
requests with zoom, lon, lat query parameters to the equivalent
hash. (Other query parameters are preserved.)

I'm assuming that we will want the lon, lat, and zoom in the hash to
take precedence over all other sources for location (e.g. cookie, home
location, bbox param, object). For example, when I load http://www.openstreetmap.org/?way=52477381,
pan around a bit, and refresh, I expect to get the view I had when I
refreshed, not for the map to recenter on the bridge as it currently
does.

I'm also assuming we'll want to update the places where we generate
links with lat/lon/zoom query parameters to use a hash instead.

We probably want to extend the state stored in the hash to include
at least the active base and overlay layers.

In the map-ui pull request, @seav raised a concern about polluting
the browser history. Fortunately, this does not happen -- location.replace
does not generate a history entry, and is available all the way back
to IE6.

@woodpeck
Copy link
Contributor

Sounds like a good idea to solve the permalink issue. Will the browser history remain un-polluted even if you refresh after a location.replace call?

@jfirebaugh
Copy link
Member Author

Will the browser history remain un-polluted even if you refresh after a location.replace call?

Yes.

@pnorman
Copy link
Contributor

pnorman commented Jul 24, 2013

Right now it is really convenient to be able to take the lat/lon from OSM.org, copy that part of the URL, and paste it into another site, e.g. geofabrik map compare, bing imagery analyzer, etc. Will we be losing that ability?

@jfirebaugh
Copy link
Member Author

Yes, we'll be losing that ability on sites that use lon, lat, and zoom query parameters. On the other hand, we'll be gaining the ability on sites that use zoom/lat/lon hash parameters (i.e. any that use leaflet-hash). And on the third hand, it will be easier to write a bookmarklet that auto-opens other sites at the current location, because it's easily determined from location.hash (whereas before you would have to delve into JS or DOM internals with no guarantee of stability).

@oandregal
Copy link

@jfirebaugh do you know geohash? It allows for shortening locations taking into account zoom level. There is plenty of libraries out there (ruby, js, etc) to interact with it. Check https://en.wikipedia.org/wiki/Geohash and http://geohash.org in case it may be useful.

@openstreetmap-website
Copy link

Are you aware that ITO have the lat/lon/zoom params in the traditional format and auto updating? Maybe that would be a better solution so that the old urls don't need redirecting?
For example http://www.itoworld.com/map/69?lon=-1.30513&lat=54.56590&zoom=10

On 23 Jul 2013, at 21:57, John Firebaugh notifications@github.com wrote:

Using a hash that updates as the map is panned and zoomed is
a direct and obvious way to persist the map state across refreshes,
to bookmark particular locations, and to share links with other
users.

Given the numerous existing ways that the initial state of the
map can be determined, this will require tweaking and refinement.
I'm submitting this PR in very early stages to get feedback and
suggestions.

The current behavior is to add a #zoom/lon/lat hash, and to redirect
requests with zoom, lon, lat query parameters to the equivalent
hash. (Other query parameters are preserved.)

I'm assuming that we will want the lon, lat, and zoom in the hash to
take precedence over all other sources for location (e.g. cookie, home
location, bbox param, object). For example, when I load http://www.openstreetmap.org/?way=52477381,
pan around a bit, and refresh, I expect to get the view I had when I
refreshed, not for the map to recenter on the bridge as it currently
does.

I'm also assuming we'll want to update the places where we generate
links with lat/lon/zoom query parameters to use a hash instead.

We probably want to extend the state stored in the hash to include
at least the active base and overlay layers.

In the map-ui pull request, @seav raised a concern about polluting
the browser history. Fortunately, this does not happen -- location.replace
does not generate a history entry, and is available all the way back
to IE6.

You can merge this Pull Request by running

git pull https://github.com/osmlab/openstreetmap-website hash
Or view, comment on, or merge it at:

#378

Commit Summary

Use leaflet-hash
Redirect lat/lon/zoom query params to hash
File Changes

M Vendorfile (4)
M app/assets/javascripts/application.js (1)
M app/assets/javascripts/index.js (2)
M app/controllers/site_controller.rb (6)
M test/functional/site_controller_test.rb (10)
A vendor/assets/leaflet/leaflet.hash.js (159)
Patch Links:

https://github.com/openstreetmap/openstreetmap-website/pull/378.patch
https://github.com/openstreetmap/openstreetmap-website/pull/378.diff


rails-dev mailing list
rails-dev@openstreetmap.org
http://lists.openstreetmap.org/listinfo/rails-dev

@jfirebaugh
Copy link
Member Author

Geohash is an interesting concept, but for this purpose we want something where the location and zoom can be read off the URL directly -- it's handy to be able to look at the location bar and see what zoom level you're at.

The ITO solution uses sesssion history management (in particular, history.replaceState), which is less widely available than location.replace (it's notably missing from IE<10). I would eventually like to progressively enhance part of OSM.org using history.pushState, but in my opinion it's best used for a different purpose:

  • history.pushState: Progressively enhance sites to add seamless, fast page loads between conceptually different pages. The GitHub file browser is an example of a good use.
  • location.replace: Change the URL hash to reference a different section or location on the existing page -- in other words, for similar cases as a normal hash anchor.

Importantly, both of these uses preserve the normal browser history semantics; history.pushState adds to the history when navigating to a conceptually different page, and location.replace avoids adding a history entry for the conceptually same page.

@jfirebaugh
Copy link
Member Author

Ok, I've implemented everything mentioned in my initial comment, and this is ready for testing.

@karussell
Copy link
Contributor

Why not use a solution like History.js where you use the HTML5 history rewrite feature if available and falls back to hash if not available? It contains some quirks but several sites including my own are using it successfully.

@rjw62
Copy link
Contributor

rjw62 commented Jul 26, 2013

Is there a reason why the ordering #zoom/lon/lat has been chosen? I'd have thought that #lat/lon/zoom would be preferable, as it would make sense to allow the omission of zoom (and the system can choose an appropriate default) but not the omission of either lat or lon. Also the current query string based implementation has the ordering lat, lon, zoom when a permalink is created, and this ordering is also used by Google and Bing maps.

@jfirebaugh
Copy link
Member Author

Good question. The current ordering is actually #zoom/lat/lon (I accidentally reversed it in the initial description), which is the default for leaflet-hash. There's no real consensus or clear choice for lat/lon vs lon/lat -- Google, Bing, and Leaflet do it one way, GeoJSON, D3, iD, and other frameworks another.

Zoom will always be present in the hashes generated by OSM.org itself, so URLs that omit zoom would be coming from third-party source. What sorts of use cases do you think a zoomless URL would be used for? And when it is omitted, how should an appropriate default be determined?

@pnorman
Copy link
Contributor

pnorman commented Jul 26, 2013

significant figures on lat/lon? That's all I can think of for zoom detection

Where will the layer information appear? right now we have layers=M for mapnik, etc.

@jfirebaugh
Copy link
Member Author

Yeah, significant figures was all I could think of too. Seems fragile; let's leave it for now. If we find a compelling use case for making zoom optional and a good way of determining a default, it will still be possible to check if there are two slash-separated components versus three.

The hash now looks like #map=z/lat/lon&layers=x. Note (N) and data (D) layers are included, and there's a special case that layers=M is dropped -- in other words, if you have the default Mapnik base layer and no overlays, there's no layers parameter clutter.

@tomhughes Can we get a test deploy of this please?

@tomhughes
Copy link
Member

Deployed at http://hash.apis.dev.openstreetmap.org/.

@seav
Copy link
Contributor

seav commented Jul 29, 2013

Using the demo site, my browser's history is polluted:

hash-browser-polluted

I'm running Firefox 22.0 under Kubuntu Quantal.

@jfirebaugh
Copy link
Member Author

@seav There's no way to prevent that, not even with the HTML5 history API. I'm referring to what ends up in the back button history.

@seav
Copy link
Contributor

seav commented Jul 29, 2013

Ouch. In that case, I'm really not in favor of having this hash anchor proposal. As you can imagine, I frequently browse around the map to check for map data issues so I really do not want tons of not-so-useful OSM URLs in my browser's history.

(Of course I might be in the minority here that actually uses my browser's history feature as part of my browsing habits.)

@vincentdephily
Copy link
Contributor

While I love the feature, I have to agree that poluting the history makes it a non-starter to me. Is it really unfixable ?

@tomhughes
Copy link
Member

Do people really browse their history like that? I think I maybe look at it like once a year or something when trying to find a URL that I know I visited at a particular time but can't find by searching my history in the awesome bar for some reason.

Back/forward sure, use them all the time. Awesome bar search of history, use it all the time. Browse history? Pretty much irrelevant for me.

@jfirebaugh
Copy link
Member Author

I'm in the same camp as @tomhughes -- I hardly ever use the global history UI, and will gladly accept extra entries there in return for the benefits of a persistent hash.

That said, it is unfortunate that some browsers have the behavior they do. There seems to be little consistency between browsers:

Firefox 22: Both location.replace and history.replaceState create new entries in the global history UI.
Chrome 28: Both location.replace and history.replaceState create new entries in the global history UI.
Chrome 30: location.replace updates the existing entry, history.replaceState creates new entries
Opera 12: Neither location.replace nor history.replaceState create new entries (but neither update the existing entry)
Opera 15: Sometimes location.replace creates a new entry, sometimes it updates an existing one (no idea what the criteria are). history.replaceState always creates a new entry.
Safari 6: Both location.replace and history.replaceState create new entries in the global history UI.

The behavior of Firefox is under discussion here.

@lxbarth
Copy link
Contributor

lxbarth commented Jul 30, 2013

This feels amazing.

@seav
Copy link
Contributor

seav commented Aug 1, 2013

Regardless of whether or not you use the global history feature of your browser, I think we can agree that making the browser consume more disk space just to store not-so-useful history entries is not ideal, right? (Yeah, disk space is cheap, but still...)

To look at the issue in another way, having the URL update on every pan and zoom change is like updating the URL every time you scroll a web page even just a little bit. In most web applications, they update the URL when there is an arguably new "page" that is shown, like in Gmail, but not when you just navigate around the current content.

Anyway, to add more data for discussion, among the other major mapping websites, Classic Google Maps, Bing Maps, and MapQuest do not use persistent URLs. The New Google Maps and Nokia's Here website do use persistent URLs.

@jfirebaugh
Copy link
Member Author

@seav So, what you are saying is that the disk space concerns are negligible, and other modern map webapps are following the same path? ;)

@lxbarth
Copy link
Contributor

lxbarth commented Aug 1, 2013

There's a big upside of much easier sharing through direct copying the URL from the address bar. Good bye crutches on the web UI (we'll keep a little share block but we can move it a click further away #328). It clearly outweighs the downside of a verbose history :)

@jfirebaugh
Copy link
Member Author

Another advantage is that after you visit a permalink (a shared or bookmarked link, or the "View" tab link) and move the map around a bit, refreshing preserves the current location rather than resetting to the original one, which can be pretty annoying.

@tomhughes
Copy link
Member

Merged.

@tomhughes tomhughes closed this Aug 4, 2013
@tomhughes tomhughes mentioned this pull request Aug 6, 2013
@pnorman
Copy link
Contributor

pnorman commented Aug 6, 2013

Note: people may have to do a force-reload to get the new javascript, until then people may have odd behaviour. I don't suggest any code changes to fix this as it will resolve itself in about a day when cached content expires.

@tomhughes
Copy link
Member

Nobody should ever have to force reload anything - the assets pipeline takes care of that by changing the hash in the URL for the javascript.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet