Ajout d'un panneau vertical pour le resultat de la recerche
This commit is contained in:
parent
f7e5bb37bf
commit
7d45e2f717
8 changed files with 549 additions and 18 deletions
104
css/style.css
104
css/style.css
|
|
@ -5,12 +5,29 @@ body, html {
|
||||||
|
|
||||||
body {
|
body {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
|
||||||
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
body > * {
|
body > * {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body > hr {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 50vh;
|
||||||
|
flex-shrink: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* HEADER and NAV */
|
/* HEADER and NAV */
|
||||||
|
|
||||||
#main-header {
|
#main-header {
|
||||||
|
|
@ -112,4 +129,89 @@ body > * {
|
||||||
filter: drop-shadow(0 0 10px black);
|
filter: drop-shadow(0 0 10px black);
|
||||||
opacity: clamp(0, calc( 1 - ( var(--zoom-level) - 18 ) ), 1) ;
|
opacity: clamp(0, calc( 1 - ( var(--zoom-level) - 18 ) ), 1) ;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SAERCH FORM */
|
||||||
|
|
||||||
|
#search-section {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 100i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PANEL */
|
||||||
|
|
||||||
|
#result-panel {
|
||||||
|
background: black;
|
||||||
|
border-top: 3px white solid;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result-panel.empty,
|
||||||
|
#result-panel:empty{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result-panel > * {
|
||||||
|
padding: 1em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result-panel::part(navigation-panel) {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 0 10px black;
|
||||||
|
border-top: solid 1px rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#result-panel::part(dot),
|
||||||
|
#result-panel::part(dot-active) {
|
||||||
|
border-radius: 0;
|
||||||
|
width: 1ex;
|
||||||
|
height: 1ex;
|
||||||
|
margin-top: 0.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result-panel::part(dot-active) {
|
||||||
|
transform-origin: 0% 100%;
|
||||||
|
transform: scaleX(1) scaleY(1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
camp-feature-short-header {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr min-content;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
camp-feature-short-header h2 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
camp-feature-short-header .feature-location {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.6em;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-result {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-result > li:not(:first-child) {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-result > li:not(:last-child) {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-result > li > a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
|
||||||
19
icons/arrow-left.svg
Normal file
19
icons/arrow-left.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="20.302734"
|
||||||
|
height="21.37561"
|
||||||
|
viewBox="0 0 20.302734 21.37561"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xml:space="preserve"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs1" /><g
|
||||||
|
id="layer2"
|
||||||
|
transform="translate(-1524.3279,-1694.6793)"><path
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.84565;stroke-linecap:butt;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 356.12486,1705.4702 h -19.62275 l 9.32634,-10.1671 -9.32634,10.1671 9.32634,9.9538"
|
||||||
|
id="path23-6-2"
|
||||||
|
transform="translate(1188.5058)" /></g></svg>
|
||||||
|
After Width: | Height: | Size: 792 B |
19
icons/arrow-right.svg
Normal file
19
icons/arrow-right.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="20.302734"
|
||||||
|
height="21.37561"
|
||||||
|
viewBox="0 0 20.302734 21.37561"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xml:space="preserve"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs1" /><g
|
||||||
|
id="layer2"
|
||||||
|
transform="translate(-1562.407,-1694.6793)"><path
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.84565;stroke-linecap:butt;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 373.90116,1705.4702 h 19.62274 l -9.32633,-10.1671 9.32633,10.1671 -9.32633,9.9538"
|
||||||
|
id="path23-8-8"
|
||||||
|
transform="translate(1188.5058)" /></g></svg>
|
||||||
|
After Width: | Height: | Size: 791 B |
20
index.html
20
index.html
|
|
@ -7,6 +7,7 @@
|
||||||
<link rel="stylesheet" href="./js/lib/leaflet/leaflet.css">
|
<link rel="stylesheet" href="./js/lib/leaflet/leaflet.css">
|
||||||
<link rel="stylesheet" href="./css/style.css">
|
<link rel="stylesheet" href="./css/style.css">
|
||||||
<script type="module" src="./js/index.js"></script>
|
<script type="module" src="./js/index.js"></script>
|
||||||
|
<script type="module" src="./js/components/bidi-panel.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header id="main-header">
|
<header id="main-header">
|
||||||
|
|
@ -14,26 +15,17 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section id="map"></section>
|
<section id="map"></section>
|
||||||
<style>
|
|
||||||
#search-section {
|
<hr>
|
||||||
background: white;
|
|
||||||
padding: 15px;
|
|
||||||
max-width: 300px;
|
|
||||||
margin-left: 15px;
|
|
||||||
margin-top: 15px;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<section id="search-section">
|
<section id="search-section">
|
||||||
<form id="search-area">
|
<form id="search-area">
|
||||||
<label for="search-area-query">Rechercher une zone</label><br/>
|
<label for="search-area-query">Rechercher une zone</label><br/>
|
||||||
<input type="search" name="query" id="search-area-query" />
|
<input type="search" name="query" id="search-area-query" />
|
||||||
<button>Rechercher</button>
|
<button>Rechercher</button>
|
||||||
</form>
|
</form>
|
||||||
<ul id="search-result"></ul>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<camp-bidi-panel id="result-panel" ></camp-bidi-panel>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
264
js/components/bidi-panel.js
Normal file
264
js/components/bidi-panel.js
Normal file
|
|
@ -0,0 +1,264 @@
|
||||||
|
const TEMPLATE = document.createElement("template");
|
||||||
|
TEMPLATE.innerHTML = `
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
background: inherit;
|
||||||
|
color: inherit;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: stretch;
|
||||||
|
|
||||||
|
padding: 0.5ex;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.single-panel) #navigation {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation .progress-container {
|
||||||
|
flex: 1;
|
||||||
|
flex-shrink: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation button {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 3em;
|
||||||
|
height: 3em;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation button img {
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-container progress {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress-dots {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
overflow-x: auto;
|
||||||
|
gap: 0.5ex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress-dots .dot {
|
||||||
|
width: 0.75ex;
|
||||||
|
height: 0.75ex;
|
||||||
|
border-radius: 100%;
|
||||||
|
background: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress-dots .dot.active {
|
||||||
|
transform: scale(1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
overflow-x: auto;
|
||||||
|
scroll-snap-type: x mandatory;
|
||||||
|
scroll-behavior: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content ::slotted(*) {
|
||||||
|
width: 100%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
scroll-snap-align: start;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<section id="content"><slot></slot></section>
|
||||||
|
|
||||||
|
<nav id="navigation" part="navigation-panel">
|
||||||
|
<button id="nav-left-panel" title="Aller au panneau de gauche" part="nav-button-left">
|
||||||
|
<img alt="Fleche vers la gauche" src="${new URL("../../icons/arrow-left.svg", import.meta.url)}"/>
|
||||||
|
</button>
|
||||||
|
<div class="progress-container">
|
||||||
|
<progress id="panel-progress-bar" value="0"></progress>
|
||||||
|
<div id="progress-dots" aria-hidden="true"></div>
|
||||||
|
</div>
|
||||||
|
<button id="nav-right-panel" title="Aller au panneau de droite" part="nav-button-right" >
|
||||||
|
<img alt="Fleche vers la droite" src="${new URL("../../icons/arrow-right.svg", import.meta.url)}"/>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
`
|
||||||
|
|
||||||
|
export class BidiPanelElement extends HTMLElement {
|
||||||
|
|
||||||
|
shadow
|
||||||
|
|
||||||
|
mutationObserver
|
||||||
|
|
||||||
|
#lastActive
|
||||||
|
#currentIndex
|
||||||
|
|
||||||
|
get contentContainer(){
|
||||||
|
return this.shadow.getElementById("content")
|
||||||
|
}
|
||||||
|
|
||||||
|
get progressBar(){
|
||||||
|
return this.shadow.getElementById("panel-progress-bar")
|
||||||
|
}
|
||||||
|
|
||||||
|
get progressDotsContainer(){
|
||||||
|
return this.shadow.getElementById("progress-dots")
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeChildrenIndex(){
|
||||||
|
let thisGeometry = this.getBoundingClientRect()
|
||||||
|
let progress = this.contentContainer.scrollLeft / (this.contentContainer.scrollWidth - thisGeometry.width)
|
||||||
|
let focusedElementIndex = Math.floor(progress * this.children.length)
|
||||||
|
if(Number.isFinite(focusedElementIndex)){
|
||||||
|
return focusedElementIndex
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set activeChildrenIndex(newIndex){
|
||||||
|
this.setActiveChildrenIndex(newIndex, {behavior: "auto"})
|
||||||
|
}
|
||||||
|
|
||||||
|
setActiveChildrenIndex(newIndex, options){
|
||||||
|
let newPanel = this.children[newIndex]
|
||||||
|
let newPanelRect = newPanel.getBoundingClientRect()
|
||||||
|
let selfRect = this.getBoundingClientRect()
|
||||||
|
this.contentContainer.scrollTo({
|
||||||
|
left: this.contentContainer.scrollLeft + ( newPanelRect.left - selfRect.left ),
|
||||||
|
behavior: options?.behavior || "auto"
|
||||||
|
})
|
||||||
|
this.#currentIndex = newIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeChildren(){
|
||||||
|
return this.children[this.activeChildrenIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback(){
|
||||||
|
if(!this.shadow){
|
||||||
|
this.shadow = this.attachShadow({ mode: "open" })
|
||||||
|
this.shadow.append(TEMPLATE.content.cloneNode(true))
|
||||||
|
}
|
||||||
|
this.contentContainer.addEventListener("scroll", this.handleContentScroll.bind(this))
|
||||||
|
this.shadow.getElementById("nav-left-panel").addEventListener("click", () => this.previous());
|
||||||
|
this.shadow.getElementById("nav-right-panel").addEventListener("click", () => this.next());
|
||||||
|
|
||||||
|
this.mutationObserver = (new MutationObserver(this.handleMutations.bind(this)))
|
||||||
|
this.mutationObserver.observe(this, {childList:true})
|
||||||
|
|
||||||
|
this.updateProgress()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMutations(mutation){
|
||||||
|
let newIndex = this.#currentIndex
|
||||||
|
this.updateProgress()
|
||||||
|
if(Number.isFinite(newIndex)){
|
||||||
|
this.setActiveChildrenIndex(newIndex, {behavior: "instant"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleContentScroll(e){
|
||||||
|
this.updateProgress()
|
||||||
|
this.#currentIndex = this.activeChildrenIndex
|
||||||
|
if(this.#currentIndex != this.#lastActive){
|
||||||
|
this.dispatchEvent(new ActivePanelChangeEvent("activePanelChange", this.#currentIndex))
|
||||||
|
this.#lastActive = this.#currentIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProgress(){
|
||||||
|
let focusedElementIndex = this.activeChildrenIndex;
|
||||||
|
|
||||||
|
let progressBar = this.progressBar;
|
||||||
|
progressBar.value = focusedElementIndex;
|
||||||
|
progressBar.min = 0;
|
||||||
|
progressBar.max = this.children.length-1;
|
||||||
|
|
||||||
|
this.classList.toggle("single-panel", this.children.length == 1)
|
||||||
|
this.classList.toggle("empty", this.children.length == 0)
|
||||||
|
|
||||||
|
let dotsContainer = this.progressDotsContainer;
|
||||||
|
if(dotsContainer.children.length != parseInt(progressBar.max)+1){
|
||||||
|
let dots = (new Array(this.children.length))
|
||||||
|
.fill(0)
|
||||||
|
.map(() => {
|
||||||
|
let el = document.createElement("div")
|
||||||
|
el.classList.add("dot")
|
||||||
|
el.part = "dot"
|
||||||
|
return el
|
||||||
|
});
|
||||||
|
dotsContainer.replaceChildren(...dots)
|
||||||
|
}
|
||||||
|
for(let inactiveDot of dotsContainer.querySelectorAll(".active")){
|
||||||
|
inactiveDot.part = "dot"
|
||||||
|
inactiveDot.classList.remove("active")
|
||||||
|
}
|
||||||
|
|
||||||
|
let activeDot = dotsContainer.children[parseInt(progressBar.value)]
|
||||||
|
if(activeDot){
|
||||||
|
activeDot.part = "dot-active"
|
||||||
|
activeDot.classList.add("active")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next(){
|
||||||
|
let nextItem = this.activeChildrenIndex + 1;
|
||||||
|
if(nextItem < this.children.length){
|
||||||
|
this.activeChildrenIndex = nextItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previous(){
|
||||||
|
let nextItem = this.activeChildrenIndex - 1;
|
||||||
|
if(nextItem >= 0){
|
||||||
|
this.activeChildrenIndex = nextItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ActivePanelChangeEvent extends Event {
|
||||||
|
constructor(name, activePanelIndex){
|
||||||
|
super(name)
|
||||||
|
this.activePanelIndex = activePanelIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("camp-bidi-panel", BidiPanelElement);
|
||||||
43
js/components/feature-short-header.js
Normal file
43
js/components/feature-short-header.js
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
const TEMPLATE = document.createElement("template")
|
||||||
|
TEMPLATE.innerHTML = `
|
||||||
|
<h2 class="feature-name"></h2>
|
||||||
|
<small class="feature-location"></small>
|
||||||
|
`
|
||||||
|
|
||||||
|
export class FeatureShortHeaderElement extends HTMLElement {
|
||||||
|
|
||||||
|
#feature
|
||||||
|
|
||||||
|
get feature(){
|
||||||
|
return this.#feature
|
||||||
|
}
|
||||||
|
|
||||||
|
set feature(value){
|
||||||
|
this.#feature = value
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback(){
|
||||||
|
this.updateContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateContent(){
|
||||||
|
if(!this.feature){
|
||||||
|
this.replaceChildren()
|
||||||
|
} else {
|
||||||
|
this.replaceChildren(TEMPLATE.content.cloneNode(true))
|
||||||
|
this.querySelector(".feature-name").textContent =
|
||||||
|
this.feature?.properties?.name ||
|
||||||
|
this.feature.mapSymbol.genericName ||
|
||||||
|
this.feature.id
|
||||||
|
|
||||||
|
let featurePoint = this.feature.asPoint()
|
||||||
|
|
||||||
|
this.querySelector(".feature-location").textContent =
|
||||||
|
this.feature?.properties?.["location-description"] ||
|
||||||
|
`${featurePoint.geometry.coordinates[1]}, ${featurePoint.geometry.coordinates[0]}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("camp-feature-short-header", FeatureShortHeaderElement)
|
||||||
26
js/components/feature.js
Normal file
26
js/components/feature.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import "./feature-short-header.js"
|
||||||
|
|
||||||
|
const TEMPLATE = document.createElement("template")
|
||||||
|
TEMPLATE.innerHTML = `
|
||||||
|
<camp-feature-short-header class="feature-header" ></camp-feature-short-header>
|
||||||
|
`
|
||||||
|
|
||||||
|
export class FeatureElement extends HTMLElement {
|
||||||
|
|
||||||
|
feature
|
||||||
|
|
||||||
|
connectedCallback(){
|
||||||
|
this.updateContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateContent(){
|
||||||
|
this.replaceChildren(TEMPLATE.content.cloneNode(true))
|
||||||
|
|
||||||
|
let header = this.querySelector("camp-feature-short-header")
|
||||||
|
header.feature = this.feature
|
||||||
|
header.updateContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("camp-feature", FeatureElement)
|
||||||
72
js/index.js
72
js/index.js
|
|
@ -1,5 +1,7 @@
|
||||||
import * as MAP from "./map.js"
|
import * as MAP from "./map.js"
|
||||||
import { PlaceDatabase } from "./places.js";
|
import { PlaceDatabase } from "./places.js";
|
||||||
|
import {FeatureElement} from "./components/feature.js"
|
||||||
|
import "./components/feature-short-header.js"
|
||||||
|
|
||||||
/** La carte */
|
/** La carte */
|
||||||
|
|
||||||
|
|
@ -47,18 +49,82 @@ search_form.addEventListener("submit", e => {
|
||||||
let a = document.createElement("a")
|
let a = document.createElement("a")
|
||||||
el.append(a)
|
el.append(a)
|
||||||
a.href = "#"+encodeURIComponent(result_item.ref)
|
a.href = "#"+encodeURIComponent(result_item.ref)
|
||||||
a.textContent = result_item.feature.properties.name+" ("+result_item.ref+")"
|
a.addEventListener("click", e => {
|
||||||
|
e.preventDefault()
|
||||||
|
openSearchResultItem(result_item.feature)
|
||||||
|
})
|
||||||
|
let header = document.createElement("camp-feature-short-header")
|
||||||
|
header.feature = result_item.feature
|
||||||
|
a.append(header)
|
||||||
resultElements.push(el)
|
resultElements.push(el)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!document.getElementById("search-result")){
|
||||||
|
let el = document.createElement("ol")
|
||||||
|
el.id = "search-result"
|
||||||
|
document.getElementById("result-panel").replaceChildren(el)
|
||||||
|
}
|
||||||
|
|
||||||
if(resultElements.length > 0){
|
if(resultElements.length > 0){
|
||||||
document.getElementById("search-result").replaceChildren(...resultElements)
|
document.getElementById("search-result").replaceChildren(...resultElements)
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("search-result").replaceChildren(document.createTextNode("Pas de resultat"))
|
document.getElementById("search-result").replaceChildren(document.createTextNode("Pas de resultat"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.getElementById("search-result").children[0]?.scrollIntoView()
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("search-result").replaceChildren([])
|
document.getElementById("search-result")?.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let newUrl = new URL(window.location)
|
||||||
|
newUrl.hash = feature.id
|
||||||
|
window.history.replaceState(newUrl.toString(), "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("result-panel").addEventListener("activePanelChange", e => {
|
||||||
|
let activeElement = e.target.children[e.activePanelIndex]
|
||||||
|
if(activeElement instanceof FeatureElement){
|
||||||
|
let feature = activeElement.feature
|
||||||
|
if(feature){
|
||||||
|
MAP.highlight(feature.id)
|
||||||
|
} else {
|
||||||
|
MAP.unhighlight_all()
|
||||||
|
}
|
||||||
|
console.log("active panel changed: "+e.activePanelIndex, feature)
|
||||||
|
} else {
|
||||||
|
MAP.unhighlight_all()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue