Call the lap function in timer - javascript

I've been bothering on this problem for a while now, I have a timer that has 4 buttons start, stop, reset and lap, when I call Stopwatch.start();, Stopwatch.stop(); or Stopwatch.reset(); it works just fine but when I'm trying to call Stopwatch.lap(); it does not work !
I had the answer before but now I have a new computer and things like that and I can't call the function. The console says "Uncaught TypeError: Stopwatch.lap is not a function" and I can't find the problem.
Here is my code:
var Stopwatch = {
init: function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
lapButton = createButton("lap", lap),
lapSpan = createTimer(),
offset,
clock,
interval;
options = options || {};
options.delay = options.delay || 1;
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
elem.appendChild(lapButton);
elem.appendChild(lapSpan);
reset();
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 lap() {
lapSpan.innerHTML=timer.innerHTML;
}
function reset() {
clock = 0;
render(0);
lap();
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock / 1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
this.getTime=function() {
return clock;
}
this.start = start;
this.stop = stop;
this.reset = reset;
}
};
var elems;
window.onload=function() {
elems = document.getElementsByClassName("basic");
for (var i = 0, len = elems.length; i < len; i++) {
Stopwatch.init(elems[i]);
}
}
And I need to call the lap function when I press a specified key and it looks like this:
document.onkeypress = function(e) {
e = e || window.event;
var charCode = e.charCode || e.keyCode,
character = String.fromCharCode(charCode);
if(e.charCode == 98 || e.keyCode == 98) {
Stopwatch.start();
} else if(e.charCode == 114 || e.keyCode == 114) {
Stopwatch.lap();
}
};
I am most familiar with JavaScript and jQuery in this project but I also know HTML and JavaScript.

You did define the function inside the class/object bu you forgot to add this.lap = lap; so you can use it as a method/property.
Should be:
this.start = start;
this.stop = stop;
this.reset = reset;
this.lap = lap; // this one was missing

You need to add
this.lap = lap;
after the lines
this.start = start;
this.stop = stop;
this.reset = reset;

Related

Check if time since last click is greater than 2 seconds

If found how to do this thanks to this post, but as you can see by the code bellow I'm trying to console.log('Done'); when the time since the last click is greater than 2 seconds. However this doesn't work.
var lastClick = 0;
var button_pressed = false;
let button1 = document.getElementById('button1');
let button2 = document.getElementById('button2');
button1.onclick = function() {
button_pressed = true;
CheckAnswer();
}
button2.onclick = function() {
button_pressed = true;
CheckAnswer();
}
function CheckAnswer() {
if(button_pressed === true) {
var d = new Date();
var t = d.getTime();
if(t - lastClick < 2000) {
console.log('Continue');
}
} else if (t - lastClick > 2000) {
console.log('Done');
}
lastClick = t;
}
<button id="button1">Button1</button>
<button id="button2">Button2</button>
Thank you for your help.
The code never reaches the else if, because it requires button_pressed to be false
I fixed your code, see below.
The else if is now declared withtin the button_pressed === true statement.
function CheckAnswer() {
if(button_pressed === true) {
var d = new Date();
var t = d.getTime();
if(t - lastClick < 2000) {
console.log('Continue');
} else {
console.log('Done');
}
}
lastClick = t;
}
var lastClick = Date.now();
var button_pressed = false;
let button1 = document.getElementById('button1');
let button2 = document.getElementById('button2');
button1.onclick = function() {
button_pressed = true;
CheckAnswer();
}
button2.onclick = function() {
button_pressed = true;
CheckAnswer();
}
function CheckAnswer() {
var t = Date.now();
var diff = t - lastClick;
if(diff < 2000) {
console.log('Continue');
} else {
console.log('Done');
}
lastClick = t;
}
<button id="button1">Button1</button>
<button id="button2">Button2</button>

Alert returning as undefined

