jquery: stopwatch - javascript

I'm using the stopwatch code I found here:
http://www.kellishaver.com/projects/stopwatch/
(function($) {
$.fn.stopwatch = function() {
var clock = this;
var timer = 0;
clock.addClass('stopwatch');
//console.log(clock);
// This is bit messy, but IE is a crybaby and must be coddled.
clock.html('<div class="display"><span class="hr">00</span>:<span class="min">00</span>:<span class="sec">00</span></div>');
clock.append('<input type="button" class="start" value="Start" />');
clock.append('<input type="button" class="stop" value="Stop" />');
clock.append('<input type="button" class="reset" value="Reset" />');
//console.log(clock.html());
// We have to do some searching, so we'll do it here, so we only have to do it once.
var h = clock.find('.hr');
var m = clock.find('.min');
var s = clock.find('.sec');
var start = clock.find('.start');
var stop = clock.find('.stop');
var reset = clock.find('.reset');
stop.hide();
start.bind('click', function() {
timer = setInterval(do_time, 1000);
stop.show();
start.hide();
});
stop.bind('click', function() {
clearInterval(timer);
timer = 0;
start.show();
stop.hide();
});
reset.bind('click', function() {
clearInterval(timer);
timer = 0;
h.html("00");
m.html("00");
s.html("00");
stop.hide();
start.show();
});
function do_time() {
// parseInt() doesn't work here...
hour = parseFloat(h.text());
minute = parseFloat(m.text());
second = parseFloat(s.text());
second++;
if(second > 59) {
second = 0;
minute = minute + 1;
}
if(minute > 59) {
minute = 0;
hour = hour + 1;
}
h.html("0".substring(hour >= 10) + hour);
m.html("0".substring(minute >= 10) + minute);
s.html("0".substring(second >= 10) + second);
}
};
})(jQuery);
And I use it like this:
<script type="text/javascript">
$('#clock1').stopwatch();
</script>
It works fine and I can stop it using the stop button. However I would like to be able to stop it programatically using javascript. Something like this:
<script type="text/javascript">
$('#clock1').stop();
</script>
I created the stop function but I cannot access the timer var defined in stopwatch(). How can I do it?

How about:
$('#clock1').find('.stop').trigger('click');

You can add a small API to the code and attach it using $.data:
var api = {
stop: function() {
stop.click(); // this should probably be improved, but you get the idea
}
};
$(clock).data('stopwatch', api);
Then use:
$('#clock1').data('stopwatch').stop();
You can also add the reset and start functions to the API using the same logic. A good thing here is that you can improve the execution code on a coffee break later without changing the way external programs uses the API.

Related

How do I record multiple time values, one after another

