import * as MAP from "./map.js" import { PlaceDatabase } from "./places.js"; import {FeatureElement} from "./components/feature.js" import "./components/feature-short-header.js" /** La carte */ /** La base de données de lieux @type {PlaceDatabase|null} */ let places = null // CHARGEMENT await Promise.all([ // Base de données des zones PlaceDatabase.createDefault().then(db => places = db), MAP.init() ]); // Un petit point de debug window.interhackPlaces = places; await MAP.init_places(places) // GESTION de la recherche const search_form = document.getElementById("search-section") search_form.elements["query"].addEventListener("change", () => search_form.requestSubmit()) search_form.elements["query"].addEventListener("input", () => search_form.requestSubmit()) function showDefaultMapState(){ MAP.unhighlight_all() for(let feature of places.featuresShownOnEmptyMap){ MAP.show(feature) } } window.addEventListener("hashchange", () => { let place_id = decodeURIComponent(location.hash.substring(1)) if (place_id) { let feature = places.getFeatureById(place_id); if (feature) { MAP.highlight(place_id) if(document.getElementById("search-result")) { // If we have a search in progress, opening search item openSearchResultItem(feature) } else { let foundIndex = null; let panelChildren = document.getElementById("result-panel").children for(let i = 0; i 1){ for(let feature_el of document.getElementById("result-panel").children) { if(feature_el instanceof FeatureElement){ MAP.show(feature_el.feature) } } } else { for(let feature of places.featuresShownOnEmptyMap){ MAP.show(feature) } } } } else { document.getElementById("result-panel").replaceChildren(null) showDefaultMapState() } }) window.dispatchEvent(new Event("hashchange")) search_form.addEventListener("submit", e => { e.preventDefault() if(places){ let data = new FormData(search_form) if(data.get("query")){ let resultElements = [] let search_results = places.search(data.get("query")) MAP.unhighlight_all(); for(let result_item of search_results){ let el = document.createElement("li") let a = document.createElement("a") el.append(a) a.href = "#"+encodeURIComponent(result_item.ref) let header = document.createElement("camp-feature-short-header") header.feature = result_item.feature a.append(header) resultElements.push(el) MAP.show(result_item.feature) } if(!document.getElementById("search-result")){ let el = document.createElement("ol") el.id = "search-result" document.getElementById("result-panel").replaceChildren(el) } if(resultElements.length > 0){ document.getElementById("search-result").replaceChildren(...resultElements) } else { document.getElementById("search-result").replaceChildren(document.createTextNode("Pas de resultat")) } } else { document.getElementById("search-result")?.remove() showDefaultMapState() } } }) function openSearchResultItem(feature){ let searchResultContainer = document.getElementById("search-result") if(searchResultContainer){ let featureIndex = -1 let featureFound = false let newChildren = [] for(let el of searchResultContainer.children){ let featureHeader = el.querySelector("camp-feature-short-header") if(!featureHeader) continue let root = document.createElement("camp-feature") root.feature = featureHeader.feature newChildren.push(root) if(!featureFound){ featureIndex += 1 if(feature == root.feature){ featureFound = true } } } let panel = document.getElementById("result-panel") panel.replaceChildren(...newChildren) requestAnimationFrame(() => { if(featureFound){ panel.setActiveChildrenIndex(featureIndex, {behavior: "instant"}) } else { panel.activeChildrenIndex = 0 } }) updateActiveFeature(feature) } } function openFeature(feature){ let panel = document.getElementById("result-panel") let root = document.createElement("camp-feature") root.feature = feature panel.replaceChildren(root) requestAnimationFrame(() => { panel.setActiveChildrenIndex(0, {behavior: "instant"}) }) updateActiveFeature(feature) } function updateActiveFeature(feature_or_featureid){ let newUrl = new URL(window.location) if(feature_or_featureid){ newUrl.hash = encodeURIComponent(feature_or_featureid.id || feature_or_featureid) } else { newUrl.hash = ""; } if(newUrl.toString() != location.toString()){ window.history.replaceState(null, "", newUrl.toString()) window.dispatchEvent(new Event("hashchange")) } } document.getElementById("result-panel").addEventListener("activePanelChange", e => { console.log("Panel changed", e.activePanelIndex) if(e.activePanelIndex || e.activePanelIndex === 0){ let activeElement = e.target.children[e.activePanelIndex] if(activeElement instanceof FeatureElement){ let feature = activeElement.feature updateActiveFeature(feature) } else { updateActiveFeature(null) } } }) { const RESULT_PANEL = document.getElementById("result-panel") /** @type {HTMLDialogElement} */ const RESULT_DIALOG = document.getElementById("result-panel-dialog") function udpateDialogState(){ if(RESULT_PANEL.children.length > 0) { // BUG d'accessibilité: Il ne faut pas modifier le focus lors de l'ouverture d'une modale // Il est preferable de ne pas ouvrir la modale avant d'être sur que l'utilisateur·ice veux vraiment y aller let active_element = document.activeElement; RESULT_DIALOG.show() if(active_element){ active_element.focus() } } else { RESULT_DIALOG.close() } } // Oberve changes in modal DOM new MutationObserver(udpateDialogState).observe(RESULT_PANEL, { childList: true }) // Empty result panel on close document.getElementById("close-result-panel-btn").addEventListener("click", e => { updateActiveFeature(null) document.getElementById("result-panel").replaceChildren() }) //Init udpateDialogState() }