Skip to content

Instantly share code, notes, and snippets.

@relet
Created September 14, 2017 12:04
Show Gist options
  • Save relet/6b73fccc6cb2636f1e60c6a5ddc6bf1b to your computer and use it in GitHub Desktop.
Save relet/6b73fccc6cb2636f1e60c6a5ddc6bf1b to your computer and use it in GitHub Desktop.
leaflet.fullhash.js
(function(window) {
var HAS_HASHCHANGE = (function() {
var doc_mode = window.documentMode;
return ('onhashchange' in window) &&
(doc_mode === undefined || doc_mode > 7);
})();
L.Hash = function(map, options) {
this.onHashChange = L.Util.bind(this.onHashChange, this);
if (map) {
this.init(map, options);
}
};
L.Hash.parseHash = function(hash) {
if(hash.indexOf('#') === 0) {
hash = hash.substr(1);
}
var args = hash.split("/");
if (args.length == 4) {
var zoom = parseInt(args[0], 10),
lat = parseFloat(args[1]),
lon = parseFloat(args[2]),
layers = (args[3]).split("-");
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
return false;
} else {
return {
center: new L.LatLng(lat, lon),
zoom: zoom,
layers: layers
};
}
} else {
return false;
}
};
L.Hash.formatHash = function(map) {
var center = map.getCenter(),
zoom = map.getZoom(),
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
layers = [];
//console.log(this.options);
var options = this.options;
//Check active layers
for(var key in options) {
if (options.hasOwnProperty(key)) {
if (map.hasLayer(options[key])) {
layers.push(key);
};
};
};
return "#" + [zoom,
center.lat.toFixed(precision),
center.lng.toFixed(precision),
layers.join("-")
].join("/");
},
L.Hash.prototype = {
map: null,
lastHash: null,
parseHash: L.Hash.parseHash,
formatHash: L.Hash.formatHash,
init: function(map, options) {
this.map = map;
L.Util.setOptions(this, options);
// reset the hash
this.lastHash = null;
this.onHashChange();
if (!this.isListening) {
this.startListening();
}
},
removeFrom: function(map) {
if (this.changeTimeout) {
clearTimeout(this.changeTimeout);
}
if (this.isListening) {
this.stopListening();
}
this.map = null;
},
onMapMove: function() {
// bail if we're moving the map (updating from a hash),
// or if the map is not yet loaded
if (this.movingMap || !this.map._loaded || !this.parsedOnce) {
return false;
}
var hash = this.formatHash(this.map);
if (this.lastHash != hash) {
location.replace(hash);
this.lastHash = hash;
}
},
movingMap: false,
update: function() {
var hash = location.hash;
if (hash === this.lastHash) {
return;
}
this.parsedOnce = true;
var parsed = this.parseHash(hash);
if (parsed) {
this.movingMap = true;
var layers = parsed.layers,
options = this.options,
that = this;
//Add/remove layers
this.map.eachLayer(function(layer) {
that.map.removeLayer(layer);
});
layers.forEach(function(element, index, array) {
//console.log(options[element]);
that.map.addLayer(options[element]);
});
this.map.setView(parsed.center, parsed.zoom);
this.movingMap = false;
} else {
this.onMapMove(this.map);
}
},
// defer hash change updates every 100ms
changeDefer: 100,
changeTimeout: null,
onHashChange: function() {
// throttle calls to update() so that they only happen every
// `changeDefer` ms
if (!this.changeTimeout) {
var that = this;
this.changeTimeout = setTimeout(function() {
that.update();
that.changeTimeout = null;
}, this.changeDefer);
}
},
isListening: false,
hashChangeInterval: null,
startListening: function() {
this.map.on("moveend layeradd layerremove", this.onMapMove, this);
if (HAS_HASHCHANGE) {
L.DomEvent.addListener(window, "hashchange", this.onHashChange);
} else {
clearInterval(this.hashChangeInterval);
this.hashChangeInterval = setInterval(this.onHashChange, 50);
}
this.isListening = true;
},
stopListening: function() {
this.map.off("moveend layeradd layerremove", this.onMapMove, this);
if (HAS_HASHCHANGE) {
L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
} else {
clearInterval(this.hashChangeInterval);
}
this.isListening = false;
},
_keyByValue: function(obj, value) {
for(var key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] === value) {
return key;
} else { return null; };
};
};
}
};
L.hash = function(map, options) {
return new L.Hash(map, options);
};
L.Map.prototype.addHash = function() {
this._hash = L.hash(this, this.options);
};
L.Map.prototype.removeHash = function() {
this._hash.removeFrom();
};
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment