diff options
-rw-r--r-- | main.js | 112 |
1 files changed, 94 insertions, 18 deletions
@@ -662,11 +662,19 @@ const ageFilterSettings = (function() { } }; return Object.seal({ - active: false, + _active: false, + get active() { + return this._active; + }, + set active(b) { + ageFilterSetActive(b); + }, type: 'relative', operator: '<=', quantity: 1, unit: 'y', + from: null, + to: null, show_unknown: false, _min_ts: null, _max_ts: null, @@ -2655,7 +2663,7 @@ const STYLES = {}; ageFilterSettings.quantity = parseInt(m0[2], 10); ageFilterSettings.unit = m0[3]; ageFilterSettings.setupMinMax(); - ageFilterSettings.active = true; + ageFilterSettings._active = true; /* don't call the setter as it's not initialized yet */ return; } const m1 = /^([0-9]{8})-([0-9]{8})$/.exec(value); /* YYYYMMDD */ @@ -2670,7 +2678,7 @@ const STYLES = {}; ageFilterSettings.from = parse_date(m1[1]); ageFilterSettings.to = parse_date(m1[2]); ageFilterSettings.setupMinMax(); - ageFilterSettings.active = true; + ageFilterSettings._active = true; /* don't call the setter as it's not initialized yet */ return; } //console.log(`Ignoring invalid value for 'age-filter' parameter: ${value}`); @@ -4945,9 +4953,11 @@ const disposePopover = (function() { })(); /* age filter dialog */ -(function() { +const ageFilterSetActive = (function() { const panel = document.getElementById('age-filter-modal'); + let updateHelpTextTimeoutID = null; + const updateHelpTextState = Object.seal({ value: null }); const dialog_setup = (function() { const dialog = document.createElement('div'); dialog.classList.add('modal-dialog', 'modal-dialog-centered'); @@ -5044,6 +5054,10 @@ const disposePopover = (function() { radio.checked = true; radio.setAttribute('aria-expanded', 'true'); + if (type_choice === type_choices.relative) { + type_choice._update_helptext(); + } + Object.values(type_choices).forEach(function(x) { const isSame = radio.isEqualNode(x.radio); if (isSame) { @@ -5145,7 +5159,6 @@ const disposePopover = (function() { return null; } else { /* update help text */ - /* TODO auto update the date passed midnight (if the modal is open) */ span_date.innerHTML = format_date(d); span_direction.innerHTML = { '>=':'tidigare', '<=':'senare' }[operator]; p.classList.remove('invisible'); @@ -5290,12 +5303,6 @@ const disposePopover = (function() { btn_cancel.onclick = function() { /* deactivate deactivate the filter but preserve its settings */ ageFilterSettings.active = false; - Object.values(mapLayers).forEach(function(lyr) { - if (lyr?.get('canFilterByAge')) { - lyr.changed(); - } - }); - const params = new URLSearchParams(window.location.hash.substring(1)); params.delete('age-filter'); params.delete('show-unknown-age'); @@ -5329,14 +5336,7 @@ const disposePopover = (function() { } ageFilterSettings.type = filter_type; ageFilterSettings.show_unknown = show_unknown_age.checked; - ageFilterSettings.setupMinMax(); ageFilterSettings.active = true; - /* TODO auto update the filter passed midnight (if active) */ - Object.values(mapLayers).forEach(function(lyr) { - if (lyr?.get('canFilterByAge')) { - lyr.changed(); - } - }); const params = new URLSearchParams(window.location.hash.substring(1)); params.set('age-filter', param); @@ -5346,6 +5346,15 @@ const disposePopover = (function() { modal.hide(); }; + const updateHelpTextTimeout = function cb() { + const type_choice = type_choices.relative; + const [ms, b] = getDelay(updateHelpTextState); + if (type_choice.radio.checked && b) { + type_choice._update_helptext(); + } + updateHelpTextTimeoutID = setTimeout(cb, ms); + }; + /* Now that all elements have been added to the form, click the radio * button to show the relevant <div>, mark its fields as required and * fills them. The function is run whenever the modal is shown. */ @@ -5372,9 +5381,32 @@ const disposePopover = (function() { break; } } + + if (updateHelpTextTimeoutID == null) { + const ms = getDelay(updateHelpTextState)[0]; + updateHelpTextTimeoutID = setTimeout(updateHelpTextTimeout, ms); + } }; })(); + /* Retun the number of milliseconds left for the next full 15min at the + * wall clock, along with a boolean indicating whether we just passed + * midnight. + * Keep using setTimeout(,15min) since unlike setInterval() it allows us to avoid clock + * skews by adjusting delays */ + const getDelay = function(state) { + const i = 900, d = new Date(); /* at *:00,15,30,45:00.50 */ + const sec = (d.getHours()*60 + d.getMinutes())*60 + d.getSeconds(); + /* add 50ms to ensure formatting the date doesn't end up on the previous period */ + const ms = (Math.floor(sec/i)*i + i - sec)*1000 - d.getMilliseconds() + 50; + const v = state.value, v2 = d.getDate(); + const b = v == null || v !== v2; + if (b) { + state.value = v2; + } + return [ms, b]; + }; + const modal = new Modal(panel, { backdrop: false, }); @@ -5404,6 +5436,11 @@ const disposePopover = (function() { if (!ageFilterSettings.active) { btn.classList.replace('btn-dark', 'btn-light'); } + if (updateHelpTextTimeoutID != null) { + clearTimeout(updateHelpTextTimeoutID); + updateHelpTextState.value = null; + updateHelpTextTimeoutID = null; + } btn.setAttribute('aria-expanded', 'false'); backdrop.classList.remove('modal-backdrop', 'show'); }); @@ -5413,4 +5450,43 @@ const disposePopover = (function() { dialog_setup(); modal.show(); }; + + return (function() { /* setter for ageFilterSettings.active */ + let timeoutID = null; + const state = { value: null }; + const fun = function cb() { + const [ms, b] = getDelay(state); + if (b && ageFilterSettings.type === 'relative') { + ageFilterSettings.setupMinMax(); + changed(); + } + timeoutID = setTimeout(cb, ms); + }; + const changed = function() { + Object.values(mapLayers) + .filter((lyr) => lyr?.get('canFilterByAge')) + .forEach((lyr) => lyr.changed()); + }; + const setter = function(active) { + if (ageFilterSettings._active !== active) { + if (active) { + ageFilterSettings.setupMinMax(); + } + ageFilterSettings._active = active; + changed(); + } + if (active && ageFilterSettings.type === 'relative') { + if (timeoutID == null) { + timeoutID = setTimeout(fun, getDelay(state)[0]); + } + } else if (timeoutID != null) { + clearTimeout(timeoutID); + state.value = null; + timeoutID = null; + } + }; + /* initial activation from param URL */ + setter(ageFilterSettings._active); + return setter; + })(); })(); |