2017-05-11 01:47:46 +00:00
|
|
|
import L from 'leaflet';
|
|
|
|
import 'leaflet-hash';
|
|
|
|
import fm from '../app';
|
|
|
|
|
|
|
|
fm.app.directive("fmHash", function($rootScope, fmUtils, $q) {
|
|
|
|
return {
|
|
|
|
restrict: "A",
|
|
|
|
require: "facilmap",
|
|
|
|
link: function($scope, element, attrs, map) {
|
|
|
|
let loadInitialViewBkp = map.loadInitialView.bind(map);
|
|
|
|
map.loadInitialView = function() {
|
|
|
|
map.loadInitialView = loadInitialViewBkp;
|
|
|
|
return (hasLocationHash() ? $q.resolve() : loadInitialViewBkp(...arguments)).then((res) => {
|
|
|
|
init();
|
|
|
|
return res;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
let hasLocationHash = () => {
|
|
|
|
return !!parseHash(location.hash, true);
|
|
|
|
};
|
|
|
|
|
|
|
|
let init = () => {
|
|
|
|
var hashControl = new L.Hash(map.map);
|
|
|
|
|
|
|
|
hashControl.parseHash = parseHash.fmWrapApply($rootScope);
|
|
|
|
hashControl.formatHash = formatHash;
|
|
|
|
|
|
|
|
// hashControl calls hashControl.onHashChange(), which will run hashControl.update() with 100ms delay.
|
|
|
|
// In the meantime, we will already set the map view, which triggers hashControl.onMapMove and replace
|
|
|
|
// the location hash. So we have to call hashControl.update() right now.
|
|
|
|
hashControl.update();
|
|
|
|
clearTimeout(hashControl.changeTimeout);
|
|
|
|
hashControl.changeTimeout = null;
|
|
|
|
|
|
|
|
map.map.on("layeradd", hashControl.onMapMove, hashControl);
|
|
|
|
map.map.on("layerremove", hashControl.onMapMove, hashControl);
|
2017-11-17 17:27:37 +00:00
|
|
|
map.mapEvents.$on("searchchange", () => {
|
|
|
|
setTimeout(() => {
|
|
|
|
hashControl.onMapMove();
|
|
|
|
}, 0);
|
|
|
|
});
|
2017-05-11 01:47:46 +00:00
|
|
|
map.client.on("filter", hashControl.onMapMove.bind(hashControl));
|
|
|
|
};
|
|
|
|
|
|
|
|
let parseHash = (hash, noApply) => {
|
|
|
|
if(hash.indexOf('#') === 0) {
|
|
|
|
hash = hash.substr(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
var args;
|
|
|
|
if(hash.indexOf("=") != -1 && hash.indexOf("/") == -1)
|
|
|
|
args = oldToNew(hash);
|
|
|
|
else
|
|
|
|
args = hash.split("/").map(decodeURIComponentTolerantly);
|
|
|
|
|
|
|
|
var ret = L.Hash.parseHash(args.slice(0, 3).join("/"));
|
|
|
|
|
|
|
|
if(!noApply) {
|
|
|
|
// This gets called just in L.Hash.update(), so we can already add/remove the layers here
|
|
|
|
|
|
|
|
var l = args[3] && args[3].split("-");
|
|
|
|
if(l && l.length > 0) {
|
|
|
|
for(var i in map.layers) {
|
|
|
|
if(l.indexOf(i) == -1) {
|
|
|
|
if(map.map.hasLayer(map.layers[i]))
|
|
|
|
map.map.removeLayer(map.layers[i]);
|
|
|
|
} else if(!map.map.hasLayer(map.layers[i]))
|
|
|
|
map.map.addLayer(map.layers[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(map.searchUi)
|
|
|
|
map.searchUi.search(args[4] || "", !!ret, args[4] ? (ret && !fmUtils.isSearchId(args[4])) : null);
|
|
|
|
|
|
|
|
map.client.setFilter(args[5] || "");
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
let formatHash = (mapObj) => {
|
|
|
|
var ret = L.Hash.formatHash(mapObj);
|
|
|
|
|
|
|
|
var l = [ ];
|
|
|
|
for(var i in map.layers) {
|
|
|
|
if(mapObj.hasLayer(map.layers[i]))
|
|
|
|
l.push(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
var additionalParts = [ l.join("-") ];
|
|
|
|
|
|
|
|
var searchHash = map.searchUi && map.searchUi.getCurrentSearchForHash();
|
|
|
|
if(searchHash)
|
|
|
|
additionalParts.push(searchHash);
|
|
|
|
|
|
|
|
if(map.client.filterExpr) {
|
|
|
|
if(!searchHash)
|
|
|
|
additionalParts.push("");
|
|
|
|
additionalParts.push(map.client.filterExpr);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret += "/" + additionalParts.map(encodeURIComponent).join("/");
|
|
|
|
|
2017-11-17 17:27:37 +00:00
|
|
|
if(parent !== window) {
|
|
|
|
parent.postMessage({
|
|
|
|
type: "facilmap-hash",
|
|
|
|
hash: ret.replace(/^#/, "")
|
|
|
|
}, "*");
|
|
|
|
}
|
|
|
|
|
2017-05-11 01:47:46 +00:00
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
let decodeQueryString = (str) => {
|
|
|
|
var obj = { };
|
|
|
|
var str_split = str.split(/[;&]/);
|
|
|
|
for(var i=0; i<str_split.length; i++) {
|
|
|
|
var equal_sign = str_split[i].indexOf("=");
|
|
|
|
if(equal_sign < 1) continue;
|
|
|
|
|
|
|
|
var key = str_split[i].substr(0, equal_sign);
|
|
|
|
var arr_match = key.match(/(\[[^\]]*\]|\.[^.]+)+$/);
|
|
|
|
if(arr_match) {
|
|
|
|
var arr_indexes = arr_match[0].replace(/^[.\[]/, "").replace(/\]$/, "").split(/\]\[|\./);
|
|
|
|
arr_indexes.unshift(key.substr(0, key.length-arr_match[0].length));
|
|
|
|
var cur_el = obj;
|
|
|
|
for(var j=0; j<arr_indexes.length; j++) {
|
|
|
|
var cur_key = decodeURIComponentTolerantly(arr_indexes[j]);
|
|
|
|
if(cur_key.length == 0) {
|
|
|
|
cur_key = 0;
|
|
|
|
while(typeof cur_el[cur_key] != "undefined")
|
|
|
|
cur_key++;
|
|
|
|
}
|
|
|
|
if(j == arr_indexes.length-1)
|
|
|
|
cur_el[cur_key] = decodeURIComponentTolerantly(str_split[i].substr(equal_sign+1));
|
|
|
|
else {
|
|
|
|
if(!cur_el[cur_key] || typeof cur_el[cur_key] != "object")
|
|
|
|
cur_el[cur_key] = { };
|
|
|
|
cur_el = cur_el[cur_key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
obj[decodeURIComponentTolerantly(key)] = decodeURIComponentTolerantly(str_split[i].substr(equal_sign+1));
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
};
|
|
|
|
|
|
|
|
let decodeURIComponentTolerantly = (str) => {
|
|
|
|
try {
|
|
|
|
return decodeURIComponent(str);
|
|
|
|
} catch(e) {
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let oldToNew = (str) => {
|
|
|
|
// Example URLs from FacilMap 1:
|
|
|
|
// https://facilmap.org/#lon=11.7268775;lat=53.04781777;zoom=9;layer=MSfR;c.s.type=fastest;c.s.medium=car;q.0=Berlin;q.1=Hamburg;q.2=Bremen
|
|
|
|
// https://facilmap.org/#lon=13.4385964;lat=52.5198535;zoom=11;layer=MSfR;q=Berlin
|
|
|
|
// https://facilmap.org/#lon=13.4385964;lat=52.5198535;zoom=11;layer=MSfR;l.OPTM.visibility=1;q=Berlin
|
|
|
|
|
|
|
|
var obj = decodeQueryString(str);
|
|
|
|
|
|
|
|
var ret = [ obj.zoom, obj.lat, obj.lon ];
|
|
|
|
|
|
|
|
var layers = [ ];
|
|
|
|
if(obj.layer)
|
|
|
|
layers.push(obj.layer);
|
|
|
|
for(var i in obj.l || { }) {
|
|
|
|
if(obj.l[i].visibility && map.layers[i])
|
|
|
|
layers.push(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.push(layers.join("-"));
|
|
|
|
|
|
|
|
if(typeof obj.q == "string")
|
|
|
|
ret.push(obj.q);
|
|
|
|
else if(typeof obj.s == "string")
|
|
|
|
ret.push(obj.s);
|
|
|
|
else if(typeof obj.q == "object") {
|
|
|
|
Object.keys(obj.q).sort(function(a, b){return a-b}).forEach(function(i) {
|
|
|
|
ret.push(obj.q[i]);
|
|
|
|
});
|
|
|
|
|
|
|
|
if(obj.c && obj.c.s && obj.c.s.medium)
|
|
|
|
ret.push(obj.c.s.medium != "foot" ? obj.c.s.medium : "pedestrian");
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|