diff --git a/src/relative-time-element.ts b/src/relative-time-element.ts index 298cb65..431777a 100644 --- a/src/relative-time-element.ts +++ b/src/relative-time-element.ts @@ -79,6 +79,7 @@ const dateObserver = new (class { export default class RelativeTimeElement extends HTMLElement implements Intl.DateTimeFormatOptions { #customTitle = false + #updating = false get #lang() { return this.closest('[lang]')?.getAttribute('lang') ?? 'default' @@ -336,11 +337,16 @@ export default class RelativeTimeElement extends HTMLElement implements Intl.Dat // Internal: Refresh the time element's formatted date when an attribute changes. attributeChangedCallback(attrName: string, oldValue: unknown, newValue: unknown): void { if (oldValue === newValue) return - if (attrName === 'title') this.#customTitle = true - if (!this.#customTitle) this.update() + if (attrName === 'title') { + this.#customTitle = newValue !== null && this.getFormattedTitle() !== newValue + } + if (!this.#updating && !(attrName === 'title' && this.#customTitle)) { + this.update() + } } update() { + this.#updating = true const oldText: string = this.#renderRoot.textContent || '' const oldTitle: string = this.getAttribute('title') || '' let newTitle: string = oldTitle @@ -348,10 +354,7 @@ export default class RelativeTimeElement extends HTMLElement implements Intl.Dat const now = new Date() if (!this.#customTitle) { newTitle = this.getFormattedTitle() || '' - if (newTitle) { - this.setAttribute('title', newTitle) - this.#customTitle = false - } + if (newTitle) this.setAttribute('title', newTitle) } newText = this.getFormattedDate(now) || '' @@ -374,5 +377,6 @@ export default class RelativeTimeElement extends HTMLElement implements Intl.Dat } else { dateObserver.unobserve(this) } + this.#updating = false } } diff --git a/test/relative-time.js b/test/relative-time.js index 79a8059..de0c687 100644 --- a/test/relative-time.js +++ b/test/relative-time.js @@ -56,6 +56,19 @@ suite('relative-time', function () { assert.equal(counter, 1) el.setAttribute('title', 'another custom') assert.equal(counter, 1) + el.removeAttribute('title') + assert.equal(counter, 2) + }) + + test('sets title back to default if removed', () => { + const el = document.createElement('relative-time') + el.setAttribute('datetime', new Date().toISOString()) + assert.ok(el.getAttribute('title')) + const text = el.getAttribute('title') + el.setAttribute('title', 'custom') + assert.equal(el.getAttribute('title'), 'custom') + el.removeAttribute('title') + assert.equal(el.getAttribute('title'), text) }) test('shadowDOM reflects textContent with invalid date', () => {