L.Control.AutoUpdate = L.Control.extend({ options: { position: 'topleft', label: 'Automatic update' }, onAdd: function() { var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control'); container.innerHTML = '
' + this.options.label + '
'; L.DomEvent.on(container, 'click', this.cbClick, this); return container; }, cbClick: function (e) { L.DomEvent.stopPropagation(e); this.intendedFunction(e); if (e.target.checked) { this.autoUpdate(); } if (!e.target.checked) { this.stopUpdate(); } }, intendedFunction: function() { alert('no function selected'); }, stopUpdate: function() { this.socket.close(); }, autoUpdate: function() { this.socket = new WebSocket('ws://' + window.location.host + '/ws'); this.socket.onmessage = function(evt) { var invalidate = function(json) { var invalidateAll = function(x, y, z) { return true }; if (!(typeof json === "string")) { return invalidateAll; } var tiles; try { tiles = JSON.parse(json); } catch (err) { return invalidateAll; } var pyramid = new Array(9); var last = new Object(); pyramid[8] = last; for (var i = 0; i < tiles.length; i++) { var xz = tiles[i]; last[xz.X + "#" + xz.Z] = xz; } for (var p = 7; p >= 0; p--) { var prev = pyramid[p+1] var curr = new Object(); pyramid[p] = curr; for (var k in prev) { if (prev.hasOwnProperty(k)) { var oxz = prev[k] var nxz = { X: oxz.X >> 1, Z: oxz.Z >> 1 }; curr[nxz.X + "#" + nxz.Z] = nxz; } } } return function(x, y, z) { if (y > 8) { x >>= y - 8; z >>= y - 8; y = 8; } var level = pyramid[y]; var k = x + "#" + z; return level.hasOwnProperty(k); }; } (evt.data); var tiles = document.getElementsByTagName('img'); var re = /\/map\/([0-9]+)\/([0-9]+)\/([0-9]+).*/; for (var i = 0; i < tiles.length; i++) { var img = tiles[i]; var cl = img.getAttribute('class'); if (!cl.contains('leaflet-tile-loaded')) { continue; } var src = img.src; var coord = src.match(re); if (coord == null) { continue; } var y = parseInt(coord[1], 10); var x = parseInt(coord[2], 10); var z = parseInt(coord[3], 10); if (invalidate(x, y, z)) { var idx = src.lastIndexOf('#'); if (idx >= 0) { src = src.substring(0, idx); } img.src = src + '#' + Math.random(); } } }; } }); L.autoUpdate = function(cbLabel, cbFunc, cbMap) { var control = new L.Control.AutoUpdate(); if (cbLabel) { control.options.label = cbLabel; } if (cbFunc) { control.intendedFunction = cbFunc; } if (cbMap === '') { return control; } else if (cbMap) { cbMap.addControl(control); } else { map.addControl(control); } return control; };