Skip to content

Commit

Permalink
feat: Add a Countdown Timer Widget (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
nfreear committed May 13, 2022
1 parent 6dc7d0d commit ff90439
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
55 changes: 55 additions & 0 deletions demo/my-countdown.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!doctype html><html lang="en"><title>my-countdown</title>

<meta name="viewport" content="width=device-width,initial-scale=1">

<link rel="stylesheet" href="style/app.css" />

<style>
:root {
--my-countdown-bg-label: #ddd;
--my-countdown-bg-num: #eee;
}

my-countdown {
border: 1px solid #ddd;
font: 1.1rem Georgia, serif;
margin: 1rem 0;
padding: .25rem;

X-background: yellow;
X-color: red;
}

my-countdown,
my-countdown > .ft {
display: inline-block;
width: 13.5rem;
}

.big {
font-size: 1.8rem;
}
.big,
.big .ft {
width: 22rem;
}
</style>

<my-page>
<h2> my-countdown </h2>

<p></p>

<my-countdown class="big" datetime="2022-12-31 23:59:59"><div class="ft">Until midnight on 31<sup>st</sup> December 2022</div></my-countdown>

<my-code>
&lt;my-countdown
datetime="2022-12-31 23:59:59"
>Until midnight on 31st December 2022
&lt;/my-countdown>
</my-code>
</my-page>

<script type="module" src="./app.js"></script>

</html>
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export { MyAtbarButtonElement } from './src/components/MyAtbarButtonElement.js';
export { MyFontElement } from './src/components/MyFontElement.js';
export { MySearchElement } from './src/components/MySearchElement.js';
export { MyGaadWidgetElement } from './src/components/MyGaadWidgetElement.js';
export { MyCountdownElement } from './src/components/MyCountdownElement.js';

export { MyElement } from './src/MyElement.js';

Expand Down
95 changes: 95 additions & 0 deletions src/components/MyCountdownElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* A Countdown Timer Widget.
*
* @copyright © Nick Freear, 07-May-2022.
*
* @see https://geeksforgeeks.org/create-countdown-timer-using-javascript/
*/

import { MyElement } from '../MyElement.js';

const STYLES = `
.countdown { display: inline-block; line-height: 1.6; }
.countdown > * { text-align: center; }
span { background: var(--my-countdown-bg-num, transparent); display: inline-block; margin: 0 1.5%; width: 29%; }
tx { background: var(--my-countdown-bg-label, transparent); display: block; font-size: 75%; padding: .25rem 0; }
num { display: block; font-size: 200%; min-height: 3rem; padding: .5rem 0; }
footer { font-size: 70%; margin: .6rem 0; }
.red { color: red; }
`;

/* const STYLES = `
.countdown { display: inline-block; }
.countdown > * { text-align: center; }
span { background: #eee; display: inline-block; margin: 0 .2rem; width: 4.2rem; }
tx { background: #ddd; display: block; font-size: small; padding: .25rem 0; }
num { display: block; font-size: 2.2rem; min-height: 3rem; padding: .5rem 0; }
footer { font-size: small; }
`; */

const INTERVAL_MS = 5 * 1000;

export class MyCountdownElement extends MyElement {
static getTag () {
return 'my-countdown';
}

async connectedCallback () {
const datetime = this.getAttribute('datetime') || '2022-12-31 23:59:59';

const countdown = this._calculate(datetime);
const ELEM = document.createElement('div');
const STYLE_EL = document.createElement('style');

ELEM.innerHTML = this._template(countdown);
ELEM.classList.add('countdown');
// ELEM.classList.add('red');
STYLE_EL.textContent = STYLES;

this.attachShadow({ mode: 'open' }).appendChild(STYLE_EL);
this.shadowRoot.appendChild(ELEM);

setInterval(() => {
const CD = this._calculate(datetime);

ELEM.title = `… and ${CD.seconds} seconds`;
ELEM.innerHTML = this._template(CD);

console.debug('.');
},
INTERVAL_MS);

console.debug('my-countdown:', countdown, this);
}

_template (countdown) {
const { days, hours, minutes, deadline } = countdown;

return `
<span class="dd"><num>${days}</num> <tx>days</tx></span>
<span class="hh"><num>${hours}</num> <tx>hours</tx></span>
<span class="mm"><num>${minutes}</num> <tx>minutes</tx></span>
<footer><time datetime="${deadline}"><slot></slot></time></footer>
`;
}

_calculate (deadlineStr) {
const deadline = new Date(deadlineStr).getTime();
const now = new Date().getTime();
const diff = deadline - now;

if (isNaN(deadline)) {
throw new Error(`Input not recognized as a date-time: '${deadlineStr}'`);
}

const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);

return { days, hours, minutes, seconds, deadline: deadlineStr, diff, expired: diff < 0 };
}
}

MyCountdownElement.define();

0 comments on commit ff90439

Please sign in to comment.