diff --git a/index.html b/index.html index fef944cec..d210e5644 100755 --- a/index.html +++ b/index.html @@ -28,6 +28,7 @@ + @@ -76,6 +77,7 @@ }); map.setZoom(18) .setCentre({ lat: 40.7965621, lon: -74.4773184 }); + iD.Hash().map(map); window.onresize = function() { map.setSize(m.node().offsetWidth, diff --git a/js/iD/renderer/Map.js b/js/iD/renderer/Map.js index 18e1524f9..1a56682c7 100755 --- a/js/iD/renderer/Map.js +++ b/js/iD/renderer/Map.js @@ -13,6 +13,8 @@ iD.Map = function(obj) { .scale(512).translate([512, 512]), connection = obj.connection; + var event = d3.dispatch('move'); + var inspector = iD.Inspector(); var linegen = d3.svg.line() @@ -239,11 +241,22 @@ iD.Map = function(obj) { .translate(d3.event.translate) .scale(d3.event.scale); } + event.move(map); tileclient.redraw(); drawVector(); download(); } + function getCenter() { + var ll = projection.invert([ + width / 2, + height / 2]); + return { + lon: ll[0], + lat: ll[1] + }; + } + function setCentre(loc) { // summary: Update centre and bbox to a specified lat/lon. var t = projection.translate(), @@ -261,6 +274,7 @@ iD.Map = function(obj) { map.setCentre = setCentre; map.setCenter = setCentre; + map.getCenter = getCenter; map.getZoom = getZoom; map.setZoom = setZoom; map.zoomIn = zoomIn; @@ -272,5 +286,5 @@ iD.Map = function(obj) { setSize(width, height); redraw(); - return map; + return d3.rebind(map, event, 'on'); }; diff --git a/js/iD/renderer/hash.js b/js/iD/renderer/hash.js new file mode 100644 index 000000000..4fa60730d --- /dev/null +++ b/js/iD/renderer/hash.js @@ -0,0 +1,63 @@ +iD.Hash = function() { + var hash = {}, + s0, // cached location.hash + lat = 90 - 1e-8, // allowable latitude range + map; + + var parser = function(map, s) { + var args = s.split("/").map(Number); + if (args.length < 3 || args.some(isNaN)) return true; // replace bogus hash + else { + map.setZoom(args[0]); + map.setCenter({lat: Math.min(lat, Math.max(-lat, args[1])), lon: args[2]}); + } + }; + + var formatter = function(map) { + var center = map.getCenter(), + zoom = map.getZoom(), + precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)); + return "#" + zoom.toFixed(2) + + "/" + center.lat.toFixed(precision) + + "/" + center.lon.toFixed(precision); + }; + + function move() { + var s1 = formatter(map); + if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map! + } + + function hashchange() { + if (location.hash === s0) return; // ignore spurious hashchange events + if (parser(map, (s0 = location.hash).substring(1))) + move(); // replace bogus hash + } + + hash.map = function(x) { + if (!arguments.length) return map; + if (map) { + map.off("move", move); + window.removeEventListener("hashchange", hashchange, false); + } + if (map = x) { + map.on("move", move); + window.addEventListener("hashchange", hashchange, false); + location.hash ? hashchange() : move(); + } + return hash; + }; + + hash.parser = function(x) { + if (!arguments.length) return parser; + parser = x; + return hash; + }; + + hash.formatter = function(x) { + if (!arguments.length) return formatter; + formatter = x; + return hash; + }; + + return hash; +};