I have an issue with printing 5 different values one after another. My code is supposed to work like this:
The user presses the the start button, the timer begins, then the user presses the stop button, the timer stops and the time that has passed is printed below. The user does that 5 times and each entry below is supposed to have a different time value based on how fast the user was. (e.g. "1. you took 2.3 seconds. 2. you took 1.7 seconds. etc.).
My code seems to print the first time value, but when I couldn't get it to work with the second attempt, I've tried adding if statements to check if the first inner html label is filled, but that didn't work.
Here is my code:
var status = 0; //0:stop 1:running
var time = 0;
var f = 0;
var s = 0;
var t = 0;
var f = 0;
var f2 = 0;
function start() {
status = 1;
document.getElementById("startBtn").disabled = true;
timer();
if (f = 0) {
f + 1;
} else if (f > 0) {
s + 1;
}
}
function stop() {
if (f = 1) {
document.getElementById("first").innerHTML = time + 1;
f++;
}
if (s = 1) {
document.getElementById("second").innerHTML = time + 1;
s++;
}
status = 0;
document.getElementById("startBtn").disabled = false;
}
function reset() {
status = 0;
time = 0;
document.getElementById('timerLabel').innerHTML = '00:00:00';
document.getElementById("startBtn").disabled = false;
}
function timer() {
if (status == 1) {
setTimeout(function() {
time++;
var min = Math.floor(time / 100 / 60);
var sec = Math.floor(time / 100);
var mSec = time % 100;
if (min < 10) {
min = "0" + min;
}
if (sec >= 60) {
sec = sec % 60;
}
if (sec < 10) {
sec = "0" + sec;
}
document.getElementById('timerLabel').innerHTML = min + ":" + sec + ":" + mSec;
timer();
}, 10);
}
}
<div class="container">
<h1 class="title">Stopwatch</h1>
<h1 id="timerLabel">00:00:00</h1>
<input type="button" value="START" class="myButton" onClick="start()" id="startBtn">
<input type="button" value="STOP" class="myButton" onClick="stop()">
<input type="button" value="RESET" class="myButton" onClick="reset()">
<h2 id="first">0</h2>
<h2 id="second">0</h2>
<h2 id="third">0</h2>
<h2 id="forth">0</h2>
<h2 id="fifth">0</h2>
</div>
I see several issues right away.
First you have var f = 0 twice.
You have f + 1; and s + 1; but those statements don't return anything, you want s++; and f++; or s+=1; and f+=1; if you want the s and f variables to increment.
Your if conditions use =, which is for assignment and therefore will always return true, instead of == (equality with conversion) or better yet, === (strict equality).
Fixing those issues will probably get you up and running.
But, you've also got too much complication in this solution.
First, you should not be using inline HTML event attributes (onclick, etc.) and instead, you should be setting up all your event handling in JavaScript.
Next, it seems that you have too many variables for what you are trying to do. There really isn't a need for status as far as I can tell. If you are in the stop function, it's obvious that you are stopped. If you are in the timer function, you must be started. I also don't see the need for the f, s, f2 and t variables or the code that tracks them.
You forgot to check mSec for single digits and prepend a 0 in those cases.
Only use .innerHTML when the string you are supplying contains HTML that needs to be parsed by the browser. If there is no HTML in the string, the HTML parser will be invoked for no reason and that's a waste of resources. For non-HTML strings, use .textContent.
You also don't need to set up empty <h2> placeholders for the results ahead of time. You can create them on the fly so there will be less HTML and less JavaScript to try to test for them and match them.
Related to the <h2> comment, you should be using tags because of the semantics they convey, not because of the default formatting the browser applies to them. <h1>is fine for your page title of Stopwatch because that's a heading, but it's incorrect for showing the elapsed time because that's not a section heading. And, to show the various times between clicks, a bullet list is appropriate because you are, well, making a list. Use the right tag for the job, but then use CSS to style anything anyway that you want.
And, by separating out the code that creates the 00:00:00 string into its own function, you can call it whenever you need that format created.
I believe I've accomplished what you want below. See comments for explanations:
var time = 0; // Store the elapsed time count
var timeout = null; // Will hold a reference to the setTimeout
var lastTime = null; // Stores the time count when the stop button was last pressed
// Get all the DOM references you'll be working with, just once
// and make them available to all the functions so you don't need
// to keep finding them over and over.
var btnStart = document.getElementById("startBtn");
var btnStop = document.getElementById("stopBtn");
var btnReset = document.getElementById("resetBtn");
var timerLabel = document.getElementById('timerLabel');
var results = document.getElementById("results");
// Set up your event handlers in JavaScript, not in HTML
btnStart.addEventListener("click", start);
btnStop.addEventListener("click", stop);
btnReset.addEventListener("click", reset);
function start() {
btnStart.disabled = true;
timeout = setTimeout(function(){
time++; // Increment time count
timerLabel.textContent = getFormattedTime(time); // Update counter with formatted time
start(); // Run timer again
}, 10);
}
function stop() {
clearTimeout(timeout); // Stop the timer
var li = document.createElement("li"); // Create a new <li> element
li.textContent = getFormattedTime(time - lastTime); // Set the text for the element
lastTime = time; // Store the time that the timer stopped
results.appendChild(li); // Add the <li> to the static <ul>
btnStart.disabled = false; // Disable the start button
}
function reset(){
clearTimeout(timeout); // Stop the timer
time = 0; // Reset the time
lastTime = 0; // Reset the last time
timerLabel.textContent = '00:00:00'; // Reset the time label
btnStart.disabled = false; // Enable the start button
results.innerHTML = ""; // Clear out the static <ul>
}
// This function accepts the time count and retuns it in a 00:00:00 format
function getFormattedTime(timeVal){
var min = Math.floor(timeVal/100/60);
var sec = Math.floor(timeVal/100);
var mSec = timeVal % 100;
if(min < 10) { min = "0" + min; }
if(sec >= 60) { sec = sec % 60; }
if(sec < 10) {
if(sec === 0) {
sec = "00";
} else {
sec = "0" + sec;
}
}
if(mSec < 10) {
if(mSec === 0) {
mSec = "00";
} else {
mSec = "0" + mSec;
}
}
return min + ":" + sec + ":" + mSec;
}
/* Make elapsed time area stand out */
#timerLabel {
font-size:2em;
font-weight:bold;
margin-bottom:1em;
background-color:#ff00ff;
font-family:Arial, Helvetica, sans-serif;
display:inline-block;
padding:15px;
width:10em;
text-align:center;
}
ul { padding:0; } /* remove default indentation of list */
li { list-style-type: none; } /* remove standard bullet discs */
li::before { content: " - "; } /* place a dash before each list item instead */
<div class="container">
<h1 class="title">Stopwatch</h1>
<div id="timerLabel">00:00:00</div>
<div>
<input type="button" value="START" class="button" id="startBtn">
<input type="button" value="STOP" class="button" id="stopBtn">
<input type="button" value="RESET" class="button" id="resetBtn">
</div>
<ul id="results"></ul>
</div>

