diff --git a/umap/static/umap/js/modules/autocomplete.js b/umap/static/umap/js/modules/autocomplete.js index 4fde8b84..da02c390 100644 --- a/umap/static/umap/js/modules/autocomplete.js +++ b/umap/static/umap/js/modules/autocomplete.js @@ -1,6 +1,11 @@ -import { DomUtil, DomEvent, setOptions } from '../../vendors/leaflet/leaflet-src.esm.js' +import { + DomUtil, + DomEvent, + setOptions, + Util, +} from '../../vendors/leaflet/leaflet-src.esm.js' import { translate } from './i18n.js' -import { ServerRequest } from './request.js' +import { Request, ServerRequest } from './request.js' export class BaseAutocomplete { constructor(el, options) { @@ -216,11 +221,17 @@ export class BaseAutocomplete { } } -class BaseAjax extends BaseAutocomplete { +export class BaseAjax extends BaseAutocomplete { + URL = '/foobar/?q={q}' constructor(el, options) { super(el, options) - this.server = new ServerRequest() + this.initRequest() } + + initRequest() { + this.request = new Request() + } + optionToResult(option) { return { value: option.value, @@ -237,71 +248,94 @@ class BaseAjax extends BaseAutocomplete { if (val === this.cache) return else this.cache = val val = val.toLowerCase() - const [{ data }, response] = await this.server.get( - `/agnocomplete/AutocompleteUser/?q=${encodeURIComponent(val)}` - ) - this.handleResults(data) + const url = Util.template(this.URL, {q: encodeURIComponent(val)}) + this.handleResults(await this._search(url)) + } + + async _search(url) { + const response = await this.request.get(url) + if (response && response.ok) { + return await response.json() + } + } } -export class AjaxAutocompleteMultiple extends BaseAjax { - initSelectedContainer() { - return DomUtil.after( - this.input, - DomUtil.element({ tagName: 'ul', className: 'umap-multiresult' }) - ) +class BaseServerAjax extends BaseAjax { + URL = '/agnocomplete/AutocompleteUser/?q={q}' + initRequest() { + this.server = new ServerRequest() } - - displaySelected(result) { - const result_el = DomUtil.element({ - tagName: 'li', - parent: this.selectedContainer, - }) - result_el.textContent = result.item.label - const close = DomUtil.element({ - tagName: 'span', - parent: result_el, - className: 'close', - textContent: '×', - }) - DomEvent.on(close, 'click', () => { - this.selectedContainer.removeChild(result_el) - this.options.on_unselect(result) - }) - this.hide() + async _search(url) { + const [{ data }, response] = await this.server.get(url) + return data } } -export class AjaxAutocomplete extends BaseAjax { - initSelectedContainer() { - return DomUtil.after( - this.input, - DomUtil.element({ tagName: 'div', className: 'umap-singleresult' }) - ) +export const SingleMixin = (Base) => + class extends Base { + initSelectedContainer() { + return DomUtil.after( + this.input, + DomUtil.element({ tagName: 'div', className: 'umap-singleresult' }) + ) + } + + displaySelected(result) { + const result_el = DomUtil.element({ + tagName: 'div', + parent: this.selectedContainer, + }) + result_el.textContent = result.item.label + const close = DomUtil.element({ + tagName: 'span', + parent: result_el, + className: 'close', + textContent: '×', + }) + this.input.style.display = 'none' + DomEvent.on( + close, + 'click', + function () { + this.selectedContainer.innerHTML = '' + this.input.style.display = 'block' + }, + this + ) + this.hide() + } } - displaySelected(result) { - const result_el = DomUtil.element({ - tagName: 'div', - parent: this.selectedContainer, - }) - result_el.textContent = result.item.label - const close = DomUtil.element({ - tagName: 'span', - parent: result_el, - className: 'close', - textContent: '×', - }) - this.input.style.display = 'none' - DomEvent.on( - close, - 'click', - function () { - this.selectedContainer.innerHTML = '' - this.input.style.display = 'block' - }, - this - ) - this.hide() +export const MultipleMixin = (Base) => + class extends Base { + initSelectedContainer() { + return DomUtil.after( + this.input, + DomUtil.element({ tagName: 'ul', className: 'umap-multiresult' }) + ) + } + + displaySelected(result) { + const result_el = DomUtil.element({ + tagName: 'li', + parent: this.selectedContainer, + }) + result_el.textContent = result.item.label + const close = DomUtil.element({ + tagName: 'span', + parent: result_el, + className: 'close', + textContent: '×', + }) + DomEvent.on(close, 'click', () => { + this.selectedContainer.removeChild(result_el) + this.options.on_unselect(result) + }) + this.hide() + } } -} + +export class AjaxAutocompleteMultiple extends MultipleMixin(BaseServerAjax) {} + +export class AjaxAutocomplete extends SingleMixin(BaseServerAjax) {} diff --git a/umap/static/umap/js/modules/importer.js b/umap/static/umap/js/modules/importer.js index 95ce108a..35233048 100644 --- a/umap/static/umap/js/modules/importer.js +++ b/umap/static/umap/js/modules/importer.js @@ -42,9 +42,13 @@ export default class Importer { parent: this.container, textContent: translate('Import from:'), }) - const plugins = L.DomUtil.element({tagName: 'div', className: 'umap-multiplechoice by2', parent: this.container}) + const plugins = L.DomUtil.element({ + tagName: 'div', + className: 'umap-multiplechoice by2', + parent: this.container, + }) for (const plugin of this.map.plugins) { - const {name, callback} = plugin.addImporter() + const { name, callback } = plugin.addImporter() L.DomUtil.createButton('flat', plugins, name, () => callback.bind(plugin)(this)) } this.typeLabel = L.DomUtil.add( diff --git a/umap/static/umap/js/modules/plugins/geodatamine.js b/umap/static/umap/js/modules/plugins/geodatamine.js index a882dffe..8952e194 100644 --- a/umap/static/umap/js/modules/plugins/geodatamine.js +++ b/umap/static/umap/js/modules/plugins/geodatamine.js @@ -1,15 +1,12 @@ import { DomUtil, DomEvent, stamp } from '../../../vendors/leaflet/leaflet-src.esm.js' import { translate } from '../i18n.js' -import { AjaxAutocomplete } from '../autocomplete.js' +import { BaseAjax, SingleMixin } from '../autocomplete.js' import { Request } from '../request.js' import Alert from '../ui/alert.js' import Dialog from '../ui/dialog.js' -class Autocomplete extends AjaxAutocomplete { - constructor(request, el, options) { - super(el, options) - this.request = request - } +class Autocomplete extends SingleMixin(BaseAjax) { + URL = 'https://geodatamine.fr/boundaries/search?text={q}' createResult(item) { return super.createResult({ @@ -17,24 +14,6 @@ class Autocomplete extends AjaxAutocomplete { label: `${item.name} (${item.ref})`, }) } - - async search() { - let val = this.input.value - if (val.length < this.options.minChar) { - this.clear() - return - } - if (`${val}` === `${this.cache}`) return - else this.cache = val - val = val.toLowerCase() - const response = await this.request.get( - `https://geodatamine.fr/boundaries/search?text=${encodeURIComponent(val)}` - ) - if (response && response.ok) { - const data = await response.json() - this.handleResults(data) - } - } } export class Plugin { @@ -83,7 +62,7 @@ export class Plugin { className: 'edit-owner', on_select: (choice) => this.onSelect(choice), } - this.autocomplete = new Autocomplete(this.request, container, options) + this.autocomplete = new Autocomplete(container, options) const confirm = () => { importer.urlInput.value = `${this.baseUrl}/data/${select.value}/${this.options.boundary}?format=geojson` importer.typeInput.value = 'geojson'