I am trying to have my alert show up with the time that my timer shows.
function Stopwatch(elem) {
var time = 0;
var offset;
var interval;
function update() {
if (this.isOn) {
time += delta();
}
elem.textContent = timeFormatter(time);
}
function delta() {
var now = Date.now();
var timePassed = now - offset;
offset = now;
return timePassed;
}
function timeFormatter(time) {
time = new Date(time);
var minutes = time.getMinutes().toString();
var seconds = time.getSeconds().toString();
var milliseconds = time.getMilliseconds().toString();
if (minutes.length < 2) {
minutes = '0' + minutes;
}
if (seconds.length < 2) {
seconds = '0' + seconds;
}
while (milliseconds.length < 3) {
milliseconds = '0' + milliseconds;
}
return minutes + ' : ' + seconds + ' . ' + milliseconds;
}
this.start = function() {
interval = setInterval(update.bind(this), 10);
offset = Date.now();
this.isOn = true;
};
this.stop = function() {
clearInterval(interval);
interval = null;
this.isOn = false;
};
this.reset = function() {
time = 0;
update();
};
this.isOn = false;
}
var timer = document.getElementById('timer');
var toggleBtn = document.getElementById('toggle');
var resetBtn = document.getElementById('reset');
var watch = new Stopwatch(timer);
function start() {
toggleBtn.textContent = 'Stop';
watch.start();
}
function stop() {
toggleBtn.textContent = 'Start';
watch.stop();
}
toggleBtn.addEventListener('click', function() {
watch.isOn ? stop() : start();
});
resetBtn.addEventListener('click', function() {
watch.reset();
});
function alertSystem(){
var timer = document.getElementById('timer')
alert(timer);
}
<h1 id="timer">00 : 00 . 000</h1>
<div>
<button class=button id="toggle">Start</button>
<button class=button id="reset">Reset</button>
<button onclick='alertSystem()'>get number</button>
</div>
It's a lot of code, but it is mostly to get the timer working. The last function called alertSystem() is on the bottom and is the one that triggers the alert call. For me the alert shows up as [object HTMLHeadingElement] or as undefined. The former comes up when I have alert(timer); but if I do alert(timer.value); or alert(timer.length); I get the latter.
Does anyone know how I can just get the value of the timer in the alert?
To get the timer's value, you should do something like:
document.querySelector('#timer').innerHTML
Otherwise , document.getElementById returns a full element as a js object.

Is there a way to make "onkeydown" return slower

I want to increment an integer by holding down the right arrow key. The function i made works, but it returns too fast.
document.onkeydown = function (e) {
e = e || window.event;
if (e.keyCode == '39') {
var steps = localStorage.getItem("steps");
if (+steps < 9) {
if (+steps === +steps) {
localStorage.setItem("steps", +steps + +1)
}
} else {
localStorage.setItem("steps", +steps - +10);
}
var sss = localStorage.getItem("steps");
unicorn.className = "unicorn_" + sss + "";
return false;
}
}
The code above is where i'm at now. I am using localStorage to check the stored integer, and incrementing if it matches. Once the integer gets to 9, it substracts back to 0.
can anyone see what i'm doing wrong, or not doing right?
You can also manually keep track of the time using a closure:
document.onkeydown = (function () {
var T0 = Date.now();
return function (event) {
if (Date.now() - T0 > 500) {
console.log("doing my thing over here", Math.random());
T0 = Date.now();
}
}
})();
If you don't want it to execute too fast then consider placing it in a setTimeout
var notTooFast = false;
var timeout = 1000; // change it whatever you want to be
document.onkeydown = function (e) {
e = e || window.event;
if (e.keyCode == '39') {
if (!notTooFast)
{
var steps = localStorage.getItem("steps");
if (+steps < 9) {
if (+steps === +steps) {
localStorage.setItem("steps", +steps + +1)
}
} else {
localStorage.setItem("steps", +steps - +10);
}
var sss = localStorage.getItem("steps");
unicorn.className = "unicorn_" + sss + "";
notTooFast = true;
setTimeout(function () {
notTooFast = false;
}, timeout);
return false;
}
}
}

Java Script Calculating and Displaying Idle Time