Countdown timer working stop on chrome extensions.

I think that I will build chrome extensions to count down.
In case of the present code, if popup.html is closed, processing will be completed compulsorily.
In this case, is it better to write setInterval to background.js?
Moreover, I want you to teach whether what I should do concrete.
background.js
var num = window.localStorage.setItem("minite_num", 20);
default_count = num*60;
function count_start() {
count = default_count;
chrome.browserAction.setIcon({
path: {
"19": "img/icon_count19.png",
"38": "img/icon_count38.png"
}
});
}
function count_down() {
count--;
if (count <= 0) {
page_change();
count_stop();
}
}
popup.js
var bg = chrome.extension.getBackgroundPage();
var num = bg.num;
var start_btn = document.count_timer.start_btn;
var count_time = document.getElementById("counter");
document.addEventListener('DOMContentLoaded', function () {
load();
start_btn.addEventListener('click', start_display);
});
function timer_reset() {
timerID = 0;
}
function count_format(num) {
var tm,ts;
tm = Math.floor(num / 60); //分
ts = num % 60; //秒
if (ts < 10) ts = "0" + ts;
return tm + ":" + ts;
}
function load(){
display_num = bg.count_format(bg.default_count);
bg.timer_reset();
start_btn.disabled = false;
count_time.innerHTML = display_num;
}
function start_display() {
start_btn.disabled = true;
bg.count_start();
timerID = setInterval(function() {bg.count_down();count_time.innerHTML = bg.count;}, 1000);
}
popup.html
<form name="count_timer" class="count_timer">
<div id="counter" class="counter"></div>
<input type="button" name="start_btn" value="START">
</form>
Thanks.
use chrome storage / localStorage to remember your target time.
Use an interval from the popup to update your calculations. First time, the popup needs to read from storage and determine where the countdown is at.
Nothing needs to be done from background, unless you want to separate logic (as in MVC), then maybe do all storage stuff from background, and ask for it with messaging.
I have a published open-source chrome extension (plus for trello) with a count(up) timer feature that does something similar.

Pause / Resume jQuery Countdown Timer

