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;
+};