Skip to content
Snippets Groups Projects
Commit ac081591 authored by xaralis's avatar xaralis
Browse files

feat(district,maps_utils): improve map back&foward navigation

parent 9f8c63f4
No related branches found
No related tags found
2 merge requests!510Release,!506More map improvements
Pipeline #8176 passed
......@@ -68,7 +68,7 @@
</div>
<section>
<h2 class="head-heavy-base mt-8 mb-4">{{ page.category_list_title|default:"Přehled dle kategorií" }}</h2>
<h2 id="kategorie" class="head-heavy-base mt-8 mb-4">{{ page.category_list_title|default:"Přehled dle kategorií" }}</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-8">
{% for category, features in features_by_category %}
......
......@@ -327,7 +327,7 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", {
*/
const onEachFeature = (feature, layer) => {
const markerPosLatLng = [];
const onClick = (evt) => this.zoomToLayer(layer);
const onClick = (evt) => this.zoomToLayer(layer, true);
const markerForPolyCoords = (coords) => {
// Find pole of inaccessibility (not centroid) for the polygon
......@@ -382,7 +382,7 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", {
addMarker(feature, pos, onClick);
// Bind click event on the layer.
layer.on({
click: (evt) => this.zoomToLayer(evt.target),
click: (evt) => this.zoomToLayer(evt.target, true),
});
});
}
......@@ -409,48 +409,56 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", {
this.map.panTo(this.layer.getBounds().getCenter());
}
// If hash is present when starting, locate the item and zoom to it.
if (window.location.hash) {
this.zoomToItemBySlugUrl(window.location.hash.substring(1));
}
// Initial check - open item detail if in URL.
this.onUserNavigation();
// Listen to URL changes when user triggers browser navigation.
window.addEventListener("popstate", this.onUserNavigation);
// Listen to hashbang changes when user users browser history navigation.
window.addEventListener("hashchange", this.onHashChange, false);
},
/**
* Stores item's url in the hashbang.
* Stores item's slug in URL `item` query param.
*
* @param {Object} item
*/
setUrlHash(item) {
pushToUrl(item) {
const url = new URL(window.location);
if (item === null) {
history.replaceState({}, null, "#");
url.searchParams.delete("item");
history.pushState({}, "", url);
} else {
history.pushState({}, item.title, "#" + item.slug);
url.searchParams.set("item", item.slug);
history.pushState({}, "", url);
}
},
/**
* Called when URL hash changes. Will display detail
* Called when user navigates. Will display detail
* of corresponding item if such exist.
*
* @param {Event} evt
*/
onHashChange(evt) {
const urlBits = evt.newURL.split("#");
if (urlBits.length == 2 && urlBits[1]) {
this.zoomToItemBySlugUrl(urlBits[1]);
} else {
this.closeItemInfo();
onUserNavigation(evt) {
const urlParams = new URLSearchParams(window.location.search);
// If query is present when starting, locate the item and zoom to it.
if (urlParams.has("item")) {
this.zoomToFeature(urlParams.get("item"), false);
} else if (this.currentItem) {
this.closeItemInfo(false);
}
},
/**
* Hide current item detail, drop it from URL.
* @param {Boolean} updateUrl whether to push new state to history.
*/
closeItemInfo() {
closeItemInfo(updateUrl = true) {
if (this.currentItem) {
this.currentItem = null;
this.setUrlHash(null);
if (updateUrl) {
this.pushToUrl(null);
}
}
},
/**
......@@ -464,55 +472,44 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", {
* Zoom to a point.
*
* @param {L.Latlng} Latlng
* @param {Boolean} pushState whether to push new state to history.
* @param {Object} feature
* @param {Boolean} updateUrl whether to push new state to history.
*/
zoomToPoint(latlng, feature, updateUrl = true) {
this.map.panTo(latlng);
this.currentItem = feature.properties;
if (updateUrl) {
this.setUrlHash(this.currentItem);
this.pushToUrl(this.currentItem);
}
},
/**
* Zoom to a detail of a layer.
*
* @param {L.Layer} layer
* @param {Boolean} pushState whether to push new state to history.
* @param {Boolean} updateUrl whether to push new state to history.
*/
zoomToLayer(layer, updateUrl = true) {
this.map.fitBounds(layer.getBounds());
this.currentItem = layer.feature.properties;
if (updateUrl) {
this.setUrlHash(this.currentItem);
}
},
/**
* Zoom to a cateogry item. Wraps `zoomTo`.
*
* @param {Object} category
* @param {Object} item
*/
zoomToCategoryItem(category, item) {
const layer = Object.values(this.layer._layers).find(
(l) => l.feature.properties.id == item.properties.id
);
if (layer) {
this.zoomToLayer(layer);
this.pushToUrl(this.currentItem);
}
},
/**
* Zoom to a item with corresponding slugified URL.
* Zoom to a feature with corresponding slugified URL.
* Only extracted to make things DRY, will not update the URL!
*
* @param {String} slugUrl
* @param {Boolean} updateUrl whether to push new state to history.
*/
zoomToItemBySlugUrl(slugUrl) {
zoomToFeature(slugUrl, updateUrl = true) {
const layer = Object.values(this.layer._layers).find(
(l) => l.feature.properties.slug == slugUrl
);
if (layer) {
this.zoomToLayer(layer, false);
this.zoomToLayer(layer, updateUrl);
}
},
/**
......@@ -546,7 +543,7 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", {
</div>
<ul v-show="category.expanded" :class="{'mb-2': index != categoryCount - 1}">
<li v-for="item in category.items" :key="item.properties.title">
<button @click="zoomToCategoryItem(category, item)" class="text-left leading-tight text-xs" style="max-width: 17em;">
<button @click="zoomToFeature(item.properties.slug)" class="text-left leading-tight text-xs" style="max-width: 17em;">
<span v-if="item.properties.index" class="rounded-full inline-flex items-center justify-center bg-grey-125 font-bold text-center text-2xs w-4 h-4 mr-1">{{ item.properties.index }}</span>
<span>{{ item.properties.title }}</span>
</button>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment