Hi I've found a great timer here on SO for a while ago and I was wondering how to call the start and stop function, so when you call the start function the timer starts and when you call the stop function the timer stops. I have tried a lot of different solutions but I can't figure it out anyway here is the code:
<!DOCTYPE html>
<html>
<head>
<title>JS Bin</title>
<style>
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
</style>
</head>
<body>
<h2>Basic example; update every 1 ms</h2>
<p>click <code>start</code> to start a stopwatch</p>
<pre>
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</pre>
<div class="basic stopwatch"></div>
<hr>
<script>
var Stopwatch = function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock/1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</script>
</body>
</html>
If you look through the code, you can see that each button is created using the below function:
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
All this does is append a series of links to the DOM, each with a click event handler calling the relevant function (passed as the handler variable), stop, start or reset.
To call one of these directly, you can simply call the function- e.g. stop()
var Stopwatch = {
init: function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock / 1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
}
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i = 0, len = elems.length; i < len; i++) {
Stopwatch.init(elems[i]);
}
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
<div class="basic stopwatch"></div>
<button onclick="Stopwatch.stop()">STOP!</button>
Related
I need to allow the user to make 2 mistakes before they lose the game. I need to:
-Create a global variable to track the number of mistakes
-Initialize that variable during startGame
-Edit the guess function so that it updates the mistake counter when the user makes and mistake, and adds a check of that variable before calling the loseGame function
Im having trouble implementing this into the JS file. How can I do it?
JS File:
const cluePauseTime = 333; //how long to pause in between clues
const nextClueWaitTime = 1000; //how long to wait before starting playback of the clue sequence
//Global variables
var clueHoldTime = 200; //how long to hold each clue's light/sound
// var pattern = [2, 3, 1, 4, 6, 1, 2, 4, 3, 5];
var pattern = [];
var clueLength = 10;
///////////////////////////////
var progress = 0;
var gamePlaying = false;
var tonePlaying = false;
var volume = 0.5;
var guessCounter = 0;
function startGame() {
progress = 0;
pattern = []; // reset so array doesn't get longer then 10 if we restart game
for (var i = 0; i < clueLength; i++) {
pattern.push(getRandomInt(5));
}
console.log("pattern: " + pattern);
gamePlaying = true;
document.getElementById("startBtn").classList.add("hidden");
document.getElementById("stopBtn").classList.remove("hidden");
playClueSequence();
}
function stopGame() {
gamePlaying = false;
document.getElementById("startBtn").classList.remove("hidden");
document.getElementById("stopBtn").classList.add("hidden");
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max) + 1);
}
function lightButton(btn) {
document.getElementById("button" + btn).classList.add("lit");
}
function clearButton(btn) {
document.getElementById("button" + btn).classList.remove("lit");
}
function playSingleClue(btn) {
if (gamePlaying) {
lightButton(btn);
playTone(btn, clueHoldTime);
setTimeout(clearButton, clueHoldTime, btn);
}
}
function playClueSequence() {
guessCounter = 0;
let delay = nextClueWaitTime; //set delay to initial wait time
for (let i = 0; i <= progress; i++) {
// for each clue that is revealed so far
console.log("play single clue: " + pattern[i] + " in " + delay + "ms");
setTimeout(playSingleClue, delay, pattern[i]); // set a timeout to play that clue
delay += clueHoldTime;
delay += cluePauseTime;
}
}
function loseGame() {
stopGame();
alert("Game Over. You lost.");
}
function winGame() {
stopGame();
alert("Yayyyyy, you win!!");
}
function guess(btn) {
console.log("user guessed: " + btn);
if (!gamePlaying) {
return;
}
if (pattern[guessCounter] == btn) {
if (guessCounter == progress) {
if (progress == pattern.length - 1) {
winGame();
} else {
progress++;
playClueSequence();
}
} else {
guessCounter++;
}
//guessCounter++;
} else {
loseGame();
}
}
// Sound Synthesis Functions
const freqMap = {
1: 261.6,
2: 329.6,
3: 392,
4: 466.2,
5: 432.8,
6: 336.2
};
function playTone(btn, len) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
setTimeout(function() {
stopTone();
}, len);
}
function startTone(btn) {
if (!tonePlaying) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
}
}
function stopTone() {
g.gain.setTargetAtTime(0, context.currentTime + 0.05, 0.025);
tonePlaying = false;
}
//Page Initialization
// Init Sound Synthesizer
var context = new AudioContext();
var o = context.createOscillator();
var g = context.createGain();
g.connect(context.destination);
g.gain.setValueAtTime(0, context.currentTime);
o.connect(g);
o.start(0);
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hello!</title>
<!-- import the webpage's stylesheet -->
<link rel="stylesheet" href="/style.css" />
<!-- import the webpage's javascript file -->
<script src="/script.js" defer></script>
</head>
<body>
<h1>Memory Game</h1>
<p>
Welcome to the game that will test your memory!
</p>
<button id="startBtn" onclick="startGame()">
Start
</button>
<button id="stopBtn" class="hidden" onclick="stopGame()">
Stop
</button>
<div id="gameButtonArea">
<button
id="button1"
onclick="guess(1)"
onmousedown="startTone(1)"
onmouseup="stopTone()"
></button>
<button
id="button2"
onclick="guess(2)"
onmousedown="startTone(2)"
onmouseup="stopTone()"
></button>
<button
id="button3"
onclick="guess(3)"
onmousedown="startTone(3)"
onmouseup="stopTone()"
></button>
<button
id="button4"
onclick="guess(4)"
onmousedown="startTone(4)"
onmouseup="stopTone()"
></button>
<button
id="button5"
onclick="guess(5)"
onmousedown="startTone(5)"
onmouseup="stopTone()"
></button>
<button
id="button6"
onclick="guess(6)"
onmousedown="startTone(6)"
onmouseup="stopTone()"
></button>
</div>
</body>
</html>
CSS:
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
background-color: slategrey;
color: white;
}
h1 {
font-family: verdana, arial, sans-serif;
color: yellow;
}
button {
padding: 15px;
border-radius: 15px;
}
#gameButtonArea > button {
width: 200px;
height: 200px;
margin: 2px;
}
.hidden {
display: none;
}
#button1 {
background: lightgreen;
}
#button1:active,
#button1.lit {
background: green;
}
#button2 {
background: lightblue;
}
#button2:active,
#button2.lit {
background: blue;
}
#button3 {
background: pink;
}
#button3:active,
#button3.lit {
background: red;
}
#button4 {
background: lightyellow;
}
#button4:active,
#button4.lit {
background: yellow;
}
#button5 {
background: lightgray;
}
#button5:active,
#button5.lit {
background: black;
}
#button6 {
background: white;
}
#button6:active,
#button6.lit {
background: purple;
}
Add a variable let lostCount = 0;.
Change guess else block to:
else {
if (lostCount < 2) lostCount++;
else loseGame();
}
const cluePauseTime = 333; //how long to pause in between clues
const nextClueWaitTime = 1000; //how long to wait before starting playback of the clue sequence
//Global variables
var clueHoldTime = 200; //how long to hold each clue's light/sound
// var pattern = [2, 3, 1, 4, 6, 1, 2, 4, 3, 5];
var pattern = [];
var clueLength = 10;
///////////////////////////////
var progress = 0;
var gamePlaying = false;
var tonePlaying = false;
var volume = 0.5;
var guessCounter = 0;
let lostCount = 0;
function startGame() {
progress = 0;
pattern = []; // reset so array doesn't get longer then 10 if we restart game
for (var i = 0; i < clueLength; i++) {
pattern.push(getRandomInt(5));
}
console.log("pattern: " + pattern);
gamePlaying = true;
document.getElementById("startBtn").classList.add("hidden");
document.getElementById("stopBtn").classList.remove("hidden");
playClueSequence();
}
function stopGame() {
gamePlaying = false;
document.getElementById("startBtn").classList.remove("hidden");
document.getElementById("stopBtn").classList.add("hidden");
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max) + 1);
}
function lightButton(btn) {
document.getElementById("button" + btn).classList.add("lit");
}
function clearButton(btn) {
document.getElementById("button" + btn).classList.remove("lit");
}
function playSingleClue(btn) {
if (gamePlaying) {
lightButton(btn);
playTone(btn, clueHoldTime);
setTimeout(clearButton, clueHoldTime, btn);
}
}
function playClueSequence() {
guessCounter = 0;
let delay = nextClueWaitTime; //set delay to initial wait time
for (let i = 0; i <= progress; i++) {
// for each clue that is revealed so far
console.log("play single clue: " + pattern[i] + " in " + delay + "ms");
setTimeout(playSingleClue, delay, pattern[i]); // set a timeout to play that clue
delay += clueHoldTime;
delay += cluePauseTime;
}
}
function loseGame() {
stopGame();
alert("Game Over. You lost.");
}
function winGame() {
stopGame();
alert("Yayyyyy, you win!!");
}
function guess(btn) {
console.log("user guessed: " + btn);
if (!gamePlaying) {
return;
}
if (pattern[guessCounter] == btn) {
if (guessCounter == progress) {
if (progress == pattern.length - 1) {
winGame();
} else {
progress++;
playClueSequence();
}
} else {
guessCounter++;
}
//guessCounter++;
} else {
if (lostCount < 2) lostCount++;
else loseGame();
}
}
// Sound Synthesis Functions
const freqMap = {
1: 261.6,
2: 329.6,
3: 392,
4: 466.2,
5: 432.8,
6: 336.2,
};
function playTone(btn, len) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
setTimeout(function () {
stopTone();
}, len);
}
function startTone(btn) {
if (!tonePlaying) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
}
}
function stopTone() {
g.gain.setTargetAtTime(0, context.currentTime + 0.05, 0.025);
tonePlaying = false;
}
//Page Initialization
// Init Sound Synthesizer
var context = new AudioContext();
var o = context.createOscillator();
var g = context.createGain();
g.connect(context.destination);
g.gain.setValueAtTime(0, context.currentTime);
o.connect(g);
o.start(0);
I'm using a script on Codepen that mimics a type effect. https://codepen.io/gschier/pen/jkivt
In my page, I have an input that locates user location using GeoIP. This Codepen prevents the GeoIP from loading due to rotation fundtion that prevents the location from being inserted. The GeoIP is loaded using 'window.onload'.
Any suggestions?
var TxtRotate = function(el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 2000;
this.txt = '';
this.tick();
this.isDeleting = false;
};
TxtRotate.prototype.tick = function() {
var i = this.loopNum % this.toRotate.length;
var fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = '<span class="wrap">'+this.txt+'</span>';
var that = this;
var delta = 300 - Math.random() * 100;
if (this.isDeleting) { delta /= 2; }
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === '') {
this.isDeleting = false;
this.loopNum++;
delta = 500;
}
setTimeout(function() {
that.tick();
}, delta);
};
window.onload = function() {
var elements = document.getElementsByClassName('txt-rotate');
for (var i=0; i<elements.length; i++) {
var toRotate = elements[i].getAttribute('data-rotate');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtRotate(elements[i], JSON.parse(toRotate), period);
}
}
// INJECT CSS
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = ".txt-rotate > .wrap { border-right: 0.08em solid #666 }";
document.body.appendChild(css);
};
html,body {
font-family: 'Raleway', sans-serif;
padding: 1em 2em;
font-size: 18px;
background: #222;
color: #aaa
}
h1,h2 {
font-weight: 200;
margin: 0.4em 0;
}
h1 { font-size: 3.5em; }
h2 {
color: #888;
font-size: 2em;
}
<link href="https://fonts.googleapis.com/css?family=Raleway:200,100,400" rel="stylesheet" type="text/css" />
<h1>This pen is
<span
class="txt-rotate"
data-period="2000"
data-rotate='[ "nerdy.", "simple.", "pure JS.", "pretty.", "fun!" ]'></span>
</h1>
<h2>A single <span> is all you need.</h2>
By the way, this is the following conflicting script as follows:
window.onload = function() {
$.getJSON( "http://jsonip.com/?callback=?", function(data){
$.ajax({
url:"https://cors-anywhere.herokuapp.com/http://www.geoplugin.net/json.gp?ip="+data.ip,
method:"POST",
dataType:"JSON",
success:function(data)
{
if(data)
{
document.getElementById("presidence").value = data['geoplugin_city']+','+data['geoplugin_region']+','+data['geoplugin_countryName']+'.';
}
else
{
alert('hy');
}
}
})
} );
};
<input id="presidence" type="text" readonly size="30" />
When you assign one function to window.onload, if somewhere else in the script, some other function is assigned to window.onload (before the event has triggered), the reference to the first function will be lost, and only the last function assigned to onload will run. This is why assigning to onload generally isn't a great idea - it's limited to holding a reference to only one function. Use addEventListener instead, which can handle a (mostly) unlimited number of attached functions. For readability, define the typewriter load function, and define your user location load function, then use addEventListener for both:
function typewriterLoad() {
var elements = document.getElementsByClassName('txt-rotate');
for (var i = 0; i < elements.length; i++) {
var toRotate = elements[i].getAttribute('data-rotate');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtRotate(elements[i], JSON.parse(toRotate), period);
}
}
// INJECT CSS
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = ".txt-rotate > .wrap { border-right: 0.08em solid #666 }";
document.body.appendChild(css);
}
function userlocationLoad() {
$.getJSON("http://jsonip.com/?callback=?", function(data) {
$.ajax({
url: "https://cors-anywhere.herokuapp.com/http://www.geoplugin.net/json.gp?ip=" + data.ip,
method: "POST",
dataType: "JSON",
success: function(data) {
if (data) {
document.getElementById("presidence").value = data['geoplugin_city'] + ',' + data['geoplugin_region'] + ',' + data['geoplugin_countryName'] + '.';
} else {
alert('hy');
}
}
})
});
}
document.addEventListener('DOMContentLoaded', typewriterLoad);
document.addEventListener('DOMContentLoaded', userlocationLoad);
An alternative is to make only a single listener, and pass it a function that calls both:
document.addEventListener('DOMContentLoaded', () => {
typewriterLoad();
userlocationLoad();
});
I'm trying to make a count-down that counts down from 200 to 0 in steps of 10.
This timer can be stopped and should then be reset to 200, however, I need also the value of the moment is stopped. The countdown fills the div #log with innerHTML. Whenever I "stop" the timer, I take the value of #log and place it in #price and I hide #log. The problem here is that the timer continues in the background, while I want it to reset so it can be started again by clicking on start. However, it just continues counting down and only after it's done, I can start it again.
In the example, it doesn't take so long for it to reach 0, but in the end, it'll take 15-20 seconds to reach 0, which'll be too long to wait for.
So in short: Countdown 200-0, but on click of Start-button or spacebar, it should stop the function running at the moment, so it can be started again.
See this PEN
If you have any suggestions on how to approach it completely different, you're very welcome to share!
HTML
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
JS
var log = document.getElementById("log");
var btn = document.getElementById("btn");
var price = document.getElementById("price");
var counting = false;
var btnClassName = btn.getAttribute("class");
function start(count) {
if (!counting) {
counting = true;
log.innerHTML = count;
var timer = setInterval(function() {
if (count >= 0) {
log.innerHTML = count;
count -= 10;
} else {
clearInterval(timer);
count = arguments[0];
counting = false;
btn.className = "normal";
}
}, 150);
};
};
btn.onclick = function() {
if (btnClassName == "normal") {
start(200);
price.style.display = 'none';
log.style.display = 'block';
btn.className = "counting";
log.innerHTML = "";
} else {
}
};
document.body.onkeyup = function(e){
if(e.keyCode == 32){
price.innerHTML = log.innerHTML;
price.style.display = 'block';
log.style.display = 'none';
}
}
I "re-code" your code because there are several issues there.
Just read the code and tell me if that's you are looking for or if you have any questions..
var log = document.getElementById("log");
var btn = document.getElementById("btn");
var price = document.getElementById("price");
var counting = false;
var timer;
var c = 0;
function start(count) {
btn.blur();
if (!counting) {
c = count;
counting = true;
log.innerHTML = count;
timer = setInterval(tick, 1500);
tick();
};
};
function tick() {
if (c >= 0) {
log.innerHTML = c;
c -= 10;
}
else {
clearInterval(timer);
c = arguments[0];
counting = false;
btn.className = "normal";
}
}
btn.onclick = function() {
resetTimer();
var btnClassName = btn.getAttribute("class");
if (btnClassName == "normal") {
price.style.display = 'none';
log.style.display = 'block';
btn.className = "counting";
log.innerHTML = "";
start(200);
} else {
pause();
}
};
document.body.onkeyup = function(e) {
if(e.keyCode == 32) {
e.preventDefault();
pause();
}
}
function pause() {
resetTimer();
price.innerHTML = log.innerHTML;
price.style.display = 'block';
log.style.display = 'none';
btn.className = 'normal';
counting = false;
}
function resetTimer() {
clearInterval(timer);
}
body { font: 100% "Helvetica Neue", sans-serif; text-align: center; }
/*#outer {
width: 400px;
height: 400px;
border-radius: 100%;
background: #ced899;
margin: auto;
}
#inner {
width: 350px;
height: 350px;
border-radius: 100%;
background: #398dba;
margin: auto;
}*/
#log, #price {
font-size: 500%;
font-weight: bold;
}
<div id="outer">
<div id="inner">
<div id="arrow">
</div>
</div>
</div>
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
Though you have already got your answer, you can try something like this:
Also I have taken liberty to reformat your code, and for demonstration purpose, have kept delay for interval as 1000
JSFiddle
function Counter(obj) {
var _initialVaue = obj.initialValue || 0;
var _interval = null;
var status = "Stopped";
var start = function() {
this.status = "Started";
if (!_interval) {
_interval = setInterval(obj.callback, obj.delay);
}
}
var reset = function() {
stop();
start();
}
var stop = function() {
if (_interval) {
this.status = "Stopped";
window.clearInterval(_interval);
_interval = null;
}
}
return {
start: start,
reset: reset,
stop: stop,
status: status
}
}
function init() {
var counterOption = {}
var count = 200;
counterOption.callback = function() {
if (count >= 0) {
printLog(count);
count -= 10;
} else {
counter.stop();
}
};
counterOption.delay = 1000;
counterOption.initialValue = 200
var counter = new Counter(counterOption);
function registerEvents() {
document.getElementById("btn").onclick = function() {
if (counter.status === "Stopped") {
count = counterOption.initialValue;
counter.start();
printLog("")
toggleDivs(counter.status)
}
};
document.onkeyup = function(e) {
if (e.keyCode === 32) {
printLog(counterOption.initialValue);
counter.stop();
toggleDivs(counter.status)
printPrice(count);
}
}
}
function printLog(str) {
document.getElementById("log").innerHTML = str;
}
function printPrice(str) {
document.getElementById("price").innerHTML = str;
}
function toggleDivs(status) {
document.getElementById("log").className = "";
document.getElementById("price").className = "";
var hideID = (status === "Started") ? "price" : "log";
document.getElementById(hideID).className = "hide";
}
registerEvents();
}
init();
body {
font: 100% "Helvetica Neue", sans-serif;
text-align: center;
}
.hide{
display: none;
}
#log,
#price {
font-size: 500%;
font-weight: bold;
}
<div id="outer">
<div id="inner">
<div id="arrow">
</div>
</div>
</div>
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
Hope it helps!
I've been wanting to create a timer for my website that countsup, and displays alerts at certain intervals. So like, it starts from 0 and counts upwards when the user pushes a button. From there, it will display a a custom alert at certain intervals... (4 minutes for example)... 45 seconds before that interval, I need the number to change to yellow and 10 seconds before that interval, I need it to change to red... then back to the normal color when it passes that interval.
I've got a basic timer code but I am not sure how to do the rest. I am quite new to this. Any help? Thanks so much in advance.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
You could do something like this
var pad = function (n) {
return ('' + n).length < 4 ? pad('0' + n) : n;
};
jQuery.fn.timer = function () {
var t = this,
i = 0;
setInterval(function () {
t.text(pad(i++));
checkTime(i, t);
}, 1000);
};
$('#timer').timer();
checkTime = function (time, t) {
switch (time -1) {
case 10:
t.css('color','red');
break;
case 20:
t.css('color','yellow');
break;
case 30:
t.css('color','green');
break;
case 40:
t.css('color','black');
break;
default:
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
Something like this should work:
Here is a jsFiddle DEMO
jQuery
$.fn.timer = function (complete, warning, danger) {
var $this = $(this);
var total = 0;
$this.text(total);
var intervalComplete = parseInt(complete, 10);
var intervalWarning = parseInt(intervalComplete - warning, 10);
var intervalDanger = parseInt(intervalComplete - danger, 10);
var clock = setInterval(function () {
total += 1;
$this.text(total);
if (intervalWarning === total) {
// set to YELLOW:
$this.addClass('yellow');
}
if (intervalDanger === total) {
// set to RED:
$this.removeClass('yellow').addClass('red');
}
if (intervalComplete === total) {
// reset:
clearInterval(clock);
$this.removeClass();
alert('COMPLETE!');
}
}, 1000);
};
$(function () {
$('#timer').timer(240, 45, 10);
});
CSS
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
An additional point:
You should place some error validation within the function to ensure your counter completion time is greater than both the warning and danger time intervals.
You can try something like this:
JSFiddle
This is a pure JS timer code. Also for popup you can use something like Bootbox.js.
Code
function timer() {
var time = {
sec: 00,
min: 00,
hr: 00
};
var finalLimit = null,
warnLimit = null,
errorLimit = null;
var max = 59;
var interval = null;
function init(_hr, _min, _sec) {
time["hr"] = _hr ? _hr : 0;
time["min"] = _min ? _min : 0;
time["sec"] = _sec ? _sec : 0;
printAll();
}
function setLimit(fLimit, wLimit, eLimit) {
finalLimit = fLimit;
warnLimit = wLimit;
errorLimit = eLimit;
}
function printAll() {
print("sec");
print("min");
print("hr");
}
function update(str) {
time[str] ++;
time[str] = time[str] % 60;
if (time[str] == 0) {
str == "sec" ? update("min") : update("hr");
}
print(str);
}
function print(str) {
var _time = time[str].toString().length == 1 ? "0" + time[str] : time[str];
document.getElementById("lbl" + str).innerHTML = _time;
}
function validateTimer() {
var c = "";
var secs = time.sec + (time.min * 60) + (time.hr * 60 * 60);
console.log(secs, finalLimit)
if (secs >= finalLimit) {
stopTimer();
} else if (secs >= errorLimit) {
c = "error";
} else if (secs >= warnLimit) {
c = "warn";
} else {
c = "";
}
var element = document.getElementsByTagName("span");
console.log(element, c)
document.getElementById("lblsec").className = c;
}
function startTimer() {
init();
if (interval) stopTimer();
interval = setInterval(function() {
update("sec");
validateTimer();
}, 1000);
}
function stopTimer() {
window.clearInterval(interval);
}
function resetInterval() {
stopTimer();
time["sec"] = time["min"] = time["hr"] = 0;
printAll();
startTimer();
}
return {
'start': startTimer,
'stop': stopTimer,
'reset': resetInterval,
'init': init,
'setLimit': setLimit
}
};
var time = new timer();
function initTimer() {
time.init(0, 0, 0);
}
function startTimer() {
time.start();
time.setLimit(10, 5, 8);
}
function endTimer() {
time.stop();
}
function resetTimer() {
time.reset();
}
span {
border: 1px solid gray;
padding: 5px;
border-radius: 4px;
background: #fff;
}
.timer {
padding: 2px;
margin: 10px;
}
.main {
background: #eee;
padding: 5px;
width: 200px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #2980b9;
text-decoration: none;
transition: 0.4s;
}
.btn:hover {
background: #3cb0fd;
text-decoration: none;
transition: 0.4s;
}
.warn {
background: yellow;
}
.error {
background: red;
}
<div class="main">
<div class="timer"> <span id="lblhr">00</span>
: <span id="lblmin">00</span>
: <span id="lblsec">00</span>
</div>
<button class="btn" onclick="startTimer()">Start</button>
<button class="btn" onclick="endTimer()">Stop</button>
<button class="btn" onclick="resetTimer()">Reset</button>
</div>
Hope it helps!
if(stopwatch >= track[song].duration)
track[song].duration finds the duration of a soundcloud track.
I am looking to create a stopwatch function that starts counting milliseconds when you click on the swap ID stopwatch so that when the function has been "clicked" for a certain amount of time the if function will do something. In my case replace an image. And also that the function will reset it itself when clicked again.
so like stopwatch = current time - clicked time How can I set up the clicked time
current time = new Date().getTime(); ? And is this in milliseconds?
$('#swap').click(function()...
You'll see the demo code is just a start/stop/reset millisecond counter. If you want to do fanciful formatting on the time, that's completely up to you. This should be more than enough to get you started.
This was a fun little project to work on. Here's how I'd approach it
var Stopwatch = function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock / 1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i = 0, len = elems.length; i < len; i++) {
new Stopwatch(elems[i]);
}
// programmatic examples
var a = document.getElementById("a-timer");
aTimer = new Stopwatch(a);
aTimer.start();
var b = document.getElementById("b-timer");
bTimer = new Stopwatch(b, {
delay: 100
});
bTimer.start();
var c = document.getElementById("c-timer");
cTimer = new Stopwatch(c, {
delay: 456
});
cTimer.start();
var d = document.getElementById("d-timer");
dTimer = new Stopwatch(d, {
delay: 1000
});
dTimer.start();
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
<h2>Basic example; update every 1 ms</h2>
<p>click <code>start</code> to start a stopwatch</p>
<pre>
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</pre>
<div class="basic stopwatch"></div>
<div class="basic stopwatch"></div>
<hr>
<h2>Programmatic example</h2>
<p><strong>Note:</strong> despite the varying <code>delay</code> settings, each stopwatch displays the correct time (in seconds)</p>
<pre>
var a = document.getElementById("a-timer");
aTimer = new Stopwatch(a);
aTimer.start();
</pre>
<div class="stopwatch" id="a-timer"></div>1 ms<br>
<pre>
var b = document.getElementById("b-timer");
bTimer = new Stopwatch(b, {delay: 100});
bTimer.start();
</pre>
<div class="stopwatch" id="b-timer"></div>100 ms<br>
<pre>
var c = document.getElementById("c-timer");
cTimer = new Stopwatch(c, {delay: 456});
cTimer.start();
</pre>
<div class="stopwatch" id="c-timer"></div>456 ms<br>
<pre>
var d = document.getElementById("d-timer");
dTimer = new Stopwatch(d, {delay: 1000});
dTimer.start();
</pre>
<div class="stopwatch" id="d-timer"></div>1000 ms<br>
Get some basic HTML wrappers for it
<!-- create 3 stopwatches -->
<div class="stopwatch"></div>
<div class="stopwatch"></div>
<div class="stopwatch"></div>
Usage is dead simple from there
var elems = document.getElementsByClassName("stopwatch");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
As a bonus, you get a programmable API for the timers as well. Here's a usage example
var elem = document.getElementById("my-stopwatch");
var timer = new Stopwatch(elem, {delay: 10});
// start the timer
timer.start();
// stop the timer
timer.stop();
// reset the timer
timer.reset();
jQuery plugin
As for the jQuery portion, once you have nice code composition as above, writing a jQuery plugin is easy mode
(function($) {
var Stopwatch = function(elem, options) {
// code from above...
};
$.fn.stopwatch = function(options) {
return this.each(function(idx, elem) {
new Stopwatch(elem, options);
});
};
})(jQuery);
jQuery plugin usage:
// all elements with class .stopwatch; default delay (1 ms)
$(".stopwatch").stopwatch();
// a specific element with id #my-stopwatch; custom delay (10 ms)
$("#my-stopwatch").stopwatch({delay: 10});
jsbin.com demo
Two native solutions
performance.now --> Call to ... took 6.414999981643632 milliseconds.
console.time --> Call to ... took 5.815 milliseconds
The difference between both is precision.
For usage and explanation read on.
Performance.now (For microsecond precision use)
var t0 = performance.now();
doSomething();
var t1 = performance.now();
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");
function doSomething(){
for(i=0;i<1000000;i++){var x = i*i;}
}
performance.now
Unlike other timing data available to JavaScript (for example
Date.now), the timestamps returned by Performance.now() are not
limited to one-millisecond resolution. Instead, they represent times
as floating-point numbers with up to microsecond precision.
Also unlike Date.now(), the values returned by Performance.now()
always increase at a constant rate, independent of the system clock
(which might be adjusted manually or skewed by software like NTP).
Otherwise, performance.timing.navigationStart + performance.now() will
be approximately equal to Date.now().
console.time
Example: (timeEnd wrapped in setTimeout for simulation)
console.time('Search page');
doSomething();
console.timeEnd('Search page');
function doSomething(){
for(i=0;i<1000000;i++){var x = i*i;}
}
You can change the Timer-Name for different operations.
A simple and easy clock for you and don't forget me ;)
var x;
var startstop = 0;
function startStop() { /* Toggle StartStop */
startstop = startstop + 1;
if (startstop === 1) {
start();
document.getElementById("start").innerHTML = "Stop";
} else if (startstop === 2) {
document.getElementById("start").innerHTML = "Start";
startstop = 0;
stop();
}
}
function start() {
x = setInterval(timer, 10);
} /* Start */
function stop() {
clearInterval(x);
} /* Stop */
var milisec = 0;
var sec = 0; /* holds incrementing value */
var min = 0;
var hour = 0;
/* Contains and outputs returned value of function checkTime */
var miliSecOut = 0;
var secOut = 0;
var minOut = 0;
var hourOut = 0;
/* Output variable End */
function timer() {
/* Main Timer */
miliSecOut = checkTime(milisec);
secOut = checkTime(sec);
minOut = checkTime(min);
hourOut = checkTime(hour);
milisec = ++milisec;
if (milisec === 100) {
milisec = 0;
sec = ++sec;
}
if (sec == 60) {
min = ++min;
sec = 0;
}
if (min == 60) {
min = 0;
hour = ++hour;
}
document.getElementById("milisec").innerHTML = miliSecOut;
document.getElementById("sec").innerHTML = secOut;
document.getElementById("min").innerHTML = minOut;
document.getElementById("hour").innerHTML = hourOut;
}
/* Adds 0 when value is <10 */
function checkTime(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function reset() {
/*Reset*/
milisec = 0;
sec = 0;
min = 0
hour = 0;
document.getElementById("milisec").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("hour").innerHTML = "00";
}
<h1>
<span id="hour">00</span> :
<span id="min">00</span> :
<span id="sec">00</span> :
<span id="milisec">00</span>
</h1>
<button onclick="startStop()" id="start">Start</button>
<button onclick="reset()">Reset</button>
This is my simple take on this question, I hope it helps someone out oneday, somewhere...
let output = document.getElementById('stopwatch');
let ms = 0;
let sec = 0;
let min = 0;
function timer() {
ms++;
if(ms >= 100){
sec++
ms = 0
}
if(sec === 60){
min++
sec = 0
}
if(min === 60){
ms, sec, min = 0;
}
//Doing some string interpolation
let milli = ms < 10 ? `0`+ ms : ms;
let seconds = sec < 10 ? `0`+ sec : sec;
let minute = min < 10 ? `0` + min : min;
let timer= `${minute}:${seconds}:${milli}`;
output.innerHTML =timer;
};
//Start timer
function start(){
time = setInterval(timer,10);
}
//stop timer
function stop(){
clearInterval(time)
}
//reset timer
function reset(){
ms = 0;
sec = 0;
min = 0;
output.innerHTML = `00:00:00`
}
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const resetBtn = document.getElementById('resetBtn');
startBtn.addEventListener('click',start,false);
stopBtn.addEventListener('click',stop,false);
resetBtn.addEventListener('click',reset,false);
<p class="stopwatch" id="stopwatch">
<!-- stopwatch goes here -->
</p>
<button class="btn-start" id="startBtn">Start</button>
<button class="btn-stop" id="stopBtn">Stop</button>
<button class="btn-reset" id="resetBtn">Reset</button>
Solution by Mosh Hamedani
Creating a StopWatch function constructor.
Define 4 local variables
startTime
endTime
isRunning
duration set to 0
Next create 3 methods
start
stop
reset
start method
check if isRunning is true if so throw an error that start cannot be called twice.
set isRunning to true
assign the current Date object to startTime.
stop method
check if isRunning is false if so throw an error that stop cannot be called twice.
set isRunning to false
assign the current Date object to endTime.
calculate the seconds by endTime and startTime Date object
increment duration with seconds
reset method:
reset all the local variables.
Read-only property
if you want to access the duration local variable you need to define a property using Object.defineProperty.
It's useful when you want to create a read-only property.
Object.defineProperty takes 3 parameters
the object which to define a property (in this case the current object (this))
the name of the property
the value of the key property.
We want to create a Read-only property so we pass an object as a value.
The object contain a get method that return the duration local variable.
in this way we cannot change the property only get it.
The trick is to use Date() object to calculate the time.
Reference the code below
function StopWatch() {
let startTime,
endTime,
isRunning,
duration = 0;
this.start = function () {
if (isRunning) throw new Error("StopWatch has already been started.");
isRunning = true;
startTime = new Date();
};
this.stop = function () {
if (!isRunning) throw new Error("StopWatch has already been stop.");
isRunning = false;
endTime = new Date();
const seconds = (endTime.getTime() - startTime.getTime()) / 1000;
duration += seconds;
};
this.reset = function () {
duration = 0;
startTime = null;
endTime = null;
isRunning = false;
};
Object.defineProperty(this, "duration", {
get: function () {
return duration;
},
});
}
const sw = new StopWatch();
function StopWatch() {
let startTime, endTime, running, duration = 0
this.start = () => {
if (running) console.log('its already running')
else {
running = true
startTime = Date.now()
}
}
this.stop = () => {
if (!running) console.log('its not running!')
else {
running = false
endTime = Date.now()
const seconds = (endTime - startTime) / 1000
duration += seconds
}
}
this.restart = () => {
startTime = endTime = null
running = false
duration = 0
}
Object.defineProperty(this, 'duration', {
get: () => duration.toFixed(2)
})
}
const sw = new StopWatch()
sw.start()
sw.stop()
sw.duration
well after a few modification of the code provided by mace,i ended up building a stopwatch.
https://codepen.io/truestbyheart/pen/EGELmv
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Stopwatch</title>
<style>
#center {
margin: 30% 30%;
font-family: tahoma;
}
.stopwatch {
border:1px solid #000;
background-color: #eee;
text-align: center;
width:656px;
height: 230px;
overflow: hidden;
}
.stopwatch span{
display: block;
font-size: 100px;
}
.stopwatch p{
display: inline-block;
font-size: 40px;
}
.stopwatch a{
font-size:45px;
}
a:link,
a:visited{
color :#000;
text-decoration: none;
padding: 12px 14px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="center">
<div class="timer stopwatch"></div>
</div>
<script>
const Stopwatch = function(elem, options) {
let timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval,
hrs = 0,
min = 0;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
if (action !== "reset") {
let a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
} else if (action === "reset") {
let a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
clean();
event.preventDefault();
});
return a;
}
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function clean() {
min = 0;
hrs = 0;
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
if (Math.floor(clock / 1000) === 60) {
min++;
reset();
if (min === 60) {
min = 0;
hrs++;
}
}
timer.innerHTML =
hrs + "<p>hrs</p>" + min + "<p>min</p>" + Math.floor(clock / 1000)+ "<p>sec</p>";
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
};
// Initiating the Stopwatch
var elems = document.getElementsByClassName("timer");
for (var i = 0, len = elems.length; i < len; i++) {
new Stopwatch(elems[i]);
}
</script>
</body>
</html>