Merge remote-tracking branch 'osmlab/hash'
This commit is contained in:
commit
f9d714dfd3
16 changed files with 702 additions and 191 deletions
10
Vendorfile
10
Vendorfile
|
@ -1,4 +1,8 @@
|
|||
folder 'vendor/assets' do
|
||||
folder 'jquery' do
|
||||
file 'jquery.throttle-debounce.js', 'https://raw.github.com/cowboy/jquery-throttle-debounce/v1.1/jquery.ba-throttle-debounce.js'
|
||||
end
|
||||
|
||||
folder 'leaflet' do
|
||||
file 'leaflet.js', 'http://cdn.leafletjs.com/leaflet-0.6.3/leaflet-src.js'
|
||||
file 'leaflet.css', 'http://cdn.leafletjs.com/leaflet-0.6.3/leaflet.css'
|
||||
|
@ -8,7 +12,7 @@ folder 'vendor/assets' do
|
|||
'marker-icon.png', 'marker-icon-2x.png',
|
||||
'marker-shadow.png' ].each do |image|
|
||||
file "images/#{image}", "http://cdn.leafletjs.com/leaflet-0.6.3/images/#{image}"
|
||||
end
|
||||
end
|
||||
|
||||
from 'git://github.com/kajic/leaflet-locationfilter.git' do
|
||||
file 'leaflet.locationfilter.css', 'src/locationfilter.css'
|
||||
|
@ -23,6 +27,10 @@ folder 'vendor/assets' do
|
|||
from 'git://github.com/jfirebaugh/leaflet-osm.git' do
|
||||
file 'leaflet.osm.js', 'leaflet-osm.js'
|
||||
end
|
||||
|
||||
from 'git://github.com/mlevans/leaflet-hash.git' do
|
||||
file 'leaflet.hash.js', 'leaflet-hash.js'
|
||||
end
|
||||
end
|
||||
|
||||
folder 'ohauth' do
|
||||
|
|
|
@ -2,15 +2,17 @@
|
|||
//= require jquery_ujs
|
||||
//= require jquery.timers
|
||||
//= require jquery.cookie
|
||||
//= require jquery.throttle-debounce
|
||||
//= require augment
|
||||
//= require osm
|
||||
//= require leaflet
|
||||
//= require leaflet.osm
|
||||
//= require leaflet.hash
|
||||
//= require leaflet.zoom
|
||||
//= require leaflet.extend
|
||||
//= require leaflet.locationfilter
|
||||
//= require i18n/translations
|
||||
//= require oauth
|
||||
//= require osm
|
||||
//= require piwik
|
||||
//= require map
|
||||
//= require menu
|
||||
|
@ -22,10 +24,7 @@
|
|||
var querystring = require('querystring-component');
|
||||
|
||||
function zoomPrecision(zoom) {
|
||||
var decimals = Math.pow(10, Math.floor(zoom/3));
|
||||
return function(x) {
|
||||
return Math.round(x * decimals) / decimals;
|
||||
};
|
||||
return Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
|
||||
}
|
||||
|
||||
function normalBounds(bounds) {
|
||||
|
@ -61,41 +60,31 @@ function remoteEditHandler(bbox, select) {
|
|||
* view tab and various other links
|
||||
*/
|
||||
function updatelinks(loc, zoom, layers, bounds, object) {
|
||||
var toPrecision = zoomPrecision(zoom);
|
||||
bounds = normalBounds(bounds);
|
||||
var node;
|
||||
$(".geolink").each(function(index, link) {
|
||||
var href = link.href.split(/[?#]/)[0],
|
||||
args = querystring.parse(link.search.substring(1));
|
||||
|
||||
var lat = toPrecision(loc.lat),
|
||||
lon = toPrecision(loc.lon || loc.lng);
|
||||
if (bounds && $(link).hasClass("bbox")) args.bbox = normalBounds(bounds).toBBoxString();
|
||||
if (object && $(link).hasClass("object")) args[object.type] = object.id;
|
||||
|
||||
if (bounds) {
|
||||
var minlon = toPrecision(bounds.getWest()),
|
||||
minlat = toPrecision(bounds.getSouth()),
|
||||
maxlon = toPrecision(bounds.getEast()),
|
||||
maxlat = toPrecision(bounds.getNorth());
|
||||
}
|
||||
|
||||
$(".geolink").each(setGeolink);
|
||||
|
||||
function setGeolink(index, link) {
|
||||
var base = link.href.split('?')[0],
|
||||
qs = link.href.split('?')[1],
|
||||
args = querystring.parse(qs);
|
||||
var query = querystring.stringify(args);
|
||||
if (query) href += '?' + query;
|
||||
|
||||
if ($(link).hasClass("llz")) {
|
||||
$.extend(args, {
|
||||
lat: lat,
|
||||
lon: lon,
|
||||
zoom: zoom
|
||||
});
|
||||
} else if (minlon && $(link).hasClass("bbox")) {
|
||||
$.extend(args, {
|
||||
bbox: minlon + "," + minlat + "," + maxlon + "," + maxlat
|
||||
});
|
||||
args = {
|
||||
lat: loc.lat,
|
||||
lon: loc.lon || loc.lng,
|
||||
zoom: zoom
|
||||
};
|
||||
|
||||
if (layers && $(link).hasClass("layers")) {
|
||||
args.layers = layers;
|
||||
}
|
||||
|
||||
href += OSM.formatHash(args);
|
||||
}
|
||||
|
||||
if (layers && $(link).hasClass("layers")) args.layers = layers;
|
||||
if (object && $(link).hasClass("object")) args[object.type] = object.id;
|
||||
link.href = href;
|
||||
|
||||
var minzoom = $(link).data("minzoom");
|
||||
if (minzoom) {
|
||||
|
@ -115,67 +104,7 @@ function updatelinks(loc, zoom, layers, bounds, object) {
|
|||
});
|
||||
}
|
||||
}
|
||||
link.href = base + '?' + querystring.stringify(args);
|
||||
}
|
||||
}
|
||||
|
||||
function getShortUrl(map) {
|
||||
return (window.location.hostname.match(/^www\.openstreetmap\.org/i) ?
|
||||
'http://osm.org/go/' : 'http://' + window.location.hostname + '/go/') +
|
||||
makeShortCode(map);
|
||||
}
|
||||
|
||||
function getUrl(map) {
|
||||
var center = map.getCenter(),
|
||||
zoom = map.getZoom(),
|
||||
toZoom = zoomPrecision(zoom);
|
||||
|
||||
return (window.location.hostname.match(/^www\.openstreetmap\.org/i) ?
|
||||
'http://openstreetmap.org/?' : 'http://' + window.location.hostname + '/?') +
|
||||
querystring.stringify({
|
||||
lat: toZoom(center.lat),
|
||||
lon: toZoom(center.lng),
|
||||
zoom: zoom,
|
||||
layers: map.getLayersCode()
|
||||
});
|
||||
}
|
||||
|
||||
// Called to create a short code for the short link.
|
||||
function makeShortCode(map) {
|
||||
var zoom = map.getZoom(),
|
||||
str = '',
|
||||
char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~",
|
||||
x = Math.round((map.getCenter().lng + 180.0) * ((1 << 30) / 90.0)),
|
||||
y = Math.round((map.getCenter().lat + 90.0) * ((1 << 30) / 45.0)),
|
||||
// JavaScript only has to keep 32 bits of bitwise operators, so this has to be
|
||||
// done in two parts. each of the parts c1/c2 has 30 bits of the total in it
|
||||
// and drops the last 4 bits of the full 64 bit Morton code.
|
||||
c1 = interlace(x >>> 17, y >>> 17), c2 = interlace((x >>> 2) & 0x7fff, (y >>> 2) & 0x7fff);
|
||||
|
||||
for (var i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
|
||||
digit = (c1 >> (24 - 6 * i)) & 0x3f;
|
||||
str += char_array.charAt(digit);
|
||||
}
|
||||
for (i = 5; i < Math.ceil((zoom + 8) / 3.0); ++i) {
|
||||
digit = (c2 >> (24 - 6 * (i - 5))) & 0x3f;
|
||||
str += char_array.charAt(digit);
|
||||
}
|
||||
for (i = 0; i < ((zoom + 8) % 3); ++i) str += "-";
|
||||
|
||||
// Called to interlace the bits in x and y, making a Morton code.
|
||||
function interlace(x, y) {
|
||||
x = (x | (x << 8)) & 0x00ff00ff;
|
||||
x = (x | (x << 4)) & 0x0f0f0f0f;
|
||||
x = (x | (x << 2)) & 0x33333333;
|
||||
x = (x | (x << 1)) & 0x55555555;
|
||||
y = (y | (y << 8)) & 0x00ff00ff;
|
||||
y = (y | (y << 4)) & 0x0f0f0f0f;
|
||||
y = (y | (y << 2)) & 0x33333333;
|
||||
y = (y | (y << 1)) & 0x55555555;
|
||||
return (x << 1) | y;
|
||||
}
|
||||
|
||||
return str;
|
||||
});
|
||||
}
|
||||
|
||||
// generate a cookie-safe string of map state
|
||||
|
|
|
@ -69,11 +69,5 @@ $(document).ready(function () {
|
|||
}
|
||||
});
|
||||
|
||||
var params = OSM.mapParams();
|
||||
if (params.bbox) {
|
||||
map.fitBounds([[params.minlat, params.minlon],
|
||||
[params.maxlat, params.maxlon]]);
|
||||
} else {
|
||||
map.fitBounds(group.getBounds());
|
||||
}
|
||||
map.fitBounds(OSM.mapParams().bounds || group.getBounds());
|
||||
});
|
||||
|
|
|
@ -19,6 +19,8 @@ $(document).ready(function () {
|
|||
|
||||
map.attributionControl.setPrefix('');
|
||||
|
||||
map.hash = L.hash(map);
|
||||
|
||||
var layers = [
|
||||
new L.OSM.Mapnik({
|
||||
attribution: '',
|
||||
|
@ -48,8 +50,11 @@ $(document).ready(function () {
|
|||
|
||||
layers[0].addTo(map);
|
||||
|
||||
map.noteLayer = new L.LayerGroup({code: 'N'});
|
||||
map.noteLayer = new L.LayerGroup();
|
||||
map.noteLayer.options = {code: 'N'};
|
||||
|
||||
map.dataLayer = new L.OSM.DataLayer(null);
|
||||
map.dataLayer.options.code = 'D';
|
||||
|
||||
$("#sidebar").on("opened closed", function () {
|
||||
map.invalidateSize();
|
||||
|
@ -79,8 +84,6 @@ $(document).ready(function () {
|
|||
|
||||
L.OSM.share({
|
||||
position: position,
|
||||
getShortUrl: getShortUrl,
|
||||
getUrl: getUrl,
|
||||
sidebar: sidebar,
|
||||
short: true
|
||||
}).addTo(map);
|
||||
|
@ -98,24 +101,21 @@ $(document).ready(function () {
|
|||
map.markerLayer = L.layerGroup().addTo(map);
|
||||
|
||||
if (!params.object_zoom) {
|
||||
if (params.bbox) {
|
||||
var bbox = L.latLngBounds([params.minlat, params.minlon],
|
||||
[params.maxlat, params.maxlon]);
|
||||
|
||||
map.fitBounds(bbox);
|
||||
|
||||
if (params.box) {
|
||||
L.rectangle(bbox, {
|
||||
weight: 2,
|
||||
color: '#e90',
|
||||
fillOpacity: 0
|
||||
}).addTo(map);
|
||||
}
|
||||
if (params.bounds) {
|
||||
map.fitBounds(params.bounds);
|
||||
} else {
|
||||
map.setView([params.lat, params.lon], params.zoom);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.box) {
|
||||
L.rectangle(params.box, {
|
||||
weight: 2,
|
||||
color: '#e90',
|
||||
fillOpacity: 0
|
||||
}).addTo(map);
|
||||
}
|
||||
|
||||
if (params.layers) {
|
||||
var foundLayer = false;
|
||||
for (var i = 0; i < layers.length; i++) {
|
||||
|
@ -164,8 +164,8 @@ $(document).ready(function () {
|
|||
}
|
||||
|
||||
initializeExport(map);
|
||||
initializeBrowse(map);
|
||||
initializeNotes(map);
|
||||
initializeBrowse(map, params);
|
||||
initializeNotes(map, params);
|
||||
});
|
||||
|
||||
function updateLocation() {
|
||||
|
@ -177,6 +177,9 @@ function updateLocation() {
|
|||
var expiry = new Date();
|
||||
expiry.setYear(expiry.getFullYear() + 10);
|
||||
$.cookie("_osm_location", cookieContent(this), { expires: expiry });
|
||||
|
||||
// Trigger hash update on layer changes.
|
||||
this.hash.onMapMove();
|
||||
}
|
||||
|
||||
function setPositionLink(map) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//= require templates/browse/feature_list
|
||||
//= require templates/browse/feature_history
|
||||
|
||||
function initializeBrowse(map) {
|
||||
function initializeBrowse(map, params) {
|
||||
var browseBounds;
|
||||
var layersById;
|
||||
var selectedLayer;
|
||||
|
@ -49,6 +49,12 @@ function initializeBrowse(map) {
|
|||
}
|
||||
});
|
||||
|
||||
if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
|
||||
if (params.layers.indexOf(dataLayer.options.code) >= 0) {
|
||||
map.addLayer(dataLayer);
|
||||
}
|
||||
}
|
||||
|
||||
function startBrowse(sidebarHtml) {
|
||||
locationFilter = new L.LocationFilter({
|
||||
enableButton: false,
|
||||
|
|
|
@ -150,12 +150,12 @@ function initializeExport(map) {
|
|||
}
|
||||
|
||||
function setBounds(bounds) {
|
||||
var toPrecision = zoomPrecision(map.getZoom());
|
||||
var precision = zoomPrecision(map.getZoom());
|
||||
|
||||
$("#minlon").val(toPrecision(bounds.getWest()));
|
||||
$("#minlat").val(toPrecision(bounds.getSouth()));
|
||||
$("#maxlon").val(toPrecision(bounds.getEast()));
|
||||
$("#maxlat").val(toPrecision(bounds.getNorth()));
|
||||
$("#minlon").val(bounds.getWest().toFixed(precision));
|
||||
$("#minlat").val(bounds.getSouth().toFixed(precision));
|
||||
$("#maxlon").val(bounds.getEast().toFixed(precision));
|
||||
$("#maxlat").val(bounds.getNorth().toFixed(precision));
|
||||
|
||||
mapnikSizeChanged();
|
||||
htmlUrlChanged();
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
//= require templates/notes/show
|
||||
//= require templates/notes/new
|
||||
|
||||
function initializeNotes(map) {
|
||||
var params = OSM.mapParams(),
|
||||
noteLayer = map.noteLayer,
|
||||
function initializeNotes(map, params) {
|
||||
var noteLayer = map.noteLayer,
|
||||
notes = {},
|
||||
newNote;
|
||||
|
||||
|
@ -50,7 +49,7 @@ function initializeNotes(map) {
|
|||
});
|
||||
|
||||
if (OSM.STATUS != 'api_offline' && OSM.STATUS != 'database_offline') {
|
||||
if (params.notes || (params.layers && params.layers.indexOf('N')) >= 0) {
|
||||
if (params.layers.indexOf(noteLayer.options.code) >= 0) {
|
||||
map.addLayer(noteLayer);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,22 +10,89 @@ L.extend(L.LatLngBounds.prototype, {
|
|||
});
|
||||
|
||||
L.extend(L.Map.prototype, {
|
||||
getLayersCode: function() {
|
||||
var layerConfig = '';
|
||||
for (var i in this._layers) { // TODO: map.eachLayer
|
||||
var layer = this._layers[i];
|
||||
if (layer.options && layer.options.code) {
|
||||
layerConfig += layer.options.code;
|
||||
}
|
||||
}
|
||||
return layerConfig;
|
||||
},
|
||||
getMapBaseLayerId: function() {
|
||||
for (var i in this._layers) { // TODO: map.eachLayer
|
||||
var layer = this._layers[i];
|
||||
if (layer.options && layer.options.keyid) return layer.options.keyid;
|
||||
}
|
||||
getLayersCode: function () {
|
||||
var layerConfig = '';
|
||||
for (var i in this._layers) { // TODO: map.eachLayer
|
||||
var layer = this._layers[i];
|
||||
if (layer.options && layer.options.code) {
|
||||
layerConfig += layer.options.code;
|
||||
}
|
||||
}
|
||||
return layerConfig;
|
||||
},
|
||||
|
||||
getMapBaseLayerId: function () {
|
||||
for (var i in this._layers) { // TODO: map.eachLayer
|
||||
var layer = this._layers[i];
|
||||
if (layer.options && layer.options.keyid) return layer.options.keyid;
|
||||
}
|
||||
},
|
||||
|
||||
getUrl: function(marker) {
|
||||
var precision = zoomPrecision(this.getZoom()),
|
||||
params = {};
|
||||
|
||||
if (marker && this.hasLayer(marker)) {
|
||||
params.mlat = marker.getLatLng().lat.toFixed(precision);
|
||||
params.mlon = marker.getLatLng().lng.toFixed(precision);
|
||||
}
|
||||
|
||||
var url = 'http://' + OSM.SERVER_URL + '/',
|
||||
query = querystring.stringify(params),
|
||||
hash = OSM.formatHash(this);
|
||||
|
||||
if (query) url += '?' + query;
|
||||
if (hash) url += hash;
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
getShortUrl: function(marker) {
|
||||
var zoom = this.getZoom(),
|
||||
latLng = marker && this.hasLayer(marker) ? marker.getLatLng() : this.getCenter(),
|
||||
str = '',
|
||||
char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~",
|
||||
x = Math.round((latLng.lng + 180.0) * ((1 << 30) / 90.0)),
|
||||
y = Math.round((latLng.lat + 90.0) * ((1 << 30) / 45.0)),
|
||||
// JavaScript only has to keep 32 bits of bitwise operators, so this has to be
|
||||
// done in two parts. each of the parts c1/c2 has 30 bits of the total in it
|
||||
// and drops the last 4 bits of the full 64 bit Morton code.
|
||||
c1 = interlace(x >>> 17, y >>> 17), c2 = interlace((x >>> 2) & 0x7fff, (y >>> 2) & 0x7fff),
|
||||
digit;
|
||||
|
||||
for (var i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
|
||||
digit = (c1 >> (24 - 6 * i)) & 0x3f;
|
||||
str += char_array.charAt(digit);
|
||||
}
|
||||
for (i = 5; i < Math.ceil((zoom + 8) / 3.0); ++i) {
|
||||
digit = (c2 >> (24 - 6 * (i - 5))) & 0x3f;
|
||||
str += char_array.charAt(digit);
|
||||
}
|
||||
for (i = 0; i < ((zoom + 8) % 3); ++i) str += "-";
|
||||
|
||||
// Called to interlace the bits in x and y, making a Morton code.
|
||||
function interlace(x, y) {
|
||||
x = (x | (x << 8)) & 0x00ff00ff;
|
||||
x = (x | (x << 4)) & 0x0f0f0f0f;
|
||||
x = (x | (x << 2)) & 0x33333333;
|
||||
x = (x | (x << 1)) & 0x55555555;
|
||||
y = (y | (y << 8)) & 0x00ff00ff;
|
||||
y = (y | (y << 4)) & 0x0f0f0f0f;
|
||||
y = (y | (y << 2)) & 0x33333333;
|
||||
y = (y | (y << 1)) & 0x55555555;
|
||||
return (x << 1) | y;
|
||||
}
|
||||
|
||||
if (marker && this.hasLayer(marker)) {
|
||||
str += '?m'
|
||||
}
|
||||
|
||||
return (window.location.hostname.match(/^www\.openstreetmap\.org/i) ?
|
||||
'http://osm.org/go/' : 'http://' + window.location.hostname + '/go/') + str;
|
||||
}
|
||||
});
|
||||
|
||||
L.Icon.Default.imagePath = <%= "#{asset_prefix}/images".to_json %>;
|
||||
|
||||
L.Hash.prototype.parseHash = OSM.parseHash;
|
||||
L.Hash.prototype.formatHash = OSM.formatHash;
|
||||
|
|
|
@ -60,8 +60,8 @@ L.OSM.share = function (options) {
|
|||
}
|
||||
|
||||
function update() {
|
||||
$shortLink.attr('href', options.getShortUrl(map));
|
||||
$longLink.attr('href', options.getUrl(map));
|
||||
$shortLink.attr('href', map.getShortUrl());
|
||||
$longLink.attr('href', map.getUrl());
|
||||
}
|
||||
|
||||
function select() {
|
||||
|
|
|
@ -23,7 +23,7 @@ OSM = {
|
|||
},
|
||||
|
||||
mapParams: function (search) {
|
||||
var params = {}, mapParams = {}, loc;
|
||||
var params = {}, mapParams = {}, bounds, loc;
|
||||
|
||||
search = (search || window.location.search).replace('?', '').split(/&|;/);
|
||||
|
||||
|
@ -41,10 +41,6 @@ OSM = {
|
|||
mapParams.mlat = parseFloat(params.mlat);
|
||||
}
|
||||
|
||||
if (params.layers) {
|
||||
mapParams.layers = params.layers;
|
||||
}
|
||||
|
||||
if (params.node || params.way || params.relation) {
|
||||
mapParams.object_zoom = true;
|
||||
|
||||
|
@ -57,21 +53,35 @@ OSM = {
|
|||
}
|
||||
}
|
||||
|
||||
// Decide on a lat lon to initialise the map with. Various ways of doing this
|
||||
if (params.bbox) {
|
||||
var bbox = params.bbox.split(",");
|
||||
mapParams.bbox = true;
|
||||
mapParams.minlon = parseFloat(bbox[0]);
|
||||
mapParams.minlat = parseFloat(bbox[1]);
|
||||
mapParams.maxlon = parseFloat(bbox[2]);
|
||||
mapParams.maxlat = parseFloat(bbox[3]);
|
||||
mapParams.object_zoom = false;
|
||||
params.bbox = params.bbox.split(',');
|
||||
bounds = L.latLngBounds(
|
||||
[parseFloat(params.bbox[1]),
|
||||
parseFloat(params.bbox[0])],
|
||||
[parseFloat(params.bbox[3]),
|
||||
parseFloat(params.bbox[2])]);
|
||||
} else if (params.minlon && params.minlat && params.maxlon && params.maxlat) {
|
||||
mapParams.bbox = true;
|
||||
mapParams.minlon = parseFloat(params.minlon);
|
||||
mapParams.minlat = parseFloat(params.minlat);
|
||||
mapParams.maxlon = parseFloat(params.maxlon);
|
||||
mapParams.maxlat = parseFloat(params.maxlat);
|
||||
bounds = L.latLngBounds(
|
||||
[parseFloat(params.minlat),
|
||||
parseFloat(params.minlon)],
|
||||
[parseFloat(params.maxlat),
|
||||
parseFloat(params.maxlon)]);
|
||||
}
|
||||
|
||||
if (params.box === 'yes') {
|
||||
mapParams.box = bounds;
|
||||
}
|
||||
|
||||
var hash = OSM.parseHash(location.hash);
|
||||
|
||||
// Decide on a map starting position. Various ways of doing this.
|
||||
if (hash.lat && hash.lon) {
|
||||
mapParams.lon = hash.center.lng;
|
||||
mapParams.lat = hash.center.lat;
|
||||
mapParams.zoom = hash.zoom;
|
||||
mapParams.object_zoom = false;
|
||||
} else if (bounds) {
|
||||
mapParams.bounds = bounds;
|
||||
mapParams.object_zoom = false;
|
||||
} else if (params.lon && params.lat) {
|
||||
mapParams.lon = parseFloat(params.lon);
|
||||
|
@ -88,30 +98,23 @@ OSM = {
|
|||
mapParams.lon = parseFloat(loc[0]);
|
||||
mapParams.lat = parseFloat(loc[1]);
|
||||
mapParams.zoom = parseInt(loc[2]);
|
||||
mapParams.layers = loc[3];
|
||||
} else if (OSM.home) {
|
||||
mapParams.lon = OSM.home.lon;
|
||||
mapParams.lat = OSM.home.lat;
|
||||
mapParams.zoom = 10;
|
||||
} else if (OSM.location) {
|
||||
mapParams.bbox = true;
|
||||
mapParams.minlon = OSM.location.minlon;
|
||||
mapParams.minlat = OSM.location.minlat;
|
||||
mapParams.maxlon = OSM.location.maxlon;
|
||||
mapParams.maxlat = OSM.location.maxlat;
|
||||
mapParams.bounds = L.latLngBounds(
|
||||
[OSM.location.minlat,
|
||||
OSM.location.minlon],
|
||||
[OSM.location.maxlat,
|
||||
OSM.location.maxlon]);
|
||||
} else {
|
||||
mapParams.lon = -0.1;
|
||||
mapParams.lat = 51.5;
|
||||
mapParams.zoom = parseInt(params.zoom || 5);
|
||||
}
|
||||
|
||||
if (mapParams.bbox) {
|
||||
mapParams.box = params.box == "yes";
|
||||
mapParams.lon = (mapParams.minlon + mapParams.maxlon) / 2;
|
||||
mapParams.lat = (mapParams.minlat + mapParams.maxlat) / 2;
|
||||
}
|
||||
|
||||
mapParams.notes = params.notes == "yes";
|
||||
mapParams.layers = hash.layers || (loc && loc[3]) || '';
|
||||
|
||||
if (params.note) {
|
||||
mapParams.note = parseInt(params.note);
|
||||
|
@ -123,5 +126,41 @@ OSM = {
|
|||
}
|
||||
|
||||
return mapParams;
|
||||
},
|
||||
|
||||
parseHash: function(hash) {
|
||||
if (hash.indexOf('#') === 0) {
|
||||
hash = hash.substr(1);
|
||||
}
|
||||
hash = querystring.parse(hash);
|
||||
var args = L.Hash.parseHash(hash.map || '') || {};
|
||||
if (hash.layers) args.layers = hash.layers;
|
||||
return args;
|
||||
},
|
||||
|
||||
formatHash: function(args) {
|
||||
if (args instanceof L.Map) {
|
||||
args = {
|
||||
lat: args.getCenter().lat,
|
||||
lon: args.getCenter().lng,
|
||||
zoom: args.getZoom(),
|
||||
layers: args.getLayersCode()
|
||||
};
|
||||
}
|
||||
|
||||
var precision = zoomPrecision(args.zoom),
|
||||
hash = '#map=' + args.zoom +
|
||||
'/' + args.lat.toFixed(precision) +
|
||||
'/' + args.lon.toFixed(precision);
|
||||
|
||||
if (args.layers) {
|
||||
args.layers = args.layers.replace('M', '');
|
||||
}
|
||||
|
||||
if (args.layers) {
|
||||
hash += '&layers=' + args.layers;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,6 +8,23 @@ class SiteController < ApplicationController
|
|||
before_filter :require_oauth, :only => [:index]
|
||||
|
||||
def index
|
||||
anchor = []
|
||||
|
||||
if params[:lat] && params[:lon]
|
||||
anchor << "map=#{params.delete(:zoom) || 5}/#{params.delete(:lat)}/#{params.delete(:lon)}"
|
||||
end
|
||||
|
||||
if params[:layers]
|
||||
anchor << "layers=#{params.delete(:layers)}"
|
||||
elsif params.delete(:notes) == 'yes'
|
||||
anchor << "layers=N"
|
||||
end
|
||||
|
||||
if anchor.present?
|
||||
redirect_to params.merge(:anchor => anchor.join('&'))
|
||||
return
|
||||
end
|
||||
|
||||
unless STATUS == :database_readonly or STATUS == :database_offline
|
||||
session[:location] ||= OSM::IPLocation(request.env['REMOTE_ADDR'])
|
||||
end
|
||||
|
@ -15,19 +32,18 @@ class SiteController < ApplicationController
|
|||
|
||||
def permalink
|
||||
lon, lat, zoom = ShortLink::decode(params[:code])
|
||||
new_params = params.clone
|
||||
new_params.delete :code
|
||||
new_params = params.except(:code, :lon, :lat, :zoom)
|
||||
|
||||
if new_params.has_key? :m
|
||||
new_params.delete :m
|
||||
new_params[:mlat] = lat
|
||||
new_params[:mlon] = lon
|
||||
else
|
||||
new_params[:lat] = lat
|
||||
new_params[:lon] = lon
|
||||
end
|
||||
new_params[:zoom] = zoom
|
||||
|
||||
new_params[:controller] = 'site'
|
||||
new_params[:action] = 'index'
|
||||
new_params[:anchor] = "#{zoom}/#{lat}/#{lon}"
|
||||
|
||||
redirect_to new_params
|
||||
end
|
||||
|
||||
|
|
|
@ -85,7 +85,12 @@
|
|||
});
|
||||
});
|
||||
|
||||
function mapMoved(lon, lat, zoom, minlon, minlat, maxlon, maxlat) {
|
||||
var mapMoved = $.throttle(250, function(lon, lat, zoom, minlon, minlat, maxlon, maxlat) {
|
||||
updatelinks({ lon: lon, lat: lat }, zoom, null, [[minlat, minlon], [maxlat, maxlon]]);
|
||||
}
|
||||
|
||||
var hash = OSM.formatHash({ lon: lon, lat: lat, zoom: zoom });
|
||||
if (hash !== location.hash) {
|
||||
location.replace(hash);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
oauth_token_secret: "<%= token.secret %>"
|
||||
});
|
||||
|
||||
id.map().on('move.embed', function() {
|
||||
id.map().on('move.embed', parent.$.throttle(250, function() {
|
||||
var extent = id.map().extent(),
|
||||
zoom = ~~id.map().zoom(),
|
||||
center = id.map().center();
|
||||
|
@ -46,7 +46,16 @@
|
|||
extent[0][0]],
|
||||
[extent[1][1],
|
||||
extent[1][0]]]);
|
||||
});
|
||||
|
||||
// 0ms timeout to avoid iframe JS context weirdness.
|
||||
// http://bl.ocks.org/jfirebaugh/5439412
|
||||
parent.setTimeout(function() {
|
||||
var hash = parent.OSM.formatHash({ lon: center[0], lat: center[1], zoom: zoom });
|
||||
if (hash !== parent.location.hash) {
|
||||
parent.location.replace(hash);
|
||||
}
|
||||
}, 0);
|
||||
}));
|
||||
|
||||
parent.$("body").on("click", "a.set_position", function (e) {
|
||||
e.preventDefault();
|
||||
|
@ -54,7 +63,7 @@
|
|||
|
||||
// 0ms timeout to avoid iframe JS context weirdness.
|
||||
// http://bl.ocks.org/jfirebaugh/5439412
|
||||
setTimeout(function() {
|
||||
parent.setTimeout(function() {
|
||||
id.map().centerZoom(
|
||||
[data.lon, data.lat],
|
||||
Math.max(data.zoom || 15, 13));
|
||||
|
|
|
@ -72,7 +72,29 @@ class SiteControllerTest < ActionController::TestCase
|
|||
assert_template 'index'
|
||||
assert_site_partials
|
||||
end
|
||||
|
||||
|
||||
def test_index_redirect
|
||||
get :index, :lat => 4, :lon => 5
|
||||
assert_redirected_to :controller => :site, :action => 'index', :anchor => 'map=5/4/5'
|
||||
|
||||
get :index, :lat => 4, :lon => 5, :zoom => 3
|
||||
assert_redirected_to :controller => :site, :action => 'index', :anchor => 'map=3/4/5'
|
||||
|
||||
get :index, :layers => 'T'
|
||||
assert_redirected_to :controller => :site, :action => 'index', :anchor => 'layers=T'
|
||||
|
||||
get :index, :notes => 'yes'
|
||||
assert_redirected_to :controller => :site, :action => 'index', :anchor => 'layers=N'
|
||||
|
||||
get :index, :lat => 4, :lon => 5, :zoom => 3, :layers => 'T'
|
||||
assert_redirected_to :controller => :site, :action => 'index', :anchor => 'map=3/4/5&layers=T'
|
||||
end
|
||||
|
||||
def test_permalink
|
||||
get :permalink, :code => 'wBz3--'
|
||||
assert_redirected_to :controller => :site, :action => 'index', :anchor => '3/4.8779296875/3.955078125'
|
||||
end
|
||||
|
||||
# Get the edit page
|
||||
def test_edit
|
||||
get :edit
|
||||
|
|
252
vendor/assets/jquery/jquery.throttle-debounce.js
vendored
Normal file
252
vendor/assets/jquery/jquery.throttle-debounce.js
vendored
Normal file
|
@ -0,0 +1,252 @@
|
|||
/*!
|
||||
* jQuery throttle / debounce - v1.1 - 3/7/2010
|
||||
* http://benalman.com/projects/jquery-throttle-debounce-plugin/
|
||||
*
|
||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://benalman.com/about/license/
|
||||
*/
|
||||
|
||||
// Script: jQuery throttle / debounce: Sometimes, less is more!
|
||||
//
|
||||
// *Version: 1.1, Last updated: 3/7/2010*
|
||||
//
|
||||
// Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
|
||||
// GitHub - http://github.com/cowboy/jquery-throttle-debounce/
|
||||
// Source - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
|
||||
// (Minified) - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
|
||||
//
|
||||
// About: License
|
||||
//
|
||||
// Copyright (c) 2010 "Cowboy" Ben Alman,
|
||||
// Dual licensed under the MIT and GPL licenses.
|
||||
// http://benalman.com/about/license/
|
||||
//
|
||||
// About: Examples
|
||||
//
|
||||
// These working examples, complete with fully commented code, illustrate a few
|
||||
// ways in which this plugin can be used.
|
||||
//
|
||||
// Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
|
||||
// Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
|
||||
//
|
||||
// About: Support and Testing
|
||||
//
|
||||
// Information about what version or versions of jQuery this plugin has been
|
||||
// tested with, what browsers it has been tested in, and where the unit tests
|
||||
// reside (so you can test it yourself).
|
||||
//
|
||||
// jQuery Versions - none, 1.3.2, 1.4.2
|
||||
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
|
||||
// Unit Tests - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
|
||||
//
|
||||
// About: Release History
|
||||
//
|
||||
// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
|
||||
// executed later than they should. Reworked a fair amount of internal
|
||||
// logic as well.
|
||||
// 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
|
||||
// from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
|
||||
// no_trailing throttle parameter and debounce functionality.
|
||||
//
|
||||
// Topic: Note for non-jQuery users
|
||||
//
|
||||
// jQuery isn't actually required for this plugin, because nothing internal
|
||||
// uses any jQuery methods or properties. jQuery is just used as a namespace
|
||||
// under which these methods can exist.
|
||||
//
|
||||
// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
|
||||
// when this plugin is loaded, the method described below will be created in
|
||||
// the `Cowboy` namespace. Usage will be exactly the same, but instead of
|
||||
// $.method() or jQuery.method(), you'll need to use Cowboy.method().
|
||||
|
||||
(function(window,undefined){
|
||||
'$:nomunge'; // Used by YUI compressor.
|
||||
|
||||
// Since jQuery really isn't required for this plugin, use `jQuery` as the
|
||||
// namespace only if it already exists, otherwise use the `Cowboy` namespace,
|
||||
// creating it if necessary.
|
||||
var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
|
||||
|
||||
// Internal method reference.
|
||||
jq_throttle;
|
||||
|
||||
// Method: jQuery.throttle
|
||||
//
|
||||
// Throttle execution of a function. Especially useful for rate limiting
|
||||
// execution of handlers on events like resize and scroll. If you want to
|
||||
// rate-limit execution of a function to a single time, see the
|
||||
// <jQuery.debounce> method.
|
||||
//
|
||||
// In this visualization, | is a throttled-function call and X is the actual
|
||||
// callback execution:
|
||||
//
|
||||
// > Throttled with `no_trailing` specified as false or unspecified:
|
||||
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
|
||||
// > X X X X X X X X X X X X
|
||||
// >
|
||||
// > Throttled with `no_trailing` specified as true:
|
||||
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
|
||||
// > X X X X X X X X X X
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
|
||||
// >
|
||||
// > jQuery('selector').bind( 'someevent', throttled );
|
||||
// > jQuery('selector').unbind( 'someevent', throttled );
|
||||
//
|
||||
// This also works in jQuery 1.4+:
|
||||
//
|
||||
// > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
|
||||
// > jQuery('selector').unbind( 'someevent', callback );
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// delay - (Number) A zero-or-greater delay in milliseconds. For event
|
||||
// callbacks, values around 100 or 250 (or even higher) are most useful.
|
||||
// no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
|
||||
// true, callback will only execute every `delay` milliseconds while the
|
||||
// throttled-function is being called. If no_trailing is false or
|
||||
// unspecified, callback will be executed one final time after the last
|
||||
// throttled-function call. (After the throttled-function has not been
|
||||
// called for `delay` milliseconds, the internal counter is reset)
|
||||
// callback - (Function) A function to be executed after delay milliseconds.
|
||||
// The `this` context and all arguments are passed through, as-is, to
|
||||
// `callback` when the throttled-function is executed.
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// (Function) A new, throttled, function.
|
||||
|
||||
$.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
|
||||
// After wrapper has stopped being called, this timeout ensures that
|
||||
// `callback` is executed at the proper times in `throttle` and `end`
|
||||
// debounce modes.
|
||||
var timeout_id,
|
||||
|
||||
// Keep track of the last time `callback` was executed.
|
||||
last_exec = 0;
|
||||
|
||||
// `no_trailing` defaults to falsy.
|
||||
if ( typeof no_trailing !== 'boolean' ) {
|
||||
debounce_mode = callback;
|
||||
callback = no_trailing;
|
||||
no_trailing = undefined;
|
||||
}
|
||||
|
||||
// The `wrapper` function encapsulates all of the throttling / debouncing
|
||||
// functionality and when executed will limit the rate at which `callback`
|
||||
// is executed.
|
||||
function wrapper() {
|
||||
var that = this,
|
||||
elapsed = +new Date() - last_exec,
|
||||
args = arguments;
|
||||
|
||||
// Execute `callback` and update the `last_exec` timestamp.
|
||||
function exec() {
|
||||
last_exec = +new Date();
|
||||
callback.apply( that, args );
|
||||
};
|
||||
|
||||
// If `debounce_mode` is true (at_begin) this is used to clear the flag
|
||||
// to allow future `callback` executions.
|
||||
function clear() {
|
||||
timeout_id = undefined;
|
||||
};
|
||||
|
||||
if ( debounce_mode && !timeout_id ) {
|
||||
// Since `wrapper` is being called for the first time and
|
||||
// `debounce_mode` is true (at_begin), execute `callback`.
|
||||
exec();
|
||||
}
|
||||
|
||||
// Clear any existing timeout.
|
||||
timeout_id && clearTimeout( timeout_id );
|
||||
|
||||
if ( debounce_mode === undefined && elapsed > delay ) {
|
||||
// In throttle mode, if `delay` time has been exceeded, execute
|
||||
// `callback`.
|
||||
exec();
|
||||
|
||||
} else if ( no_trailing !== true ) {
|
||||
// In trailing throttle mode, since `delay` time has not been
|
||||
// exceeded, schedule `callback` to execute `delay` ms after most
|
||||
// recent execution.
|
||||
//
|
||||
// If `debounce_mode` is true (at_begin), schedule `clear` to execute
|
||||
// after `delay` ms.
|
||||
//
|
||||
// If `debounce_mode` is false (at end), schedule `callback` to
|
||||
// execute after `delay` ms.
|
||||
timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
|
||||
}
|
||||
};
|
||||
|
||||
// Set the guid of `wrapper` function to the same of original callback, so
|
||||
// it can be removed in jQuery 1.4+ .unbind or .die by using the original
|
||||
// callback as a reference.
|
||||
if ( $.guid ) {
|
||||
wrapper.guid = callback.guid = callback.guid || $.guid++;
|
||||
}
|
||||
|
||||
// Return the wrapper function.
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
// Method: jQuery.debounce
|
||||
//
|
||||
// Debounce execution of a function. Debouncing, unlike throttling,
|
||||
// guarantees that a function is only executed a single time, either at the
|
||||
// very beginning of a series of calls, or at the very end. If you want to
|
||||
// simply rate-limit execution of a function, see the <jQuery.throttle>
|
||||
// method.
|
||||
//
|
||||
// In this visualization, | is a debounced-function call and X is the actual
|
||||
// callback execution:
|
||||
//
|
||||
// > Debounced with `at_begin` specified as false or unspecified:
|
||||
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
|
||||
// > X X
|
||||
// >
|
||||
// > Debounced with `at_begin` specified as true:
|
||||
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
|
||||
// > X X
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
|
||||
// >
|
||||
// > jQuery('selector').bind( 'someevent', debounced );
|
||||
// > jQuery('selector').unbind( 'someevent', debounced );
|
||||
//
|
||||
// This also works in jQuery 1.4+:
|
||||
//
|
||||
// > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
|
||||
// > jQuery('selector').unbind( 'someevent', callback );
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// delay - (Number) A zero-or-greater delay in milliseconds. For event
|
||||
// callbacks, values around 100 or 250 (or even higher) are most useful.
|
||||
// at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
|
||||
// unspecified, callback will only be executed `delay` milliseconds after
|
||||
// the last debounced-function call. If at_begin is true, callback will be
|
||||
// executed only at the first debounced-function call. (After the
|
||||
// throttled-function has not been called for `delay` milliseconds, the
|
||||
// internal counter is reset)
|
||||
// callback - (Function) A function to be executed after delay milliseconds.
|
||||
// The `this` context and all arguments are passed through, as-is, to
|
||||
// `callback` when the debounced-function is executed.
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// (Function) A new, debounced, function.
|
||||
|
||||
$.debounce = function( delay, at_begin, callback ) {
|
||||
return callback === undefined
|
||||
? jq_throttle( delay, at_begin, false )
|
||||
: jq_throttle( delay, callback, at_begin !== false );
|
||||
};
|
||||
|
||||
})(this);
|
162
vendor/assets/leaflet/leaflet.hash.js
vendored
Normal file
162
vendor/assets/leaflet/leaflet.hash.js
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
(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) {
|
||||
this.onHashChange = L.Util.bind(this.onHashChange, this);
|
||||
|
||||
if (map) {
|
||||
this.init(map);
|
||||
}
|
||||
};
|
||||
|
||||
L.Hash.parseHash = function(hash) {
|
||||
if(hash.indexOf('#') === 0) {
|
||||
hash = hash.substr(1);
|
||||
}
|
||||
var args = hash.split("/");
|
||||
if (args.length == 3) {
|
||||
var zoom = parseInt(args[0], 10),
|
||||
lat = parseFloat(args[1]),
|
||||
lon = parseFloat(args[2]);
|
||||
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
|
||||
return false;
|
||||
} else {
|
||||
return {
|
||||
center: new L.LatLng(lat, lon),
|
||||
zoom: zoom
|
||||
};
|
||||
}
|
||||
} 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));
|
||||
|
||||
return "#" + [zoom,
|
||||
center.lat.toFixed(precision),
|
||||
center.lng.toFixed(precision)
|
||||
].join("/");
|
||||
},
|
||||
|
||||
L.Hash.prototype = {
|
||||
map: null,
|
||||
lastHash: null,
|
||||
|
||||
parseHash: L.Hash.parseHash,
|
||||
formatHash: L.Hash.formatHash,
|
||||
|
||||
init: function(map) {
|
||||
this.map = map;
|
||||
|
||||
// reset the hash
|
||||
this.lastHash = null;
|
||||
this.onHashChange();
|
||||
|
||||
if (!this.isListening) {
|
||||
this.startListening();
|
||||
}
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
var parsed = this.parseHash(hash);
|
||||
if (parsed) {
|
||||
this.movingMap = true;
|
||||
|
||||
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", 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", this.onMapMove, this);
|
||||
|
||||
if (HAS_HASHCHANGE) {
|
||||
L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
|
||||
} else {
|
||||
clearInterval(this.hashChangeInterval);
|
||||
}
|
||||
this.isListening = false;
|
||||
}
|
||||
};
|
||||
L.hash = function(map) {
|
||||
return new L.Hash(map);
|
||||
};
|
||||
L.Map.prototype.addHash = function() {
|
||||
this._hash = L.hash(this);
|
||||
};
|
||||
L.Map.prototype.removeHash = function() {
|
||||
this._hash.remove();
|
||||
};
|
||||
})(window);
|
Loading…
Add table
Add a link
Reference in a new issue