mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-19 15:40:50 +00:00
Make relative-time a self-maintaining custom element (#8134)
Fixes #8124 Replaces #8130 Use a custom element for relative-time. Thanks to @Beowulf for suggesting this approach. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8134 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: Beowulf <beowulf@beocode.eu> Co-authored-by: Benedikt Straub <benedikt-straub@web.de> Co-committed-by: Benedikt Straub <benedikt-straub@web.de>
This commit is contained in:
parent
b97c462d2e
commit
9b6e3b61cf
2 changed files with 37 additions and 15 deletions
|
@ -130,21 +130,42 @@ export function DoUpdateRelativeTime(object, now) {
|
||||||
return HALF_MINUTE;
|
return HALF_MINUTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update the displayed text of one relative-time DOM element with its human-readable, localized relative time string. */
|
window.customElements.define('relative-time', class extends HTMLElement {
|
||||||
function UpdateRelativeTime(object) {
|
static observedAttributes = ['datetime'];
|
||||||
const next = DoUpdateRelativeTime(object);
|
|
||||||
if (next !== null) setTimeout(() => { UpdateRelativeTime(object) }, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update the displayed text of all relative-time DOM elements with their respective human-readable, localized relative time string. */
|
alive = false;
|
||||||
function UpdateAllRelativeTimes() {
|
contentSpan = null;
|
||||||
for (const object of document.querySelectorAll('relative-time')) UpdateRelativeTime(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
update = (recurring) => {
|
||||||
UpdateAllRelativeTimes();
|
if (!this.alive) return;
|
||||||
// Also update relative-time DOM elements after htmx swap events.
|
|
||||||
document.body.addEventListener('htmx:afterSwap', () => {
|
if (!this.shadowRoot) {
|
||||||
for (const object of document.querySelectorAll('relative-time')) DoUpdateRelativeTime(object);
|
this.attachShadow({mode: 'open'});
|
||||||
});
|
this.contentSpan = document.createElement('span');
|
||||||
|
this.shadowRoot.append(this.contentSpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = DoUpdateRelativeTime(this);
|
||||||
|
if (recurring && next !== null) setTimeout(() => { this.update(true) }, next);
|
||||||
|
};
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.alive = true;
|
||||||
|
this.update(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeChangedCallback(name, oldValue, newValue) {
|
||||||
|
if (name === 'datetime' && oldValue !== newValue) this.update(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
set textContent(value) {
|
||||||
|
if (this.contentSpan) this.contentSpan.textContent = value;
|
||||||
|
}
|
||||||
|
get textContent() {
|
||||||
|
return this.contentSpan?.textContent;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,6 +23,7 @@ test('CalculateRelativeTimes', () => {
|
||||||
'relativetime.years': ['%d year ago', '%d years ago'],
|
'relativetime.years': ['%d year ago', '%d years ago'],
|
||||||
};
|
};
|
||||||
const mock = document.createElement('relative-time');
|
const mock = document.createElement('relative-time');
|
||||||
|
document.body.append(mock);
|
||||||
|
|
||||||
const now = Date.parse('2024-10-27T04:05:30+01:00'); // One hour after DST switchover, CET.
|
const now = Date.parse('2024-10-27T04:05:30+01:00'); // One hour after DST switchover, CET.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue