Skip to content

Commit

Permalink
Merge pull request #200 from github/avoid-eagerly-calling-this-update
Browse files Browse the repository at this point in the history
avoid eagerly calling this.update()
  • Loading branch information
keithamus committed Nov 7, 2022
2 parents 4bc8693 + 38e1be5 commit 709a65b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 10 deletions.
27 changes: 18 additions & 9 deletions src/relative-time-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,26 @@ function getUnitFactor(ms: number): number {

const dateObserver = new (class {
elements: Set<RelativeTimeElement> = new Set()
time = 0

observe(element: RelativeTimeElement) {
if (this.elements.has(element)) return
this.elements.add(element)
this.update()
const date = element.date
if (date && date.getTime()) {
const ms = getUnitFactor(date.getTime())
const time = Date.now() + ms
if (time < this.time) {
clearTimeout(this.timer)
this.timer = setTimeout(() => this.update, ms)
this.time = time
}
}
}

unobserve(element: RelativeTimeElement) {
if (!this.elements.has(element)) return
this.elements.delete(element)
this.update()
}

timer: ReturnType<typeof setTimeout> = -1 as unknown as ReturnType<typeof setTimeout>
Expand All @@ -52,8 +61,9 @@ const dateObserver = new (class {
nearestDistance = Math.min(nearestDistance, distance)
timeEl.update()
}
const ms = Math.min(60 * 60 * 1000, nearestDistance)
this.timer = setTimeout(() => this.update(), ms)
this.time = Math.min(60 * 60 * 1000, nearestDistance)
this.timer = setTimeout(() => this.update(), this.time)
this.time += Date.now()
}
})()

Expand Down Expand Up @@ -298,11 +308,10 @@ export default class RelativeTimeElement extends HTMLElement implements Intl.Dat
}

// Internal: Refresh the time element's formatted date when an attribute changes.
attributeChangedCallback(attrName: string): void {
if (attrName === 'title') {
this.#customTitle = true
}
this.update()
attributeChangedCallback(attrName: string, oldValue: unknown, newValue: unknown): void {
if (oldValue === newValue) return
if (attrName === 'title') this.#customTitle = true
if (!this.#customTitle) this.update()
}

update() {
Expand Down
22 changes: 21 additions & 1 deletion test/relative-time.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {assert} from '@open-wc/testing'
import '../src/relative-time-element.ts'
import RelativeTimeElement from '../src/relative-time-element.ts'

suite('relative-time', function () {
let dateNow
Expand Down Expand Up @@ -38,6 +38,26 @@ suite('relative-time', function () {
}
})

test('does not call update() frequently with attributeChangedCallback', () => {
let counter = 0
const el = document.createElement('relative-time')
el.update = function () {
counter += 1
return RelativeTimeElement.prototype.update.call(this)
}
assert.equal(counter, 0)
el.setAttribute('datetime', new Date().toISOString())
assert.equal(counter, 1)
el.setAttribute('datetime', el.getAttribute('datetime'))
assert.equal(counter, 1)
el.disconnectedCallback()
assert.equal(counter, 1)
el.setAttribute('title', 'custom')
assert.equal(counter, 1)
el.setAttribute('title', 'another custom')
assert.equal(counter, 1)
})

test("doesn't error when no date is provided", function () {
const element = document.createElement('relative-time')
assert.doesNotThrow(() => element.attributeChangedCallback('datetime', null, null))
Expand Down

0 comments on commit 709a65b

Please sign in to comment.