/**
* @module components/SelectionTool.js
* @name SelectionTool
* @copyright 2023 3Liz
* @author BOISTEAULT Nicolas
* @license MPL-2.0
*/
import {mainLizmap, mainEventDispatcher} from '../modules/Globals.js';
import {html, render} from 'lit-html';
/**
* @class
* @name SelectionTool
* @augments HTMLElement
*/
export default class SelectionTool extends HTMLElement {
/**
* The HTML element constructor
* @class
* @private
*/
constructor() {
super();
}
/**
* Invoked when a component is added to the document's DOM.
*/
connectedCallback() {
const titleTemplate = () => html`
<h3>
<span class="title">
<button
type="button"
class="btn-selectiontool-clear btn btn-sm btn-error btn-link"
title="${lizDict['toolbar.content.stop']}"
@click=${() => mainLizmap.selectionTool.disable()}
>×</button>
<span class="icon-star icon-white"></span>
<span class="text"> ${lizDict['selectiontool.toolbar.title']} </span>
</span>
</h3>`;
const layerListSelectTemplate = () => html`
<select
class="selectiontool-layer-list"
@change=${ (event) => mainLizmap.selectionTool.allFeatureTypeSelected = event.target.value}>
<optgroup label="${lizDict['selectiontool.toolbar.layers.single']}">
${mainLizmap.selectionTool.layers.map((layer) => html`
<option value="${layer.name}">${layer.title}</option>`
)}
</optgroup>
<optgroup label="${lizDict['selectiontool.toolbar.layers.multiple']}">
<option value="selectable-visible-layers">
${lizDict['selectiontool.toolbar.layers.selectableAndVisible']}
</option>
<option value="selectable-layers">${lizDict['selectiontool.toolbar.layers.selectable']}</option>
</optgroup>
</select>`;
const geomOperatorSelectTemplate = () => html`
<select
class="selectiontool-geom-operator"
data-bs-toggle="tooltip"
data-bs-title="${lizDict['selectiontool.toolbar.geomOperator']}"
@change=${ (event) => mainLizmap.selectionTool.geomOperator = event.target.value}
>
<option value="intersects">${lizDict['selectiontool.toolbar.geomOperator.intersects']}</option>
<option value="within">${lizDict['selectiontool.toolbar.geomOperator.within']}</option>
<option value="overlaps">${lizDict['selectiontool.toolbar.geomOperator.overlaps']}</option>
<option value="contains">${lizDict['selectiontool.toolbar.geomOperator.contains']}</option>
<option value="crosses">${lizDict['selectiontool.toolbar.geomOperator.crosses']}</option>
<option value="disjoint">${lizDict['selectiontool.toolbar.geomOperator.disjoint']}</option>
<option value="touches">${lizDict['selectiontool.toolbar.geomOperator.touches']}</option>
</select>`;
const buttonsTypeTemplate = (newAddRemoveSelected) => html`
<div class="selectiontool-type-buttons btn-group">
<button
type="button"
value="refresh"
class="selectiontool-type-refresh btn btn-sm ${newAddRemoveSelected === 'new' ? 'active' : ''}"
data-bs-toggle="tooltip"
data-bs-title="${lizDict['selectiontool.toolbar.action.type.refresh']}"
@click=${() => newAddRemoveSelected = 'new'}
>
<i class="icon-refresh"></i>
</button>
<button
type="button"
value="plus"
class="selectiontool-type-plus btn btn-sm ${newAddRemoveSelected === 'add' ? 'active' : ''}"
data-bs-toggle="tooltip"
data-bs-title="${lizDict['selectiontool.toolbar.action.type.plus']}"
@click=${() => newAddRemoveSelected = 'add'}
>
<i class="icon-plus"></i>
</button>
<button
type="button"
value="minus"
class="selectiontool-type-minus btn btn-sm ${newAddRemoveSelected === 'remove' ? 'active' : ''}"
data-bs-toggle="tooltip"
data-bs-title="${lizDict['selectiontool.toolbar.action.type.minus']}"
@click=${() => newAddRemoveSelected = 'remove'}
>
<i class="icon-minus"></i>
</button>
</div>`;
const filterButtonTemplate = (isFilterDisabled, filteredFeaturesCount) => html`
<button
type="button"
class="selectiontool-filter btn btn-sm ${filteredFeaturesCount !== 0 ? 'active' : ''}"
?disabled=${isFilterDisabled}
@click=${ () => mainLizmap.selectionTool.filter()}
data-bs-toggle="tooltip"
data-bs-title="${lizDict['selectiontool.toolbar.action.filter']}">
<i class="icon-filter"></i>
</button>`;
const exportTemplate = () => this.hasAttribute('layer-export') ? html`
<div
class="btn-group dropup selectiontool-export"
role="group"
data-bs-toggle="tooltip"
data-bs-title="${mainLizmap.selectionTool.isExportable ? '' : lizDict['switcher.layer.export.warn']}"
>
<button
type="button"
class="btn btn-sm dropdown-toggle"
data-bs-toggle="dropdown"
aria-expanded="false"
?disabled=${ !mainLizmap.selectionTool.isExportable }
>
${lizDict['switcher.layer.export.title']}
<span class="caret"></span>
</button>
<ul class="selectiontool-export-formats dropdown-menu dropdown-menu-right" role="menu">
<li><a href="#" class="btn-export-selection">GeoJSON</a></li>
<li><a href="#" class="btn-export-selection">GML</a></li>
${mainLizmap.selectionTool.exportFormats.map(
(format) => html`<li><a href="#" class="btn-export-selection">${format}</a></li>`
)}
</ul>
</div>` : '';
const mainTemplate = (isFilterDisabled, results, newAddRemoveSelected, filteredFeaturesCount) => html`
<div class="selectiontool">
<h3>${titleTemplate()}</h3>
<div class="menu-content">
<div>${lizDict['selectiontool.toolbar.layer']}</div>
<div>${layerListSelectTemplate()}</div>
<lizmap-digitizing
context="selectiontool"
selected-tool="box"
available-tools="point,line,polygon,box,freehand"
import-export
></lizmap-digitizing>
<div class="selectiontool-buffer">
<label><span>${lizDict['selectiontool.toolbar.buffer']}</span>
<div class="input-append">
<input
type="number"
min="0"
class="input-mini"
.value="${mainLizmap.selectionTool.bufferValue}"
@input=${(event) => mainLizmap.selectionTool.bufferValue = parseInt(event.target.value)}
><span class="add-on">m</span>
</div>
</label>
</div>
<div>${geomOperatorSelectTemplate()}</div>
<div class="selectiontool-results" style="padding:2px">${results}</div>
<div class="selectiontool-actions">
${buttonsTypeTemplate(newAddRemoveSelected)}
<button
type="button"
class="selectiontool-unselect btn btn-sm"
?disabled=${mainLizmap.selectionTool.selectedFeaturesCount === 0}
@click=${ () => mainLizmap.selectionTool.unselect()}
data-bs-toggle="tooltip"
data-bs-title="${lizDict['selectiontool.toolbar.action.unselect']}"
>
<i class="icon-star-empty"></i>
</button>
${filterButtonTemplate(isFilterDisabled, filteredFeaturesCount)}
<lizmap-selection-invert></lizmap-selection-invert>
${exportTemplate()}
</div>
</div>
</div>`;
render(
mainTemplate(
this.isFilterDisabled,
this.results,
mainLizmap.selectionTool.newAddRemoveSelected,
mainLizmap.selectionTool.filteredFeaturesCount
),
this
);
// Add tooltip on buttons
// TODO allow tooltip on disabled buttons : https://stackoverflow.com/a/19938049/2000654
$('.menu-content button, .menu-content .selectiontool-export, .selectiontool-geom-operator', this).tooltip({
placement: 'top'
});
// Export
this.querySelectorAll('.btn-export-selection').forEach(exportbtn => {
exportbtn.addEventListener('click', evt => {
mainLizmap.selectionTool.export(evt.target.text);
});
});
mainEventDispatcher.addListener(
() => {
render(
mainTemplate(
this.isFilterDisabled,
this.results,
mainLizmap.selectionTool.newAddRemoveSelected,
mainLizmap.selectionTool.filteredFeaturesCount
),
this
);
},
[
'selectionTool.newAddRemoveSelected',
'selectionTool.allFeatureTypeSelected',
'selection.changed',
'filteredFeatures.changed',
'selection.bufferValue',
]
);
}
/**
* Invoked when a component is removed from the document's DOM.
*/
disconnectedCallback() {
}
/**
* The filter is disabled
* @type {boolean}
*/
get isFilterDisabled () {
return mainLizmap.selectionTool.selectedFeaturesCount === 0 &&
mainLizmap.selectionTool.filteredFeaturesCount === 0;
}
/**
* The results of the selection
* @type {string}
*/
get results () {
if (mainLizmap.selectionTool.selectedFeaturesCount > 1 ) {
return lizDict['selectiontool.results.more'].replace('%s', mainLizmap.selectionTool.selectedFeaturesCount);
} else if (mainLizmap.selectionTool.selectedFeaturesCount === 1) {
return lizDict['selectiontool.results.one'];
}
return lizDict['selectiontool.results.none'];
}
}