diff --git a/umap/static/umap/css/icon.css b/umap/static/umap/css/icon.css index 69778b26..59a73aaa 100644 --- a/umap/static/umap/css/icon.css +++ b/umap/static/umap/css/icon.css @@ -79,6 +79,9 @@ .icon-resize { background-position: -74px -144px; } +.icon-restore { + background-position: -121px -74px; +} .expanded .icon-resize { background-position: -50px -144px; } diff --git a/umap/static/umap/js/modules/browser.js b/umap/static/umap/js/modules/browser.js index 22811c86..db281a19 100644 --- a/umap/static/umap/js/modules/browser.js +++ b/umap/static/umap/js/modules/browser.js @@ -109,13 +109,17 @@ export default class Browser { counter.title = translate(`Features in this layer: ${count}`) } + toggleBadge() { + U.Utils.toggleBadge(this.filtersTitle, this.hasFilters()) + U.Utils.toggleBadge('.umap-control-browse', this.hasFilters()) + } + onFormChange() { this.map.eachBrowsableDataLayer((datalayer) => { datalayer.resetLayer(true) this.updateDatalayer(datalayer) }) - U.Utils.toggleBadge(this.filtersTitle, this.hasFilters()) - U.Utils.toggleBadge('.umap-control-browse', this.hasFilters()) + this.toggleBadge() } redraw() { @@ -164,7 +168,7 @@ export default class Browser { icon: 'icon-filters', }) this.filtersTitle = container.querySelector('summary') - U.Utils.toggleBadge(this.filtersTitle, this.hasFilters()) + this.toggleBadge() this.dataContainer = DomUtil.create('div', '', container) let fields = [ @@ -177,14 +181,27 @@ export default class Browser { const builder = new L.FormBuilder(this, fields, { callback: () => this.onFormChange(), }) + let filtersBuilder formContainer.appendChild(builder.build()) + DomEvent.on(builder.form, 'reset', () => { + window.setTimeout(builder.syncAll.bind(builder)) + }) if (this.map.options.facetKey) { fields = this.map.facets.build() - const builder = new L.FormBuilder(this.map.facets, fields, { + filtersBuilder = new L.FormBuilder(this.map.facets, fields, { callback: () => this.onFormChange(), }) - formContainer.appendChild(builder.build()) + DomEvent.on(filtersBuilder.form, 'reset', () => { + window.setTimeout(filtersBuilder.syncAll.bind(filtersBuilder)) + }) + formContainer.appendChild(filtersBuilder.build()) } + const reset = DomUtil.createButton('flat', formContainer, '', () => { + builder.form.reset() + if (filtersBuilder) filtersBuilder.form.reset() + }) + DomUtil.createIcon(reset, 'icon-restore') + DomUtil.element({ tagName: 'span', parent: reset, textContent: translate('Reset all') }) this.map.panel.open({ content: container, diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index deecd6dc..3bb0e5df 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -823,10 +823,12 @@ L.FormBuilder.MinMaxBase = L.FormBuilder.FacetSearchBase.extend({ this.minInput.type = this.inputType this.minInput.step = 'any' if (min != null) { - this.minInput.valueAsNumber = this.prepareForHTML(currentMin) this.minInput.dataset.value = min + // Use setAttribute so to restore to this value when resetting + // form. + // https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset + this.minInput.setAttribute('value', this.prepareForHTML(min)) } - this.minInput.dataset.modified = this.isMinModified() this.maxLabel = L.DomUtil.create('label', '', this.container) this.maxLabel.textContent = maxLabel @@ -835,19 +837,23 @@ L.FormBuilder.MinMaxBase = L.FormBuilder.FacetSearchBase.extend({ this.maxInput.type = this.inputType this.maxInput.step = 'any' if (max != null) { - this.maxInput.valueAsNumber = this.prepareForHTML(currentMax) this.maxInput.dataset.value = max + this.maxInput.setAttribute('value', this.prepareForHTML(max)) } - this.maxInput.dataset.modified = this.isMaxModified() + this.toggleStatus() - L.DomEvent.on(this.minInput, 'change', (e) => this.sync()) - L.DomEvent.on(this.maxInput, 'change', (e) => this.sync()) + L.DomEvent.on(this.minInput, 'change', () => this.sync()) + L.DomEvent.on(this.maxInput, 'change', () => this.sync()) + }, + + toggleStatus: function () { + this.minInput.dataset.modified = this.isMinModified() + this.maxInput.dataset.modified = this.isMaxModified() }, sync: function () { L.FormBuilder.Element.prototype.sync.call(this) - this.minInput.dataset.modified = this.isMinModified() - this.maxInput.dataset.modified = this.isMaxModified() + this.toggleStatus() }, isMinModified: function () { @@ -889,10 +895,16 @@ L.FormBuilder.FacetSearchDate = L.FormBuilder.MinMaxBase.extend({ return new Date(value) }, - prepareForHTML: function (value) { - // Deal with timezone - return value.valueOf() - value.getTimezoneOffset() * 60000 + toLocaleDateTime: function (dt) { + return new Date(dt.valueOf() - dt.getTimezoneOffset() * 60000) }, + + prepareForHTML: function (value) { + // Value must be in local time + if (isNaN(value)) return + return this.toLocaleDateTime(value).toISOString().substr(0, 10) + }, + getLabels: function () { return [L._('From'), L._('Until')] }, @@ -902,6 +914,12 @@ L.FormBuilder.FacetSearchDateTime = L.FormBuilder.FacetSearchDate.extend({ getInputType: function (type) { return 'datetime-local' }, + + prepareForHTML: function (value) { + // Value must be in local time + if (isNaN(value)) return + return this.toLocaleDateTime(value).toISOString().slice(0, -1) + }, }) L.FormBuilder.MultiChoice = L.FormBuilder.Element.extend({