I'm trying to write with javascript and html how to display the time a user is idle (not moving mouse or pressing keys). While the program can detect mousemovements and key presses, the program for some reason isn't calling the idleTime() method which displays the time in minutes and seconds.
I'm wondering why the method isn't getting called, as if it is called it would display true or false if a button is pressed.
var startIdle = new Date().getTime();
var mouseMoved = false;
var buttonPressed = false;
function idleTime() {
document.write(buttonPressed);
if (mouseMoved || buttonPressed) {
startIdle = new Date().getTime();
}
document.getElementById('idle').innerHTML = calculateMin(startIdle) + " minutes: " + calculateSec(startIdle) + " seconds";
var t = setTimeout(function() {
idleTime()
}, 500);
}
function calculateSec(startIdle1) {
var currentIdle = new Date().getTime();
var timeDiff = Math.abs(currentIdle - startIdle1);
var idleSec = Math.ceil(timeDiff / (1000));
return idleSec % 60;
}
function calculateMin(startIdle1) {
var currentIdle = new Date().getTime();
var timeDiff = Math.abs(currentIdle - startIdle1);
var idleMin = Math.ceil(timeDiff / (1000 * 60));
return idleMin;
}
var timer;
// mousemove code
var stoppedElement = document.getElementById("stopped");
function mouseStopped() { // the actual function that is called
mouseMoved = false;
stoppedElement.innerHTML = "Mouse stopped";
}
window.addEventListener("mousemove", function() {
mouseMoved = true;
stoppedElement.innerHTML = "Mouse moving";
clearTimeout(timer);
timer = setTimeout(mouseStopped, 300);
});
//keypress code
var keysElement = document.getElementById('keyPressed');
window.addEventListener("keyup", function() {
buttonPressed = false;
keysElement.innerHTML = "Keys not Pressed";
clearTimeout(timer);
timer = setTimeout("keysPressed", 300);
});
window.addEventListener("keydown", function() {
buttonPressed = true;
keysElement.innerHTML = "Keys Pressed";
clearTimeout(timer);
timer = setTimeout("keyPressed", 300);
});
function checkTime(i) {
if (i < 10) {
i = "0" + i
}; // add zero in front of numbers < 10
return i;
}
Here is the HTML code:
<body onload="idleTime()">
<div id="stopped"><br>Mouse stopped</br></div>
<div id="keyPressed"> Keys not Pressed</div>
<strong>
<div id="header"><br>Time Idle:</br>
</div>
<div id="idle"></div>
</strong>
</body>
Actually the keysElement and stoppedElement were not referred firing before the DOM load. and also removed the document.write
Thats all all good. :)
var startIdle = new Date().getTime();
var mouseMoved = false;
var buttonPressed = false;
function idleTime() {
//document.write(buttonPressed);
if (mouseMoved || buttonPressed) {
startIdle = new Date().getTime();
}
document.getElementById('idle').innerHTML = calculateMin(startIdle) + " minutes: " + calculateSec(startIdle) + " seconds";
var t = setTimeout(function() {
idleTime()
}, 500);
}
function calculateSec(startIdle1) {
var currentIdle = new Date().getTime();
var timeDiff = Math.abs(currentIdle - startIdle1);
var idleSec = Math.ceil(timeDiff / (1000));
return idleSec % 60;
}
function calculateMin(startIdle1) {
var currentIdle = new Date().getTime();
var timeDiff = Math.abs(currentIdle - startIdle1);
var idleMin = Math.ceil(timeDiff / (1000 * 60));
return idleMin;
}
var timer;
// mousemove code
//var stoppedElement = document.getElementById("stopped");
function mouseStopped() { // the actual function that is called
mouseMoved = false;
document.getElementById("stopped").innerHTML = "Mouse stopped";
}
function keyStopped() { // the actual function that is called
buttonPressed = false;
document.getElementById("keyPressed").innerHTML = "Keys stopped";
}
window.addEventListener("mousemove", function() {
mouseMoved = true;
document.getElementById("stopped").innerHTML = "Mouse moving";
clearTimeout(timer);
timer = setTimeout(mouseStopped, 500);
});
window.addEventListener("keyup", function() {
buttonPressed = true;
document.getElementById('keyPressed').innerHTML = "Keys Pressed";
clearTimeout(timer);
timer = setTimeout(keyStopped, 500);
});
window.addEventListener("keydown", function() {
buttonPressed = true;
document.getElementById('keyPressed').innerHTML = "Keys Pressed";
clearTimeout(timer);
timer = setTimeout(keyStopped, 500);
});
function checkTime(i) {
if (i < 10) {
i = "0" + i
}; // add zero in front of numbers < 10
return i;
}
window.onload = idleTime;
<div id="stopped"><br>Mouse stopped</br></div>
<div id="keyPressed"> Keys not Pressed</div>
<strong>
<div id="header"><br>Time Idle:</br></div>
<div id="idle"></div>
</strong>

Pause and resume setInterval

