From 9a4ad0bd7ce014a4bb9e827df125c9b52b03dbd2 Mon Sep 17 00:00:00 2001 From: Dylan Clarke Date: Wed, 17 Apr 2024 16:41:11 +0100 Subject: [PATCH] feat(CountdownController): New configuration value `padZeros` to control whether hours, minutes and seconds are output as zero-padded or not. Also fixed `removeUnused` behaviour. (#351) The default is "true" so if you are expecting hours minutes and seconds to be unpadded, you'll need to add data-countdown-pad-zeros="false" to your controller elements. --- .../visual/countdown_controller.mdx | 9 ++- .../controllers/countdown_controller.html | 51 +++++++++---- .../src/visual/countdown_controller.ts | 76 +++++++++++++------ 3 files changed, 96 insertions(+), 40 deletions(-) diff --git a/docs/docs/controllers/visual/countdown_controller.mdx b/docs/docs/controllers/visual/countdown_controller.mdx index 53df7f13..8cab81cd 100644 --- a/docs/docs/controllers/visual/countdown_controller.mdx +++ b/docs/docs/controllers/visual/countdown_controller.mdx @@ -37,10 +37,11 @@ A controller that displays a countdown clock to a specified date/time. ## [Values](https://stimulus.hotwire.dev/reference/values) -| Value | Type | Description | Default | -|----------------|---------|-------------------------------------------------------------------------------|---------| -| `deadline` | Date | The date/time to count down to | - | -| `removeUnused` | Boolean | Whether to remove unused targets. i.e. if there are no years in the countdown | `false` | +| Value | Type | Description | Default | +|----------------|---------|---------------------------------------------------------------------------------------------------------|---------| +| `deadline` | Date | The date/time to count down to | - | +| `removeUnused` | Boolean | Whether to remove unused targets. i.e. if there are no years in the countdown | `false` | +| `padZeros` | Boolean | Whether to pad the countdown values for hours, minutes, and seconds with zeros i.e. "06" instead of "6" | `true` | ## Events diff --git a/examples/controllers/countdown_controller.html b/examples/controllers/countdown_controller.html index cae58ef4..fd70d81e 100644 --- a/examples/controllers/countdown_controller.html +++ b/examples/controllers/countdown_controller.html @@ -2,20 +2,22 @@ - - + + Countdown Controller

Countdown til next Christmas:

@@ -25,42 +27,63 @@
+
+

+ Sale ends in: +

+ +
+ + : + + : + +
- + diff --git a/packages/controllers/src/visual/countdown_controller.ts b/packages/controllers/src/visual/countdown_controller.ts index 45c10371..78723971 100644 --- a/packages/controllers/src/visual/countdown_controller.ts +++ b/packages/controllers/src/visual/countdown_controller.ts @@ -6,7 +6,11 @@ import { installClassMethods } from "@stimulus-library/mixins"; export class CountdownController extends BaseController { - static values = { deadline: String, removeUnused: Boolean }; + static values = { + deadline: String, + removeUnused: Boolean, + padZeros: Boolean, + }; static targets = ["years", "months", "days", "hours", "minutes", "seconds"]; static classes = ["countingDown", "ended"]; @@ -14,6 +18,8 @@ export class CountdownController extends BaseController { declare readonly deadlineValue: string; declare readonly removeUnusedValue: boolean; declare readonly hasRemoveUnusedValue: boolean; + declare readonly padZerosValue: boolean; + declare readonly hasPadZerosValue: boolean; // Targets declare readonly hasYearsTarget: boolean; declare readonly yearsTarget: HTMLElement; @@ -40,6 +46,10 @@ export class CountdownController extends BaseController { return this.hasRemoveUnusedValue ? this.removeUnusedValue : false; } + get _padZeros(): boolean { + return this.hasPadZerosValue ? this.padZerosValue : true; + } + get _deadlineDate() { return new Date(this.deadlineValue); } @@ -50,7 +60,6 @@ export class CountdownController extends BaseController { connect() { this._timeout = setTimeout(this._tick, 1000); - console.log(this._timeout); installClassMethods(this); this.addCountingDownClasses(); } @@ -82,7 +91,7 @@ export class CountdownController extends BaseController { this.dispatchEvent(this.el, this.eventName("ended")); return; } else { - distance = intervalToDuration({ start: this._deadlineDate, end: now }); + distance = intervalToDuration({ start: now, end: this._deadlineDate }); this._timeout = setTimeout(this._tick, 1000); } @@ -117,47 +126,70 @@ export class CountdownController extends BaseController { } } - _updateTarget(target: HTMLElement, value: number) { + _updateTarget(target: HTMLElement, value: string) { this._removeTargetIfUnused(target, value); - target.innerHTML = value.toString(); + target.innerHTML = value; } - _removeTargetIfUnused(target: HTMLElement, value: number) { + _removeTargetIfUnused(target: HTMLElement, value: string) { + let intValue = Number.parseInt(value); if (this._removeUnused) { - if (value === 0 && target.dataset.unused) { - if (Number.parseInt(target.dataset.unused) > Date.now() + 1500) { + if (intValue === 0 && target.dataset.unused) { + let number = Number.parseInt(target.dataset.unused); + if (number < Date.now() - 1000) { target.remove(); } - } else if (value == 0) { + } else if (intValue == 0) { target.dataset.unused = Date.now().toString(); } else { - target.dataset.unused = undefined; + delete target.dataset.unused; } } } - _years(duration: Duration): number { - return duration.years || 0; + _years(duration: Duration): string { + let unit = duration.years || 0; + return (unit > 0 ? unit : 0).toString(); } - _months(duration: Duration): number { - return duration.months || 0; + _months(duration: Duration): string { + let unit = duration.months || 0; + return (unit > 0 ? unit : 0).toString(); } - _days(duration: Duration): number { - return duration.days || 0; + _days(duration: Duration): string { + let unit = duration.days || 0; + return (unit > 0 ? unit : 0).toString(); } - _hours(duration: Duration): number { - return duration.hours || 0; + _hours(duration: Duration): string { + let unit = duration.hours || 0; + let str = (unit > 0 ? unit : 0).toString(); + if (this._padZeros) { + return str.padStart(2, "0"); + } else { + return str; + } } - _minutes(duration: Duration): number { - return duration.minutes || 0; + _minutes(duration: Duration): string { + let unit = duration.minutes || 0; + let str = (unit > 0 ? unit : 0).toString(); + if (this._padZeros) { + return str.padStart(2, "0"); + } else { + return str; + } } - _seconds(duration: Duration): number { - return duration.seconds || 0; + _seconds(duration: Duration): string { + let unit = duration.seconds || 0; + let str = (unit > 0 ? unit : 0).toString(); + if (this._padZeros) { + return str.padStart(2, "0"); + } else { + return str; + } } }