stamen / modestmaps-js

Modest Maps javascript port
http://modestmaps.com
566 stars 152 forks source link

Port polymaps.hash() #24

Closed tmcw closed 13 years ago

tmcw commented 13 years ago

It'd be nice to have a hashchange-using permalink functionality in modestmaps. I'll develop this loosely connected to the core - not sure what your opinions are on whether this should be in core or outside.

RandomEtc commented 13 years ago

We should make sure the pattern is supported by easy methods on Map, and provide an example for it, but personally I think this is an application-level design choice...

For example with a little bit of server-side support you can use pushState in HTML5 to support this kind of permalink without manipulating the hash/fragment https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history - Map should support a clean way of passing state around as used in that API.

On http://cartagr.am we didn't use pushState, we used a jquery.history plug-in (of which there are many), it looks something like this:

// http://tkyk.github.com/jquery-history-plugin/#documentation
$.history.init(function(hash){
    if(hash != "") {
        var args = hash.split("/");
        if (args.length == 3) {
            map.setCenterZoom(new MM.Location(Number(args[1]), Number(args[2])), Number(args[0]));
        }    
    }
}, { unescape: ",/" });

var updateTimer = 0;
function updateHash() {
    if (updateTimer) {
        clearTimeout(updateTimer);
        updateTimer = 0;
    }
    updateTimer = setTimeout(reallyUpdateHash, 500);
}

function reallyUpdateHash() {
    var zoom = map.getZoom(),
        center = map.getCenter(),
        lat = center.lat,
        lon = center.lon,
        precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)), // trust the Bostock
        hash = zoom.toFixed(2) + "/" + lat.toFixed(precision) + "/" + lon.toFixed(precision);
    // library only updates if hash is different
    $.history.load(hash);
    updateTimer = 0;
}

map.addCallback('drawn', updateHash);

Note the 500ms timer to make sure you're not modifying the URL hash on every frame. This makes the back button work with map state, but I'm not sure it's 100% right - it's quite annoying to have to hit back a lot after a long browsing session. OTOH it's quite cool that it works :)

I've also used Sammy.js and Really Simple History to do similar things, and I think jQuery might be getting core support for this functionality soon as well?

Definitely interested in a clean modular example for this, anyway!

migurski commented 13 years ago

I love this feature in Polymaps. It feels like a slightly external add-on, or at least an optional one on a per-map basis. It's pretty normal for me to use more than one map per page, so it's important to identify the one that has hash support.

mbostock commented 13 years ago

Trust the Bostock FTW!

RandomEtc commented 13 years ago

Looks like a solid library to learn from, if not to adopt in an example: https://github.com/balupton/History.js

tmcw commented 13 years ago

Started working on this outside of core in Wax's hash.js, but it'll need a lot more work (pluggable history, definitely) to be mature.

tmcw commented 13 years ago

I think this can live in Wax unless anyone strongly wants it in Modest Maps - it's a nice-to-have, but not essential to putting tiles on a page.