window.setInterval(function(){
//do stuff
}, milisec);
Is there a way to stop this interval at will, and to resume it from where it lasted? Say, code runs every 5 sec. I stop it in the middle of the 2nd second, when resumed, I want it to run the remaining 3 seconds and continue to run afterwards every 5 sec. again.
Try this:
1- when you want to pause the timer, calculate the remaining milliseconds and store it somewhere then call clearInterval.
2- When you want to resume the timer, just make a call to setTimeout passing the remaining time stored in the previous step as the argument.
3- And in setTimeout's callback you should call setInterval again.
UPDATE: This is what you want, a changed version of javascript: pause setTimeout(); thanks to #Felix Kling
function IntervalTimer(callback, interval) {
var timerId, startTime, remaining = 0;
var state = 0; // 0 = idle, 1 = running, 2 = paused, 3= resumed
this.pause = function () {
if (state != 1) return;
remaining = interval - (new Date() - startTime);
window.clearInterval(timerId);
state = 2;
};
this.resume = function () {
if (state != 2) return;
state = 3;
window.setTimeout(this.timeoutCallback, remaining);
};
this.timeoutCallback = function () {
if (state != 3) return;
callback();
startTime = new Date();
timerId = window.setInterval(callback, interval);
state = 1;
};
startTime = new Date();
timerId = window.setInterval(callback, interval);
state = 1;
}
Usage:
var timer = new IntervalTimer(function () {
alert("Done!");
}, 5000);
window.setTimeout(function () {
timer.pause();
window.setTimeout(function () {
timer.resume();
}, 5000);
}, 2000);
To piggyback off Alireza's answer, here's an ES6 class that does the same thing with a bit more functionality, and doesn't start right away. You can set a maximum number of times the timer will fire off before automatically stopping, and pause and resume any number of times before the next time it's set to fire off.
export default class IntervalTimer{
constructor(name, callback, interval, maxFires = null){
this.remaining = 0;
this.state = 0; // 0 = idle, 1 = running, 2 = paused, 3= resumed
this.name = name;
this.interval = interval; //in ms
this.callback = callback;
this.maxFires = maxFires;
this.pausedTime = 0; //how long we've been paused for
this.fires = 0;
}
proxyCallback(){
if(this.maxFires != null && this.fires >= this.maxFires){
this.stop();
return;
}
this.lastTimeFired = new Date();
this.fires++;
this.callback();
}
start(){
this.log.info('Starting Timer ' + this.name);
this.timerId = setInterval(() => this.proxyCallback(), this.interval);
this.lastTimeFired = new Date();
this.state = 1;
this.fires = 0;
}
pause(){
if (this.state != 1 && this.state != 3) return;
this.log.info('Pausing Timer ' + this.name);
this.remaining = this.interval - (new Date() - this.lastTimeFired) + this.pausedTime;
this.lastPauseTime = new Date();
clearInterval(this.timerId);
clearTimeout(this.resumeId);
this.state = 2;
}
resume(){
if (this.state != 2) return;
this.pausedTime += new Date() - this.lastPauseTime;
this.log.info(`Resuming Timer ${this.name} with ${this.remaining} remaining`);
this.state = 3;
this.resumeId = setTimeout(() => this.timeoutCallback(), this.remaining);
}
timeoutCallback(){
if (this.state != 3) return;
this.pausedTime = 0;
this.proxyCallback();
this.start();
}
stop(){
if(this.state === 0) return;
this.log.info('Stopping Timer %s. Fired %s/%s times', this.name, this.fires, this.maxFires);
clearInterval(this.timerId);
clearTimeout(this.resumeId);
this.state = 0;
}
//set a new interval to use on the next interval loop
setInterval(newInterval){
this.log.info('Changing interval from %s to %s for %s', this.interval, newInterval, this.name);
//if we're running do a little switch-er-oo
if(this.state == 1){
this.pause();
this.interval = newInterval;
this.resume();
}
//if we're already stopped, idle, or paused just switch it
else{
this.interval = newInterval;
}
}
setMaxFires(newMax){
if(newMax != null && this.fires >= newMax){
this.stop();
}
this.maxFires = newMax;
}
}
You should only need setTimeout with a go and stop - http://jsfiddle.net/devitate/QjdUR/1/
var cnt = 0;
var fivecnt = 0;
var go = false;
function timer() {
if(!go)
return;
cnt++;
if(cnt >= 5){
cnt=0;
everyFive();
}
jQuery("#counter").text(cnt);
setTimeout(timer, 1000);
}
function everyFive(){
fivecnt++;
jQuery("#fiver").text(fivecnt);
}
function stopTimer(){
go = false;
}
function startTimer(){
go = true;
timer();
}
let time = document.getElementById("time");
let stopButton = document.getElementById("stop");
let playButton = document.getElementById("play");
let timeCount = 0,
currentTimeout;
function play_pause() {
let status = playButton.innerHTML;
if (status == "pause") {
playButton.innerHTML = "Resume";
clearInterval(currentTimeout);
return;
}
playButton.innerHTML = "pause";
stopButton.hidden = false;
clearInterval(currentTimeout);
currentTimeout = setInterval(() => {
timeCount++;
const min = String(Math.trunc(timeCount / 60)).padStart(2, 0);
const sec = String(Math.trunc(timeCount % 60)).padStart(2, 0);
time.innerHTML = `${min} : ${sec}`;
}, 1000);
}
function reset() {
stopButton.hidden = true;
playButton.innerHTML = "play";
clearInterval(currentTimeout);
timeCount = 0;
time.innerHTML = `00 : 00`;
}
<div>
<h1 id="time">00 : 00</h1>
<br />
<div>
<button onclick="play_pause()" id="play">play</button>
<button onclick="reset()" id="stop" hidden>Reset</button>
</div>
</div>

Categories