draft
This commit is contained in:
parent
65671ab7ba
commit
9c3ac133e3
23 changed files with 330 additions and 273 deletions
|
@ -0,0 +1,4 @@
|
|||
|
||||
Please note:
|
||||
1. We clear `setInterval` timer when the element is removed from the document. That's important, otherwise it continues ticking even if not needed any more. And the browser can't clear the memory from this element and referenced by it.
|
||||
2. We can access current date as `elem.date` property. All class methods and properties are naturally element methods and properties.
|
|
@ -0,0 +1,9 @@
|
|||
<!doctype html>
|
||||
<script src="time-formatted.js"></script>
|
||||
<script src="live-timer.js"></script>
|
||||
|
||||
<live-timer id="elem"></live-timer>
|
||||
|
||||
<script>
|
||||
elem.addEventListener('tick', event => console.log(event.detail));
|
||||
</script>
|
|
@ -0,0 +1,32 @@
|
|||
class LiveTimer extends HTMLElement {
|
||||
|
||||
render() {
|
||||
this.innerHTML = `
|
||||
<time-formatted hour="numeric" minute="numeric" second="numeric">
|
||||
</time-formatted>
|
||||
`;
|
||||
|
||||
this.timerElem = this.firstElementChild;
|
||||
}
|
||||
|
||||
connectedCallback() { // (2)
|
||||
if (!this.rendered) {
|
||||
this.render();
|
||||
this.rendered = true;
|
||||
}
|
||||
this.timer = setInterval(() => this.update(), 1000);
|
||||
}
|
||||
|
||||
update() {
|
||||
this.date = new Date();
|
||||
this.timerElem.setAttribute('datetime', this.date);
|
||||
this.dispatchEvent(new CustomEvent('tick', { detail: this.date }));
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
clearInterval(this.timer); // important to let the element be garbage-collected
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define("live-timer", LiveTimer);
|
|
@ -0,0 +1,34 @@
|
|||
class TimeFormatted extends HTMLElement {
|
||||
|
||||
render() {
|
||||
let date = new Date(this.getAttribute('datetime') || Date.now());
|
||||
|
||||
this.innerHTML = new Intl.DateTimeFormat("default", {
|
||||
year: this.getAttribute('year') || undefined,
|
||||
month: this.getAttribute('month') || undefined,
|
||||
day: this.getAttribute('day') || undefined,
|
||||
hour: this.getAttribute('hour') || undefined,
|
||||
minute: this.getAttribute('minute') || undefined,
|
||||
second: this.getAttribute('second') || undefined,
|
||||
timeZoneName: this.getAttribute('time-zone-name') || undefined,
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (!this.rendered) {
|
||||
this.render();
|
||||
this.rendered = true;
|
||||
}
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['datetime', 'year', 'month', 'day', 'hour', 'minute', 'second', 'time-zone-name'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
this.render();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define("time-formatted", TimeFormatted);
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<!-- don't modify this -->
|
||||
<script src="time-formatted.js"></script>
|
||||
|
||||
<!-- your code here: -->
|
||||
<script src="live-timer.js"></script>
|
||||
|
||||
<live-timer id="elem"></live-timer>
|
||||
|
||||
<script>
|
||||
elem.addEventListener('tick', event => console.log(event.detail));
|
||||
</script>
|
|
@ -0,0 +1,7 @@
|
|||
class LiveTimer extends HTMLElement {
|
||||
|
||||
/* your code here */
|
||||
|
||||
}
|
||||
|
||||
customElements.define("live-timer", LiveTimer);
|
|
@ -0,0 +1,34 @@
|
|||
class TimeFormatted extends HTMLElement {
|
||||
|
||||
render() {
|
||||
let date = new Date(this.getAttribute('datetime') || Date.now());
|
||||
|
||||
this.innerHTML = new Intl.DateTimeFormat("default", {
|
||||
year: this.getAttribute('year') || undefined,
|
||||
month: this.getAttribute('month') || undefined,
|
||||
day: this.getAttribute('day') || undefined,
|
||||
hour: this.getAttribute('hour') || undefined,
|
||||
minute: this.getAttribute('minute') || undefined,
|
||||
second: this.getAttribute('second') || undefined,
|
||||
timeZoneName: this.getAttribute('time-zone-name') || undefined,
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (!this.rendered) {
|
||||
this.render();
|
||||
this.rendered = true;
|
||||
}
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['datetime', 'year', 'month', 'day', 'hour', 'minute', 'second', 'time-zone-name'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
this.render();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define("time-formatted", TimeFormatted);
|
23
8-web-components/2-custom-elements/1-live-timer/task.md
Normal file
23
8-web-components/2-custom-elements/1-live-timer/task.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
|
||||
# Live timer element
|
||||
|
||||
We already have `<time-formatted>` element to show a nicely formatted time.
|
||||
|
||||
Create `<live-timer>` element to show the current time:
|
||||
1. It should use `<time-formatted>` internally, not duplicate its functionality.
|
||||
2. Ticks (updates) every second.
|
||||
3. For every tick, a custom event named `tick` should be generated, with the current date in `event.detail` (see chapter <info:dispatch-events>).
|
||||
|
||||
Usage:
|
||||
|
||||
```html
|
||||
<live-timer id="elem"></live-timer>
|
||||
|
||||
<script>
|
||||
elem.addEventListener('tick', event => console.log(event.detail));
|
||||
</script>
|
||||
```
|
||||
|
||||
Demo:
|
||||
|
||||
[iframe src="solution" height=40]
|
Loading…
Add table
Add a link
Reference in a new issue