2         var HAS_HASHCHANGE = (function() {
 
   3                 var doc_mode = window.documentMode;
 
   4                 return ('onhashchange' in window) &&
 
   5                         (doc_mode === undefined || doc_mode > 7);
 
   8         L.Hash = function(map) {
 
   9                 this.onHashChange = L.Util.bind(this.onHashChange, this);
 
  16         L.Hash.parseHash = function(hash) {
 
  17                 if(hash.indexOf('#') === 0) {
 
  18                         hash = hash.substr(1);
 
  20                 var args = hash.split("/");
 
  21                 if (args.length == 3) {
 
  22                         var zoom = parseInt(args[0], 10),
 
  23                         lat = parseFloat(args[1]),
 
  24                         lon = parseFloat(args[2]);
 
  25                         if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
 
  29                                         center: new L.LatLng(lat, lon),
 
  38         L.Hash.formatHash = function(map) {
 
  39                 var center = map.getCenter(),
 
  41                     precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
 
  44                         center.lat.toFixed(precision),
 
  45                         center.lng.toFixed(precision)
 
  53                 parseHash: L.Hash.parseHash,
 
  54                 formatHash: L.Hash.formatHash,
 
  63                         if (!this.isListening) {
 
  64                                 this.startListening();
 
  69                         if (this.changeTimeout) {
 
  70                                 clearTimeout(this.changeTimeout);
 
  73                         if (this.isListening) {
 
  80                 onMapMove: function() {
 
  81                         // bail if we're moving the map (updating from a hash),
 
  82                         // or if the map is not yet loaded
 
  84                         if (this.movingMap || !this.map._loaded) {
 
  88                         var hash = this.formatHash(this.map);
 
  89                         if (this.lastHash != hash) {
 
  90                                 location.replace(hash);
 
  97                         var hash = location.hash;
 
  98                         if (hash === this.lastHash) {
 
 101                         var parsed = this.parseHash(hash);
 
 103                                 this.movingMap = true;
 
 105                                 this.map.setView(parsed.center, parsed.zoom);
 
 107                                 this.movingMap = false;
 
 109                                 this.onMapMove(this.map);
 
 113                 // defer hash change updates every 100ms
 
 116                 onHashChange: function() {
 
 117                         // throttle calls to update() so that they only happen every
 
 119                         if (!this.changeTimeout) {
 
 121                                 this.changeTimeout = setTimeout(function() {
 
 123                                         that.changeTimeout = null;
 
 124                                 }, this.changeDefer);
 
 129                 hashChangeInterval: null,
 
 130                 startListening: function() {
 
 131                         this.map.on("moveend", this.onMapMove, this);
 
 133                         if (HAS_HASHCHANGE) {
 
 134                                 L.DomEvent.addListener(window, "hashchange", this.onHashChange);
 
 136                                 clearInterval(this.hashChangeInterval);
 
 137                                 this.hashChangeInterval = setInterval(this.onHashChange, 50);
 
 139                         this.isListening = true;
 
 142                 stopListening: function() {
 
 143                         this.map.off("moveend", this.onMapMove, this);
 
 145                         if (HAS_HASHCHANGE) {
 
 146                                 L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
 
 148                                 clearInterval(this.hashChangeInterval);
 
 150                         this.isListening = false;
 
 153         L.hash = function(map) {
 
 154                 return new L.Hash(map);
 
 156         L.Map.prototype.addHash = function() {
 
 157                 this._hash = L.hash(this);
 
 159         L.Map.prototype.removeHash = function() {