mirror of
https://github.com/umap-project/umap.git
synced 2025-05-04 21:51:50 +02:00
wip: dynamic autocomplete for prompt condition
This commit is contained in:
parent
628e74ecb3
commit
4552dc0341
5 changed files with 52 additions and 12 deletions
|
@ -6,6 +6,7 @@ import {
|
|||
} from '../../vendors/leaflet/leaflet-src.esm.js'
|
||||
import { translate } from './i18n.js'
|
||||
import { Request, ServerRequest } from './request.js'
|
||||
import { escapeHTML, generateId } from './utils.js'
|
||||
|
||||
export class BaseAutocomplete {
|
||||
constructor(el, options) {
|
||||
|
@ -46,7 +47,7 @@ export class BaseAutocomplete {
|
|||
placeholder: this.options.placeholder,
|
||||
autocomplete: 'off',
|
||||
className: this.options.className,
|
||||
name: this.options.name || 'autocomplete'
|
||||
name: this.options.name || 'autocomplete',
|
||||
})
|
||||
DomEvent.on(this.input, 'keydown', this.onKeyDown, this)
|
||||
DomEvent.on(this.input, 'keyup', this.onKeyUp, this)
|
||||
|
@ -350,3 +351,19 @@ export const MultipleMixin = (Base) =>
|
|||
export class AjaxAutocompleteMultiple extends MultipleMixin(BaseServerAjax) {}
|
||||
|
||||
export class AjaxAutocomplete extends SingleMixin(BaseServerAjax) {}
|
||||
|
||||
export class AutocompleteDatalist {
|
||||
constructor(input) {
|
||||
this.input = input
|
||||
this.datalist = document.createElement('datalist')
|
||||
this.datalist.id = generateId()
|
||||
this.input.setAttribute('list', this.datalist.id)
|
||||
this.input.parentElement.appendChild(this.datalist)
|
||||
}
|
||||
|
||||
set suggestions(values) {
|
||||
this.datalist.innerHTML = values
|
||||
.map((value) => `<option>${escapeHTML(value)}</option>`)
|
||||
.join('')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
uMapAlertConflict as AlertConflict,
|
||||
uMapAlertCreation as AlertCreation,
|
||||
} from '../components/alerts/alert.js'
|
||||
import { AjaxAutocomplete, AjaxAutocompleteMultiple } from './autocomplete.js'
|
||||
import { AjaxAutocomplete, AjaxAutocompleteMultiple, AutocompleteDatalist } from './autocomplete.js'
|
||||
import Browser from './browser.js'
|
||||
import Caption from './caption.js'
|
||||
import Facets from './facets.js'
|
||||
|
@ -30,6 +30,7 @@ window.U = {
|
|||
AlertConflict,
|
||||
AjaxAutocomplete,
|
||||
AjaxAutocompleteMultiple,
|
||||
AutocompleteDatalist,
|
||||
Browser,
|
||||
Caption,
|
||||
Dialog,
|
||||
|
|
|
@ -181,8 +181,8 @@ export default class Dialog {
|
|||
return this.open(Object.assign({}, config, { message, template: false }))
|
||||
}
|
||||
|
||||
prompt(message, fallback = '', config = {}) {
|
||||
const template = `<input type="text" name="prompt" value="${fallback}">`
|
||||
prompt(message, config = {}) {
|
||||
const template = `<input type="text" name="prompt">`
|
||||
return this.open(Object.assign({}, config, { message, template }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -919,6 +919,13 @@ U.DataLayer = L.Evented.extend({
|
|||
if (idx !== -1) this._propertiesIndex.splice(idx, 1)
|
||||
},
|
||||
|
||||
sortedValues: function (property) {
|
||||
return Object.values(this._layers)
|
||||
.map((feature) => feature.properties[property])
|
||||
.filter((val, idx, arr) => arr.indexOf(val) === idx)
|
||||
.sort(U.Utils.naturalSort)
|
||||
},
|
||||
|
||||
addData: function (geojson, sync) {
|
||||
try {
|
||||
// Do not fail if remote data is somehow invalid,
|
||||
|
|
|
@ -101,14 +101,29 @@ U.TableEditor = L.Class.extend({
|
|||
})
|
||||
},
|
||||
|
||||
refine: function () {
|
||||
const promise = new U.Prompt().open({
|
||||
className: 'dark',
|
||||
title: L._('Deleting rows matching condition'),
|
||||
deleteRows: function () {
|
||||
const dialog = this.datalayer.map.dialog
|
||||
const promise = dialog.prompt(L._('Deleting rows matching condition'))
|
||||
|
||||
const autocomplete = new U.AutocompleteDatalist(
|
||||
dialog.dialog.querySelector('[name=prompt]')
|
||||
)
|
||||
autocomplete.suggestions = this.datalayer._propertiesIndex
|
||||
autocomplete.input.addEventListener('input', (event) => {
|
||||
const value = event.target.value
|
||||
if (this.datalayer._propertiesIndex.includes(value)) {
|
||||
autocomplete.suggestions = [`${value}=`, `${value}!=`, `${value}>`, `${value}<`]
|
||||
} else if (value.endsWith('=')) {
|
||||
const key = value.split('!')[0].split('=')[0]
|
||||
autocomplete.suggestions = this.datalayer
|
||||
.sortedValues(key)
|
||||
.map((str) => `${value}${str || ''}`)
|
||||
}
|
||||
})
|
||||
promise.then((raw) => {
|
||||
if (!raw) return
|
||||
const rule = new U.Rule(raw)
|
||||
|
||||
promise.then(({ prompt }) => {
|
||||
if (!prompt) return
|
||||
const rule = new U.Rule(prompt)
|
||||
const matched = []
|
||||
this.datalayer.eachLayer((feature) => {
|
||||
if (rule.match(feature.properties)) {
|
||||
|
@ -148,7 +163,7 @@ U.TableEditor = L.Class.extend({
|
|||
L.DomUtil.createIcon(refineButton, 'icon-add'),
|
||||
refineButton.firstChild
|
||||
)
|
||||
L.DomEvent.on(refineButton, 'click', this.refine, this)
|
||||
L.DomEvent.on(refineButton, 'click', this.deleteRows, this)
|
||||
this.datalayer.map.fullPanel.open({
|
||||
content: this.table,
|
||||
className: 'umap-table-editor',
|
||||
|
|
Loading…
Reference in a new issue