import { queryItems, queryItem } from '../modules/api.js'
import svgSprites from '@dataforsyningen/designsystem/assets/icons.svg'
import { state, autorun } from '../state/index.js'
/**
* Web component that fetches a list of items covering a specific collection, coordinate, and orientation.
* Enables user to select an item for view by its date.
* @prop {string} dataset.itemkey - `data-itemkey` attribute used to look up state by the viewport's image item key.
*/
export class SkraaFotoDateSelector extends HTMLElement {
#selectElement
#buttonDown
#buttonUp
#styles = `
skraafoto-date-selector {
z-index: 1;
position: absolute;
bottom: 1rem;
pointer-events: none;
height: 5rem;
width: 100%;
display: flex;
justify-content: space-around;
}
.ds-button-group button, .ds-button-group {
padding: 0;
pointer-events: all;
align-items: center;
}
skraafoto-date-selector .ds-button-group >.quiet+hr {
height: var(--button-base-height);
background-color: var(--card-border-color);
}
`
constructor() {
super()
}
#renderTemplate() {
return `
<style>
${ this.#styles }
</style>
<nav class="ds-nav-tools">
<div class="ds-button-group" data-theme="light">
<button class="button-down quiet" title="Skift billede">
<svg><use href="${ svgSprites }#arrow-single-down"/></svg>
</button>
<hr>
<select class="sf-date-selector" id="date" style="border: none; width: auto;"></select>
<hr>
<button class="button-up quiet" title="Skift billede">
<svg><use href="${ svgSprites }#arrow-single-up"/></svg>
</button>
</div>
</nav>
`
}
#fetchIds(item, marker) {
if (!item || !marker) {
return
}
queryItems(marker.position, item.properties.direction, item.collection, 50).then((response) => {
this.#selectElement.innerHTML = this.#renderOptions(response.features)
this.#selectElement.value = state.items[this.dataset.itemkey].id
})
}
#renderOptions(features) {
let templateString = ''
features.map((i, idx, arr) => {
const datetime = new Date(i.properties.datetime)
const seriesDate = `${datetime.toLocaleDateString()} ${idx + 1}/${arr.length}`
templateString += `
<option value="${i.id}">
${seriesDate}
</option>
`
})
return templateString
}
shiftItemHandler(event) {
if (event.detail === -1) {
this.#buttonDown.click()
} else if (event.detail === 1) {
this.#buttonUp.click()
}
}
connectedCallback() {
this.innerHTML = this.#renderTemplate()
this.#selectElement = this.querySelector('select')
this.#buttonDown = this.querySelector('.button-down')
this.#buttonUp = this.querySelector('.button-up')
let isOptionClicked = false
// Add event listener to the button-down
this.#buttonDown.addEventListener('click', () => {
const selectedIndex = this.#selectElement.selectedIndex
const lastIndex = this.#selectElement.options.length - 1
const nextIndex = selectedIndex === lastIndex ? 0 : selectedIndex + 1
this.#selectElement.selectedIndex = nextIndex
this.#selectElement.dispatchEvent(new Event('change')) // Trigger change event manually
})
// Add event listener to the button-up
this.#buttonUp.addEventListener('click', () => {
const selectedIndex = this.#selectElement.selectedIndex
const lastIndex = this.#selectElement.options.length - 1
const prevIndex = selectedIndex === 0 ? lastIndex : selectedIndex - 1
this.#selectElement.selectedIndex = prevIndex
this.#selectElement.dispatchEvent(new Event('change')) // Trigger change event manually
})
// When an option is clicked, set the flag to prevent focus removal
this.#selectElement.addEventListener('mousedown', () => {
isOptionClicked = true
})
// When the select element loses focus, remove focus if no option is selected
this.#selectElement.addEventListener('blur', () => {
if (!isOptionClicked) {
this.#selectElement.selectedIndex = -1 // Deselect any selected option
}
isOptionClicked = false // Reset the flag
})
// Add global listener for state changes
this.autorunDisposer = autorun(() => {
this.#fetchIds(state.items[this.dataset.itemkey], state.marker)
})
// Add event listener to the document for arrow key navigation
window.addEventListener('imageshift', this.shiftItemHandler.bind(this))
// When an option is selected, update the state with the new item
this.#selectElement.addEventListener('change', (event) => {
queryItem(event.target.value).then((data) => {
state.setItem(data, this.dataset.itemkey)
})
this.#selectElement.blur() // Remove focus from the select element
})
}
disconnectedCallback() {
this.autorunDisposer()
window.removeEventListener('imageshift', this.shiftItemHandler)
}
}