I'm trying to make a countdown timer that can be paused with a single HTML5 button tag using a JS onClick() event, or more preferably, using jQuery with something like $("#pause_resume").off('click').on('click', firstClick)in conjunction with another function. Logically, I would assume the task would require getting the current values of both $.min and $.sec and then setting these values, while switching functions, until the "resume" button is pressed again. But I honestly have no idea how to go about doing this. I've looked at other code on this site and others, but what I saw was heavily deprecated and not in line with my project plan. Any insight is appreciated.
HTML:
<p class="timer">
<span class="min"></span>:<span class="sec"></span>/
<span class="fullTime">1:30</span>
</p>
JavaScript:
<script type="text/javascript">
var timer = $('.timer');
var leadingZero = function(n) {
if (n < 10 && n >= 0)
return '0' + n;
else
return n;
};
var minutes = 1;
var seconds = 30;
setInterval(function () {
var m = $('.min', timer),
s = $('.sec', timer);
if (seconds == 0) {
minutes--;
seconds = 59;
} else {
seconds--;
}
m.text(minutes);
s.text(leadingZero(seconds));
}, 1000);
</script>
Well, I think this is what you want. http://jsfiddle.net/joey6978/67sR2/3/
I added a button that toggles a boolean on click to determine whether to set your function in the interval or to clear the interval.
var clicked=true;
var counter;
$('button').click(function(){
if(clicked){
counter=setInterval(function () {
var m = $('.min', timer),
s = $('.sec', timer);
if (seconds === 0) {
minutes--;
seconds = 59;
} else {
seconds--;
}
m.text(minutes);
s.text(leadingZero(seconds));
}, 1000);
}
else{
clearInterval(counter);
}
clicked=!clicked;
});

Reset javascript function

I am having trouble getting a javascript function to reset itself after an onclick event. When I click the "Start" button the counter begins to count up. But when I click the "Reset" button nothing happens. I need the timer to reset to "0:00" and wait for me to click "Start" again. Here is my code:
<script type="text/javascript">
var seconds = 0;
var minutes = 0;
function zeroPad(time) {
var numZeropad = time + '';
while(numZeropad.length < 2) {
numZeropad = "0" + numZeropad;
}
return numZeropad;
}
function countSecs() {
seconds++;
if (seconds > 59) {
minutes++;
seconds = 0;
}
document.getElementById("timeBox").innerHTML = "Time " + zeroPad(minutes) + ":" + zeroPad(seconds);
}
function startTimer() {
action = window.setInterval(countSecs,1000);
}
function resetTimer() {
var seconds = 0;
var minutes = 0;
}
</script>
<body>
<button onclick = "startTimer()">Start</button>
<div id="timeBox">Time 00:00</div>
<button onclick = "resetTimer">Reset</button>
</body>
Call the clearInterval() method.
function resetTimer() {
window.clearInterval(action);
}
This is a scoping issue, using var inside a function, makes seconds and minutes local to that function. Removing the leading var will start you off in the right direction.
function resetTimer() {
seconds = 0;
minutes = 0;
}
Onclick events must call functions like: onclick="resetTimer();" with the parenthesis at the end. Some browsers may try to submit on button clicks if you don't define type="button". I didn't assume you wanted reset timer to stop the timer so I added a stop button.
http://jsfiddle.net/iambriansreed/WRdSK/
<button type="button" onclick="startTimer();">Start</button>
<div id="timeBox">Time 00:00</div>
<button type="button" onclick="resetTimer();">Reset</button>
<button type="button" onclick="stopTimer();">Stop</button>
<script>
window.seconds = 0;
window.minutes = 0;
function startTimer() {
window.action = setInterval(countSecs,1000);
}
function resetTimer() {
seconds = 0;
minutes = 0;
}
function stopTimer() {
clearInterval(action);
seconds = -1;
minutes = 0;
countSecs();
}
function zeroPad(time) {
var numZeropad = time + '';
while(numZeropad.length < 2) {
numZeropad = "0" + numZeropad;
}
return numZeropad;
}
function countSecs() {
seconds++;
if (seconds > 59) {
minutes++;
seconds = 0;
}
document.getElementById("timeBox").innerHTML = "Time " + zeroPad(minutes) + ":" + zeroPad(seconds);
}
</script>
​
You have two errors in your code:
First, in the button you missed the () after the function's name in order to make an actual call:
<button onclick = "resetTimer()">Reset</button>
Second, you did not stop the interval using window.clearInterval() (MDN docu), so the timer went on and on.
// just to make it an explicit global variable. already was an implicit one.
var action;
// rest of your code
function resetTimer() {
// clear the timer
window.clearInterval( action );
// reset variables
var seconds = 0;
var minutes = 0;
// update output
document.getElementById("timeBox").innerHTML = "Time " + zeroPad(minutes) + ":" + zeroPad(seconds);
}
I set up a working fiddle here.

