var params = parseQueryParams(); // Set window title if (params.name) document.title = params.name + " - Popup Timer"; var hours, minutes, seconds; var secondsElem = document.getElementById("seconds"); var minutesElem = document.getElementById("minutes"); var hoursElem = document.getElementById("hours"); var playBtn = document.getElementById("play"); var progressBar = document.getElementById("progress-fg"); var timeout; var timesUpStr = "[ TIME'S UP! ] "; var lastPaused = -1; // Init audio var oscillator, audioContext; if (params.beep === "true") { try { audioContext = new (window.AudioContext || window.webkitAudioContext); } catch(e) {} } // Autostart if (params.autostart === "true") { switch (params.type) { case "timer": initTimer(); startTimer(1000); break; case "stopwatch": initStopwatch(); startStopwatch(1000); break; default: location.href = "/"; } } // Reset timer/stopwatch document.getElementById("restart").onclick = function() { if (timeout) clearTimeout(timeout); var paused = playBtn.classList.contains("fa-play"); switch (params.type) { case "timer": // Reset progress bar // TODO progressBar.animationName = ""; progressBar.animationName = "progress"; initTimer(); if (!paused) startTimer(1000); break; case "stopwatch": // Reset displayed time secondsElem.innerText = "00s"; secondsElem.classList.remove("highlighted"); minutesElem.innerText = "00m"; minutesElem.classList.remove("highlighted"); hoursElem.innerText = "00h"; hoursElem.classList.remove("highlighted"); initStopwatch(); if (!paused) startStopwatch(1000); break; } } // Pause / Resume playBtn.onclick = function() { if (!timeout) return; // Pause if (playBtn.classList.contains("fa-pause")) { lastPaused = Date.now(); if (params.type === "timer") progressBar.style.animationPlayState = "paused"; clearTimeout(timeout); // Change icon playBtn.classList.remove("fa-pause"); playBtn.classList.add("fa-play"); // Resume } else { var startOffset = lastPaused % 1000; switch (params.type) { case "timer": if (hours === 0 && minutes == 0 && seconds === 0) return; progressBar.style.animationPlayState = "running"; startTimer(startOffset); break; case "stopwatch": startStopwatch(startOffset); break; } // Change icon playBtn.classList.remove("fa-play"); playBtn.classList.add("fa-pause"); } } function initTimer() { hours = parseInt(params.h); minutes = parseInt(params.m); seconds = parseInt(params.s); if (hours === 0 && minutes === 0 && seconds === 0) return; // Only highlight relevant parts if (hours > 0) { hoursElem.classList.add("highlighted"); minutesElem.classList.add("highlighted"); secondsElem.classList.add("highlighted"); } else if (minutes > 0) { minutesElem.classList.add("highlighted"); secondsElem.classList.add("highlighted"); } else { secondsElem.classList.add("highlighted"); } // Print initial time hoursElem.innerText = pad(hours) + "h"; minutesElem.innerText = pad(minutes) + "m"; secondsElem.innerText = pad(seconds) + "s"; // Animate progress bar var totalSeconds = (hours * 60 * 60) + (minutes * 60) + seconds; progressBar.style.animationDuration = totalSeconds + "s"; progressBar.style.animationName = "progress"; } function startTimer(startOffset) { playBtn.classList.remove("fa-play"); playBtn.classList.add("fa-pause"); // Wait the starting offset timeout = setTimeout(updateTimer, startOffset); document.getElementById("progress-fg").style.animationPlayState = "running"; } function updateTimer() { seconds--; if (seconds === 0 && minutes === 0 && hours === 0) secondsElem.classList.remove("highlighted"); if (seconds <= -1) { seconds = 59; minutes--; if (minutes === 0 && hours === 0) minutesElem.classList.remove("highlighted"); if (minutes <= -1) { minutes = 59; hours--; if (hours === 0) hoursElem.classList.remove("highlighted"); hoursElem.innerText = pad(hours) + "h"; } minutesElem.innerText = pad(minutes) + "m"; } secondsElem.innerText = pad(seconds) + "s"; if (hours === 0 && minutes === 0 && seconds == 0) timeUp(); else timeout = setTimeout(updateTimer, 1000); } // Makes the numbers blink red etc. function timeUp() { var timeUpInterval = setInterval(function() { // Blink red [].slice.call(document.querySelectorAll("main > span")).forEach(function(elem) { elem.classList.toggle("red"); }); //document.querySelector // Blink title if (document.title.indexOf(timesUpStr) === -1) document.title = timesUpStr + document.title; else document.title = document.title.substr(timesUpStr.length); // Play beep if (params.beep === "true" && audioContext) { try { oscillator = audioContext.createOscillator(); oscillator.type = "sine"; oscillator.frequency.value = 1000; oscillator.connect(audioContext.destination); oscillator.start(); oscillator.stop(audioContext.currentTime + 0.25); } catch(e) {} } }, 500); // Stop when user clicks document.onclick = function() { if (oscillator) oscillator.stop(); // Reset color [].slice.call(document.querySelectorAll("main > span")).forEach(function(elem) { elem.classList.remove("red"); }); // Remove "TIME UP" from title if (document.title.indexOf(timesUpStr) !== -1) document.title = document.title.substr(timesUpStr.length); // Clean up clearInterval(timeUpInterval); document.onclick = null; } } function initStopwatch() { hours = 0; minutes = 0; seconds = 0; } function startStopwatch(startOffset) { playBtn.classList.remove("fa-play"); playBtn.classList.add("fa-pause"); timeout = setTimeout(updateStopwatch, startOffset); } function updateStopwatch() { // Update seconds seconds++; if (hours === 0 && minutes === 0 && seconds === 1) secondsElem.classList.add("highlighted"); if (seconds >= 60) { seconds = 0; // Update minutes minutes++; if (hours === 0 && minutes === 1) minutesElem.classList.add("highlighted"); if (minutes >= 60) { minutes = 0; // Update hours hours++; if (hours === 1) hoursElem.classList.add("highlighted"); hoursElem.innerText = pad(hours) + "h"; } // Minutes minutesElem.innerText = pad(minutes) + "m"; } // Seconds secondsElem.innerText = pad(seconds) + "s"; timeout = setTimeout(updateStopwatch, 1000); } function parseQueryParams() { if (location.search === "" || location.search.indexOf("?") !== 0) return {}; var result = {}; location.search.substr(1).split("&").forEach(function(str) { var key = str.split("=")[0]; var value; if (str.split("=").length > 1) value = str.split("=")[1]; else value = null; result[key] = value; }); return result; } // Adds one leading zero if necessary function pad(num) { return ("00" + num).substr(-2); }