<talking-timer>
- Introduction
- How it works
- Attributes
- External default config
- Styling
A custom element for visual and audio countdown timing. (For when my kids need to stop doing a thing they don't want to stop. And for when I'm teaching and running a time sensitive exercise)
<talking-timer>
uses the Web Speech API,
the Web Audio API
and custom elements to build a
Web component
that provides audio and visual representation of the progress of a timer.
You can see it in action on CodePen
- You create a
<talking-timer time="HH:MM:SS"></talking-timer>
element. - When you're ready you press the "Start" button and the timer begins counting down
- Then as it reaches defined times it announces the time reached (e.g. "Half way.")
- When it reaches zero, it says "Time's up." (or whatever you've
set
end-message
to and plays a chime
At it's most basic you can configure a reusable timer like so: (this is a three minute timer)
<talking-timer time="03:00">Egg timer</talking-timer>
The text within the element wrapper is used a the title for the time.
Duration of the timer.
The time
attribute is required and can either be the total number
of seconds or a time string (HH:MM:SS
)
NOTE: hours & minutes are optional
<talking-timer time="03:00">
Three minute timer
</talking-timer>
<talking-timer time="180">
Three minute timer (defined as seconds)
</talking-timer>
<talking-timer time="2:15:00">
Two hours and fifteen minute timer
</talking-timer>
end-message
allows you to control what is spoken when a timer completes.
NOTE: If you use the
nosayend
attribute andend-message
,nosayend
will be ignored on the assumption that if you're going to the trouble to specify a custom end message, then you want it to be spoken, thusnosayend
is a mistake.'
<talking-timer time="03:00" end-message="What??? Still not loaded???">
Sitecore page load
</talking-timer>
By default speak
is set to "1/2 30s last20 last15 allLast10"
:
1/2
- announce the "Half way." interval30s
- announce every 30 second and 1 minute interval (e.g. for a three minute timer that would be "30 seconds gone.", "1 minute gone.", "1 minute to go.", "30 seconds to go.". NOTE: "1 minute, 30 seconds" is the same as "Half way.". Because1/2
was defined first, it has higher priority so "1 minute, 30 seconds" is omitted.)last20
(same aslast20s
) = "20 seconds to go."last15
(same aslast15s
) = "15 seconds" (as intervals get closer together, there's less time to say everything so we drop the "to go." part)allLast10
count down from 10 ("Ten!", "Nine!", "Eights!", "Seven!", "Six!", "Five!", "Four!", "Three!", "Two!", "One!")
NOTE: Text to speech is not fully supported by all browsers
NOTE:
speak
options are not case sensitive, and their parts can be hyphen or underscore separated for better readability.
- Time interval:
[all|every|X][last|first][YY][s|m|h]
or- (hypen separated)
[all|X]][last|first]-[YY]-[s|m|h]
or - (underscore separated)
[all]_[last|first]_[YY]_[s|m|h]
- Fraction interval:
[all|every|X][last|first]1/[2, 3, 4, 5, 6, 7, 8, 9, 10]
or- (hypen separated)
[all|X]-[last|first]-1/[2, 3, 4, 5, 6, 7, 8, 9, 10]
or - (underscore separated)
[all|X]_[last|first]_1/[2, 3, 4, 5, 6, 7, 8, 9, 10]
-
all
- is a modifier forlast
&first
.all
is assumed iflast
/last
is not present. All of these intervals are spoken (e.g.all
Last5m
: speak 5, 4, 3, 2 & 1 minutes to go) or (e.gall
5m
=5m
: if timer if 25 minutes speak 20, 15, 10 & 5 minutes to go) -
X
(represents a number) is a modifier forlast
&first
. When present, it multiplies the number of times a give interval is announced (e.g.3last15
- same aslast15
&last30
&last45
- would result in "45 seconds to go.", "30 seconds to go." & "15 Seconds") or (e.g. 2last1/5 - would result in both "Two fifths to go." & "One fifth to go" being announced) -
every
- works in the same way asX
but every interval is spoken for the duration of the timer relative tolast
/first
. (e.g. everyLast30 - for a three minute timer: "2 minutes and 30 seconds to go.", "2 minutes to go.", "1 minute and 30 seconds to go.", "1 minute to go.", "30 seconds to go.") or (e.g. everyLast1/4 - # a three minute timer: "3 quarters to go.", "Half way.", "1 quarter to go.") -
last
|first
- this interval is spoken when its based on the time remaining (for last) or time ellapsed (for first). (e.g.last
5m
: speak the interval five minutes from the end of the timer.) or (e.g.first
1m
: speak "One minute passed." after the time has run for a minute.) NOTE: Whenall
&first
/last
are combined with a fraction, the fractions are spoken after or before the halfway mark respectively. (e.g.all
First
1/5
"One Fifth gone." & "Two fifths gone." will be spoken) (e.g.every
First
1/5
"One Fifth gone.", "two Fifth gone.", "three Fifth gone." & "four fifths gone." will be spoken)
YY
: (YY
represents digits) - the number of seconds/minutes/hours from the end (e.g.all
5
m
: speak interval every 5 minutes)s
|m
|h
-s
= seconds,m
= minutes,h
= hours (NOTE: if this is omitted seconds are assumend)
1/2
,1/3
,1/4
,1/5
,1/6
,1/7
,1/8
,1/9
,1/10
fraction of total time to be announced.
<!-- -->
<talking-timer time="03:00" speak="1m allLast10">
Only speak minute intervals and countdown last 10 seconds
<!--
"1 minute gone."
"1 minute to go."
"10", "9", "8", "7", "6", "5", "4", "3", "2", "1"
"Time's up."
-->
</talking-timer>
<talking-timer time="03:00" nospeak="1/3 last20 1m">
Only speak thirds, minute intervals and
last second announcements
<!--
NOTE: In this example `1m` is redundant because it's the same as 1/3,
so it is omitted because, by default, franction intervals
have priority over time intervals)
"One third gone."
"One third to go."
"20 seconds to go."
"Time's up."
-->
</talking-timer>
<talking-timer time="03:00" nospeak="1/3 last20 1m" priority="time">
Only speak thirds, minute intervals and
last second announcements
<!--
NOTE: In this example `1/3` is redundant because it's the same as 1m.
With priority set to `time`, fractions are omitted if they
over lap an equivalent time interval.
"1 minute gone."
"1 minute to go."
"20 seconds to go."
"Time's up."
-->
</talking-timer>
<talking-timer time="03:00">
Speak default announcements
<!--
"30 seconds gone."
"1 minute gone."
"Half way."
"1 minute to go."
"30 seconds to go."
"20 seconds to go."
"15 seconds."
"10", "9", "8", "7", "6", "5", "4", "3", "2", "1"
"Time's up."
-->
</talking-timer>
<talking-timer time="03:00" speak="" nosayend>
Nothing in speak (i.e. empty whitelist)
Don't speak any announcments - Silent (but play tone at the end)
</talking-timer>
NOTE: When announcements overlap (e.g. 3 minute time with minutes and thirds) Minute announcements are spoken and fractions are skipped
Hide the "Pause" from the user interface (UI) button while the timer is counting.
NOTE:
nopause
also hides the "Start again", "Reset" & "Close X" buttons during time activity
Hides the Start again
button from the UI
Hides the Reset
button from the UI
By default "Time's up!" is spoken when a timer ends. By including
nosayend
you can block this behaviour.
NOTE: You can configure what is spoken at the end of a timer by using the
end-message
attributes.
Note also: if
end-message
is present, nosayend is ignored on the basis that if you go to the trouble of specifyingend-message
, then nosayend is probably a mistake
By default, a short 5 second chime is played upon timer completion.
If you're using the timer on Firefox mobile the chime sounds
TERRIBLE you can use no noendchime
to disable it.
Removed the ability to configure <talking-timer>
NOTE: When the timer is active changing the configuration functionality is disabled. (i.e. changing configuration is only possible before the timer starts and after the timer has finished.)
If you don't want the timer to be able to be dismissed, use noclosebtn
NOTE:
noclosebtn
&selfdestruct
are mutually exclusive. ifselfdestruct
is simply boolean thennoclosebtn
will override it and prevent the node from being automatically removed after completion of timer.
Conversly, ifselfdestruct
is set with a numeric value (e.g.selfdestruct="5"
) then it assumes thatnoclosebutton
is a mistake, sonoclosebutton
is ignored
autoreset
causes the timer to automatically reset itself when it completes.
By default nothing is spoken when a timer starts by the including
saystart
attribute "Ready! Set! Go!" is spoken.
NOTE: Start text can be configured using the [
start-message
] (#start-message) attribute (see below)
To reduce the amount of talking, announcements can only be made if they are seven seconds later or earlier than another anouncement. By default fraction anouncements have priority e.g. when the timer is set to 3 minutes, the "Half way" announcement is also the same as the "One minute, thirty seconds to go" anouncement so the "Half way" announcement is spoken but the "One minute, thirty seconds to go." is skipped.
It's possible (even probable) that, when using fraction intervals
(like 1/2
) and time intervals (like 30s
) you will get two
announcements for the same interval. In this case, the priority
decides which is spoken.
fraction
(default) Fraction intervals are spoken if there's a confilict between a time and a fraction announcement.time
time intervals are spoken if there's a confilict between a time and a fraction announcement.order
order they're defined inspeak
- the one defined first over-rides one spoken at a similar time but defined later.
<talking-timer time="03:00">
When the timer is set to 3 minutes, the "Half way." announcement is
also the same as the "One minute, thirty seconds to go." anouncement
so the "Half way." announcement is spoken but the "One minute,
thirty seconds to go." is skipped.
</talking-timer>
<talking-timer time="03:00" priority="time">
When the timer is set to 3 minutes, the "Half way." announcement is
also the same as the "One minute, thirty seconds to go." anouncement
so the "One minute, thirty seconds to go." announcement is spoken
but the "Half way" is skipped.
</talking-timer>
<talking-timer time="03:00" priority="fraction">
The "Half way." announcement is also the same as the "One minute,
thirty seconds to go." anouncement so the "Half way" announcement
is spoken but the "One minute, thirty seconds to go." is skipped.
</talking-timer>
<talking-timer time="03:00" priority="order" speak="1/3 30s 1/4 last20 last15 allLast10">
The "Half way." (2/4) announcement is also the same as the
"One minute, thirty seconds to go." anouncement but since `30s` is
defined before `1/4`, "One minute, thirty seconds to go." is spoken
and "Half way." is skipped.
</talking-timer>
start-message
allows you to control what is spoken when a timer starts.
NOTE: by default nothing is spoken when a timer starts
start-message
has the same result assaystart
with the added advantage that you can control what is spoken
If selfdestruct
is set, then the timer will remove itself thirty
seconds after completion or as many seconds as the timer ran for
(which ever is shorter).
<talking-timer time="03:00" selfdestruct>
Self destruct after 30 seconds
</talking-timer>
<talking-timer time="03:00" selfdestruct="true">
Self destruct after 30 seconds
</talking-timer>
<talking-timer time="03:00" selfdestruct="600">
Self destruct after 10 minutes
</talking-timer>
NOTE: If
selfdestruct
has a numeric value, then that number will set the number of seconds, after timer finishes, when the node will remove itself.
NOTE ALSO: If the value of
selfdestruct
is greater than 43200 (12 hours) 43200 will be used.
FINAL NOTE:
noclosebtn
&selfdestruct
are mutually exclusive. ifselfdestruct
is has a numeric value it will overridenoclosebtn
will override it and will force the node to be automatically removed after completion of timer.
To make it easier to just drop the <taking-timer>
code into your
project, I've set up a way to allow you to customise the some of the
defaults so you don't have to configure via attributes.
If you define talkingTimerExternalDefaults
in the global scope,
then its properties can be used to define <taking-timer>
's
default values.
NOTE: the type of the value you define must match the default value's type listed below or they will be ignored
Note also: You only need to define the properties you wish to over-ride.
var talkingTimerExternalDefaults = {
priority: 'fraction',
pre: {
10000: 200,
19999: 600,
86400: 1200,
},
preSpeakStart: 2300,
preSpeakEnd: 3300,
chimeDelay: 5000,
suffixes: {
first: ' gone.',
last: ' to go.',
half: 'Half way.',
},
intervalTime: 20,
sayDefault: '1/2 30s last20 last15 allLast10',
endText: 'Time\'s up!',
startText: 'Ready. Set. Go!',
}
See priority
attribute documentation above
pre
controls the amount of time (in milliseconds) speaking an interval should start before the actual interval occurs
-
10000
= 10 seconds (10k milliseconds) This is for spoken intervals where the time remaining is 10 seconds or less (i.e. only the number of seconds is spoken - e.g. "Eight") -
19999
= 20 seconds (20k milliseconds) This is for spoken intervals where the time remaining greater than 10 seconds and less than 20 seconds. It needs to be a bit longer to account for saying the word "seconds" after the number of seconds is spoken. (i.e. the number plus "seconds" is spoken but "to go." is omitted - e.g. "Fifteen seconds") -
86400
= 1 day This is for everything else. It accounts for the extra time taken to say "to go." or "gone" (e.g. "One minute, Thirty seconds to go.")
This provides a delay to starting the timer when "Ready. Set. Go!" is spoken before the timer starts.
If the end chime is to be played along after "Time's up!" is spoken, this provides the delay so the chime doesn't start before the browser has finished announcing "Time's up!".
If the end chime is played when the timer finishes and the timer is set to self destruct or auto reset, this provides the delay so that the chime finishes playing before the <talking-timer>
block is removed or reset.
Suffixes are what is said to denote the interval's relation to the begining or end of the timer.
-
first
(default: " gone.") defines what is spoken when an interval is relative to the start of the timer. -
last
(default: " to go.") defines what is spoken when an interval is relative to the finish of the timer. -
half
(default: "Half way.") what is spoken when the timer is exactly half way.
The time ellapsed for timer takes to check where it's at and do the stuff it needs to do (like updating the timer coundown.)
The codes for the intervals that are spoken when the <talking-timer>
doesn't specify them specifically.
What is spoken when the timer finishes
What is spoken just before the timer starts.
Styling is very personal. I've done what I think is a good design. But what I think is good and what you think is good may not necessarily be the same. So, in light of that, most of the visual style of the talking-timer web component can be styled via CSS variables.
Below are tables for the variables controlling the style of each element in the shadow dom along with the CSS attribute they represent and the defaults value I've set.
Grid setup for talking timer
Variable name | CSS attribute | default value |
---|---|---|
--talkingTimer-columns | grid-template-columns | auto 2em |
--talkingTimer-rows | grid-template-rows | 2em auto auto 2em auto auto |
Variable name | CSS attribute | default value |
---|---|---|
--h1-size | font-size | 1.5em |
--h1-padding | padding | 0.5em 2.5em 0.5em 0.5em |
--h1-align | text-align | center |
If the close button is hidden, you need to adjust the padding to ensure the heading is centred (if you keep it centred as is default)
Variable name | CSS attribute | default value |
---|---|---|
--h1-noclosebtn-padding | noclosebtn-padding | 0.5em |
Timer text is the text that changes (counts down) as the timer progresses
Variable name | CSS attribute | default value |
---|---|---|
--timertext-color | color (font colour) | #222 |
--timertext-family | family | verdana, arial, helvetica, sans-serif |
--timertext-size | font-size | 6em |
--timertext-weight | font-weight | bold |
--timertext-padding | padding | 0.1em 0.25em 0.2em |
--timertext-align | text-align | center |
Variable name | CSS attribute | default value |
---|---|---|
--finished-background | background-color | #c00 |
--finished-color | color (font colour) | #fff |
(Still working on this styling. there are big differences between Chrome and Firefox)
Variable name | CSS attribute | default value |
---|---|---|
--progress-background | background | #fff |
--progress-border-color | border-color | #ccc |
--progress-border-width | border-width | 0.05em |
--progress-color | color (font colour) | #F00 |
--progress-height | line-height | 2em |
--progress-left | left | -0.05em |
--progress-right | right | auto |
Variable name | CSS attribute | default value |
---|---|---|
--btn-color | color | inherit |
--btn-background | background-color | #fff |
--btn-size | font-size | 1.25em |
--btn-padding | padding | 0.5em 0 |
--btn-border-color | border-color | #c0e |
--btn-border-width | border-width | 0.05em |
Variable name | CSS attribute | default value |
---|---|---|
--btn-hover-color | color | #fff |
--btn-hover-background | background-color | #eee |
--btn-hover-border-color | border-color | #eee |
--btn-hover-border-width | border-width | 0.05em |
Button that triggers Play/Pause (Green with white text by default)
Variable name | CSS attribute | default value |
---|---|---|
--playpause-color | color (font colour) | #fff |
--playpause-size | font-size | 1.25em |
--playpause-weight | font-weight | bold |
--playpause-background | background | #050 |
--playpause-border-width | border-width | 0.05em |
--playpause-border-color | border-color | #040 |
Variable name | CSS attribute | default value |
---|---|---|
--playpause-hover-weight | font-weight | bold |
--playpause-hover-color | color (font colour) | #fff |
--playpause-hover-background | background-color | #030 |
--playpause-hover-border-width | border-width | #fff |
--playpause-hover-border-color | border-color | #020 |
By defaul the close button sits on the top right of the <talking-timer>
box
Variable name | CSS attribute | default value |
---|---|---|
--smallbtn-background | background-color | transparent |
--smallbtn-border-color | border-color | transparent |
--smallbtn-border-style | border-style | none |
--smallbtn-border-width | border-width | 0 |
--smallbtn-color | color (font colour) | inherit |
--smallbtn-left | left (grid-column-start) | 2 |
--smallbtn-padding | padding | 0.2em 0.25em |
--smallbtn-position | position | absolute |
--smallbtn-right | right (grid-column-end | 3 |
--smallbtn-size | font-size | 2em |
--smallbtn-weight | font-weight | normal |
Variable name | CSS attribute | default value |
---|---|---|
--smallbtn-hover-color | color (font colour) | #c00 |
--smallbtn-hover-weight | font-weight | bold |
--smallbtn-hover-background | hover-background | transparent |
--smallbtn-hover-border-width | border-width | 0 |
--smallbtn-hover-border-style | border-style | none |
--smallbtn-hover-border-color | border-color | transparent |
Position of the close button (using Grid columns) <talking-timer>
Variable name | CSS attribute | default value |
---|---|---|
--closebtn-top | top (grid-row-start) | 1 |
--closebtn-bottom | bottom (grid-row-end) | 2 |
Position of the config button (using Grid columns) <talking-timer>
Variable name | CSS attribute | default value |
---|---|---|
--configbtn-top | top (grid-row-start) | 3 |
--configbtn-bottom | bottom (grid-row-end) | 4 |