How to stop my javascript countdown?

How can I stop my javascript function when countdown = 0?
JS:
var settimmer = 0;
$(function(){
window.setInterval(function() {
var timeCounter = $("b[id=show-time]").html();
var updateTime = eval(timeCounter)- eval(1);
$("b[id=show-time]").html(updateTime);
}, 1000);
});
HTML:
<b id="show-time">20</b>
For one thing remove those evals. They don't do anything.
Then all you have to do is clear the timer when it reaches zero.
$(function(){
var timer = setInterval(function() {
var timeCounter = parseInt($("b[id=show-time]").text());
$("b[id=show-time]").text(--timeCounter); // remove one
if(!timeCounter) clearInterval(timer);
}, 1000);
});
It is easy! When you call setInterval it return an ID, so you can destroy the interval later. To destroy it you must use clearInterval(id), and voilà!
It works like this:
// Activate timer
var iv = window.setInterval(...);
// Deactive timer
window.clearInterval(iv);
Also you should use parseInt() instead of eval():
$(function() {
// Read the start value once and store it in a variable
var timeCounter = parseInt( $("b[id=show-time]").text() );
// Active the counter
var iv = window.setInterval(function() {
// Decrement by one and write back into the document
$("b[id=show-time]").text(--timeCounter);
// Check if counter == 0 -> stop counting
if (0 == timeCounter) {
window.clearInterval(iv);
// ...do whatever else needs to be done when counter == 0 ..
}
}, 1000);
});
Example:
var i = 0,
pid = setInterval(function() {
if (++i > 10)
clearInterval(pid);
}, 1000);
Based on what you wanted for your code ...
$(function() {
var el = document.getElementById('show-time'),
pid = setInterval(function() {
// (s - i) coerces s to Number
var t = el.innerHTML - 1;
el.innerHTML = t;
if (t < 1)
clearInterval(pid);
}, 1000);
});
Keep in mind that JS won't be 100% accurate with its timing.
Pasted code below or see the fiddle: http://jsfiddle.net/raHrm/
<script type="text/javascript">
$(function(){
var settimmer = 0,
timeCounter = $("#show-time").html(),
updateTime = timeCounter;
(function countDown() {
timeCounter = $("#show-time").html();
updateTime = parseInt(timeCounter)-1;
$("#show-time").html(updateTime);
if ( updateTime ) {
setTimeout(countDown, 1000);
}
})();
});​
</script>
Set the timer to a variable, then use clearInterval in-order to stop the loop. As for catching the end, use a simple conditional:
$(function(){
var elem=$('strong[id="show-time"]'),settimmer=0,updateTime,t;
t=window.setInterval(function() {
updateTime=parseFloat(elem.html(),10)-1;
if(updateTime==0) {
window.clearInterval(t);
elem.html('Done!');
} else {
elem.html(updateTime);
}
},1000);
});
Then in the HTML:
<strong id="show-time">20</strong>
The <b> tag is depreciated, try to avoid using it. Also, there is no reason to eval() the HTML you are getting from the element; a simple parseFloat() works just fine.

Categories