JSFiddle - React, Tailwind, and code Playground

by nathan

HTML

<ul id="instructions" class="hideable">
    <li>Press [F11] to view in fullscreen</li>
    <li class="nrta countdown">Numbers at any time will reset the timer and enter a new value</li>
    <li class="nrta countup">[Enter] or [Space] starts or stops the timer</li>
    <li class="nrta countdown">[Enter] or [Space] starts or stops the timer, or resets it if it's at zero</li>
    <li class="nrta countdown">[R] resets the timer to it's previous start value</li>
    <li class="nrta countdown">[Esc] clears (zeros) the timer</li>
    <li class="nrta countup">[R] or [Esc] resets the timer ([Esc] also clears the number of digits shown, but [R] doesn't)</li>
    <li class="nrta countup">[Tab] shows split times</li>
    <li class="nrta countdown countup">[&lt;] and [&gt;] ([,] and [.]) change the number of digits shown</li>
    <li>[+] and [-] increase and decrease the size of the timer</li>
    <li>Arrow keys move the timer around on the screen</li>
    <li style="padding-top: 2em;">Press [S] to show/hide this section</li>
</ul>
<ul id="configuration" class="hideable">
    <li>
        <input type="radio" id="countdown-selector" name="type-selector" value="countdown" checked="checked">
        <label for="countdown-selector">countdown</label>
        <input type="radio" id="countup-selector" name="type-selector" value="countup">
        <label for="countup-selector">stopwatch</label>
        <input type="radio" id="clock-selector" name="type-selector" value="clock">
        <label for="clock-selector">clock</label>
    </li>
    <li>
        <label for="text-colour-box">Text colour</label>
        <input type="text" id="text-colour-box" />
    </li>
    <li>
        <label for="background-colour-box">Background colour</label>
        <input type="text" id="background-colour-box" />
    </li>
    <li class="nrta countdown">
        <label for="flash-colour-box">Flash colour</label>
        <input type="text" id="flash-colour-box" />
    </li>
</ul>
<div id="timer">
   ...

CSS

html {
    height: 100%;
    overflow: hidden;
}
body {
    height: 100%;
    overflow: hidden;
}
#instructions,#configuration {
    width: 49%;
    float: left;
    margin: 0;
    padding: 0;
    text-indent: 0;
    list-style: none;
}
#timer {
    clear: both;
    font-size: 10em;
}
#legal-and-ads {
    position: absolute;
    bottom: 0;
}

JavaScript

var Timer = function () {
    var updatePeriod = 10,
        proc,
        systemTimeAtStart,
        oldTime,
        timerTimeAtStart,
        resettableTime,
        currentPausedTime,
        countdown = true,
        countup;
    this.countdown = function (a) {
        if (a === undefined) {
            a = 0;
        }
        countup = false;
        countdown = true;
        return this.setNewTime(a);
    };
    this.countup = function () {
        countup = true;
        countdown = false;
        return this.setNewTime(new Date(0));
    };
    this.clock = function () {
        countup = false;
        countdown = false;
        return this.start();
    };
    this.start = function () {
        var timerObj = this;
        systemTimeAtStart = new Date();
        if (timerTimeAtStart === undefined) {
            timerTimeAtStart = currentPausedTime;
        }
        oldTime = this.getCurrentTime();
        timerTimeAtStart = oldTime;
        if (!countdown || this.getCurrentTime().getTime() !== 0) {
            proc = window.setInterval(function () {
                var current = timerObj.getCurrentTime();
                if (countdown &&
                    current.getHours() === 23 &&
                    current.getMinutes() === 59 &&
                    current.getSeconds() === 59 &&
                    current.getMilliseconds() > 500) {
                    timerObj.update(0);
                    window.clearInterval(proc);
                    currentPausedTime = 0;
                    timerObj.complete();
                } else {
                    timerObj.update(timerObj.getCurrentTime());
                }
            }, updatePeriod);
            currentPausedTime = undefined;
        }
    };
    this.stop = function () {
        if (countdown || countup) {
            currentPausedTime = this.getCurrentTime();
            window.clearInterval(proc);
        }
        return this;
    };
    this.reset = function () {
        currentPausedTime...