aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.js112
1 files changed, 94 insertions, 18 deletions
diff --git a/main.js b/main.js
index 3455e46..c0a3186 100644
--- a/main.js
+++ b/main.js
@@ -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;
+ })();
})();