I have this Football count up script
// Class: Timer
var Timer = function (callback) {
// Property: Frequency of elapse event of the timer in milliseconds
this.Interval = 1000;
// Property: Whether the timer is enable or not
this.Enable = new Boolean(false);
// Event: Timer tick
this.Tick = callback;
// Member variable: Hold interval id of the timer
var timerId = 0;
// Member variable: Hold instance of this class
var thisObject;
// Function: Start the timer
this.Start = function () {
this.Enable = new Boolean(true);
thisObject = this;
if (thisObject.Enable) {
thisObject.timerId = setInterval(
function () {
thisObject.Tick();
}, thisObject.Interval);
}
};
// Function: Stops the timer
this.Stop = function () {
thisObject.Enable = new Boolean(false);
clearInterval(thisObject.timerId);
};
};
// Namespace: Match rules and timings
var Match = {
Timers: {
FirstHalf: new Timer(TimerTick),
HalfTime: new Timer(TimerTick),
SecondHalf: new Timer(TimerTick),
TickCount: -1
},
Strings: {
FirstHalf: 'First Half',
HalfTime: 'Half Time',
SecondHalf: 'Second Half',
FullTime: 'Finished'
},
DisplayTime: function (t) {
var m = parseInt(t / 60);
var s = t % 60;
return (m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s);
}
};
// Function: Tick Event Handler (callback function)
function TimerTick(timer) {
// Document elements used.
var TimerP = document.getElementById('time');
var DisplayP = document.getElementById('display');
// During First Half
if (Match.Timers.FirstHalf.Enable == true) {
if (Match.Timers.TickCount == -1) { Match.Timers.TickCount = 0 }
if (Match.Timers.TickCount == 2700) {
Match.Timers.FirstHalf.Stop();
Match.Timers.TickCount = -1;
Match.Timers.HalfTime.Start();
} else {
TimerP.innerHTML = Match.DisplayTime(Match.Timers.TickCount);
DisplayP.innerHTML = Match.Strings.FirstHalf;
Match.Timers.TickCount++;
}
}
// During Half Time
else if (Match.Timers.HalfTime.Enable == true) {
if (Match.Timers.TickCount == -1) { Match.Timers.TickCount = 0 }
if (Match.Timers.TickCount == 900) {
Match.Timers.HalfTime.Stop();
Match.Timers.TickCount = -1;
Match.Timers.SecondHalf.Start();
} else {
TimerP.innerHTML = '45:00';
DisplayP.innerHTML = Match.Strings.HalfTime + ' (' + Match.DisplayTime(900 - Match.Timers.TickCount) + ')';
Match.Timers.TickCount++;
}
}
// During Second Half
else if (Match.Timers.SecondHalf.Enable == true) {
if (Match.Timers.TickCount == -1) { Match.Timers.TickCount = 2700 }
if (Match.Timers.TickCount == 5400) {
TimerP.innerHTML = '90:00';
DisplayP.innerHTML = Match.Strings.FullTime;
Match.Timers.SecondHalf.Stop();
Match.Timers.TickCount = -1;
} else {
TimerP.innerHTML = Match.DisplayTime(Match.Timers.TickCount);
DisplayP.innerHTML = Match.Strings.SecondHalf;
Match.Timers.TickCount++;
}
}
}
function KickOff() {
var btn = document.getElementById('btnKickOff');
btn.setAttribute('style','display: none;');
Match.Timers.FirstHalf.Start();
}
or check it here http://pastebin.com/CkmPQ9ZV
and I have this HTML code for the script :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<title>Simple Football Match Timer</title>
<script src="timer.js" type="text/javascript"></script>
</head>
<body>
<form id="pageForm" runat="server">
<div>
<p id="display">Waiting for kick off.</p>
<p id="time">00:00</p>
<input id="btnKickOff" type="button" value="Kick Off!" onclick="KickOff();" />
</div>
</form>
</body>
</html>
This script start counting when i click Kick off.. it counts from 0 to 45 mins after that it show HalfTime and countdown 15 mins break after 15 mins is finish it starts counting again from 45 until 90 and when it reach 90 it shows "Finished"
Its nice script but my problem is that i want this script not to start again after every page refresh i want to post it on my website so when users open my website they will be able to see what time the match is.. i will click it on the start of the match.. and it continue until the end
PS: i'm not good in Javascript.. i got help in creating this script :)
If you want everyone to see the same thing when they come to your site, i.e the same match time, you can't use JavaScript like this. JavaScript is run on your users' computers so when you start your timer, only you will see it.
This is difficult to do unless you store a start time on your server that the JavaScript can access to find out how far into the match it is. Personally, I'd create a database table with MySQL and store all the matches and their start times in it. You can then access it with PHP and then call a httprequest to get it into JavaScript. There are probably easier ways of doing this however.
You can probably set a specific unix time for it to start, then have it reference that rather than "timerId" variable.
Related
What I mean is when I start the timer from 20seconds, then close the browser the timer continues running in the background and when I open it again the timer would be like 10seconds till 0 then repeated again from 20seconds, do that forever.
I've written this code in js but the problem is the code is running in the client side which means when I exit and enter again the timer will start from 20 again.
<p id="demo"></p>
<script>
var rtime = 4;
const irtime = 4; // initial time for resetting
function rF(){
setTimeout(() => {
var x = document.getElementById("demo").innerHTML = rtime;
if(rtime > 0){
rtime-- ;
rF();
}else{
rtime = irtime;
rF();
}
}, 1000);
}
rF();
</script>
You can store the previous time in localStorage, then, on page load, retrieve the time and assign it to rtime:
<p id="demo"></p>
<script>
var rtime = localStorage.getItem("last-time");
const irtime = 4; // initial time for resetting
rtime = !rtime ? 4 : rtime;
function rF() {
setTimeout(() => {
var x = document.getElementById("demo").innerHTML = rtime;
if (rtime > 0) {
rtime--;
rF();
} else {
rtime = irtime;
rF();
}
localStorage.setItem("last-time", rtime)
}, 1000);
}
rF();
</script>
Demo: https://jsfiddle.net/Spectric/h8kgjo5d/
I am trying to put together a stopwatch using JavaScript. I have got the date to populate with the correct information but my Stopwatch doesn't work. I click start and the numbers never move from 0, I would like to have it increment in MS no seconds. I have my code for the JS and the HTML also. HTML is functioning as it should but the JS is not. I am very green to the JavaScript world and i have looked and looked and was unable to come across a solution that would be a benefit to me. Thanks for your assistance.
"use strict";
var $ = function(id) { return document.getElementById(id); };
var stopwatchTimer;
var elapsedMinutes = 0;
var elapsedSeconds = 0;
var elapsedMilliseconds = 0;
var displayCurrentTime = function() {
var now = new Date();
var hours = now.getHours();
var ampm = "AM";
if (hours > 12) {
hours = hours - 12;
ampm = "PM";
} else {
switch (hours) {
case 12:
ampm = "PM";
break;
case 0:
hours = 12;
ampm = "AM";
}
}
$("hours").firstChild.nodeValue = hours;
$("minutes").firstChild.nodeValue = padSingleDigit(now.getMinutes());
$("seconds").firstChild.nodeValue = padSingleDigit(now.getSeconds());
$("ampm").firstChild.nodeValue = ampm;
};
var padSingleDigit = function(num) {
if (num < 10) { return "0" + num; }
else { return num; }
};
var tickStopwatch = function() {
// I also need to increment in 10 milliseconds increments but unsure if I //have this right
var ms=0;
var sec=0;
var min=0;
var frame= function() {
If(ms==1000)
ms=0;
sec++;
}
if(sec==60) {
sec=0;
min++;
document.getElementById("s_seconds").innerHTML = valueOf(sec);
document.getElementById("s_minutes").innerHTML = valueOf(min);
document.getElementById("s_ms").innerHTML = valueOf(ms);
}
};
var startStopwatch = function(evt) {
};
var stopStopwatch = function(evt) {
};
var resetStopwatch = function(evt) {
};
window.onload = function() {
displayCurrentTime();
setInterval(tickStopwatch, 1000);
};
"use strict"; //evt is in a separate file
var evt = {
attach: function(node, eventName, func) {
},
detach: function(node, eventName, func) {
},
preventDefault: function(e) {
}
};
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Clock</title>
<link rel="stylesheet" href="clock.css">
<script src="library_event.js"></script>
<script src="clock.js"></script>
</head>
<body>
<main>
<h1>Digital clock with stopwatch</h1>
<fieldset>
<legend>Clock</legend>
<span id="hours"> </span>:
<span id="minutes"> </span>:
<span id="seconds"> </span>
<span id="ampm"> </span>
</fieldset>
<fieldset>
<legend>Stop Watch</legend>
Start
Stop
Reset
<span id="s_minutes">00</span>:
<span id="s_seconds">00</span>:
<span id="s_ms">000</span>
</fieldset>
</main>
</body>
</html>
If you incrementally update the values ms, seconds, minutes you'll never be accurate. You'll lose time with every update. There simply is no interval that can operate at that speed and accuracy in JS.
Instead, compute them from the internal clock
let offset = 0,
paused = true;
render();
function startStopwatch(evt) {
if (paused) {
paused = false;
offset -= Date.now();
render();
}
}
function stopStopwatch(evt) {
if (!paused) {
paused = true;
offset += Date.now();
}
}
function resetStopwatch(evt) {
if (paused) {
offset = 0;
render();
} else {
offset = -Date.now();
}
}
function format(value, scale, modulo, padding) {
value = Math.floor(value / scale) % modulo;
return value.toString().padStart(padding, 0);
}
function render() {
var value = paused ? offset : Date.now() + offset;
document.querySelector('#s_ms').textContent = format(value, 1, 1000, 3);
document.querySelector('#s_seconds').textContent = format(value, 1000, 60, 2);
document.querySelector('#s_minutes').textContent = format(value, 60000, 60, 2);
if(!paused) {
requestAnimationFrame(render);
}
}
<fieldset>
<legend>Stop Watch</legend>
Start
Stop
Reset
<span id="s_minutes">00</span>:
<span id="s_seconds">00</span>:
<span id="s_ms">000</span>
</fieldset>
offset stores two values: when paused it stores the value at which you stopped, otherwise it stores the offset you have to add to Date.now() to compute the value.
The value is the time in ms, computing seconds and minutes out of it is basic arithmetic.
Your interval function is set to run once per 1000ms (or 1 sec), which won't give you 1ms resolution. In fact, the best you can do is 10ms resolution with setInterval. You also need to increment a counter, which you currently don't do.
Try:
setInterval(tickStopwatch, 10);
var ms = 0;
var tickStopwatch = function() {
var ms += 10;
// rest of your logic
}
I have an issue that hold my neck with time interval. I am calculating my time/clock one second at a time with the function below.
Header.prototype= {
time_changed : function(time){
var that = this;
var clock_handle;
var clock = $('#gmtclock');
that.time_now = time;
var increase_time_by = function(interval) {
that.time_now += interval;
};
var update_time = function() {
clock.html(moment(that.time_now).utc().format("YYYY-MM-DD HH:mm") + " GMT");
};
update_time();
clearInterval(clock_handle);
clock_handle = setInterval(function() {
increase_time_by(1000);
update_time();
}, 1000);
},
};
The above works fine and increase my time a second at a time correctly . However. I added another event that fires on web changed or tab navigated.
var start_time;
var tabChanged = function() {
if(clock_started === true){
if (document.hidden || document.webkitHidden) {
start_time = moment().valueOf();
time_now = page.header.time_now;
}else {
var tnow = (time_now + (moment().valueOf() - start_time));
page.header.time_changed(tnow);
}
}
};
if (typeof document.webkitHidden !== 'undefined') {
if (document.addEventListener) {
document.addEventListener("webkitvisibilitychange", tabChanged);
}
}
The above fires when ever user leave the page and comes back . It add the delay to the time. However, i notice the second increase rapidly . and very past my timer does not fire very second any more as specified in the clock hand. It add second every milliseconds and fats. Please why this and how do i fix this ? My time run fast and ahead when ever i change tab and returned . Any help would be appreciated
Update
Below is my WS request function.
Header.prototype = {
start_clock_ws : function(){
var that = this;
function init(){
clock_started = true;
WS.send({ "time": 1,"passthrough":{"client_time" : moment().valueOf()}});
}
that.run = function(){
setInterval(init, 900000);
};
init();
that.run();
return;
},
time_counter : function(response){
var that = this;
var clock_handle;
var clock = $('#gmt-clock');
var start_timestamp = response.time;
var pass = response.echo_req.passthrough.client_time;
that.time_now = ((start_timestamp * 1000) + (moment().valueOf() - pass));
var increase_time = function() {
that.time_now += (moment().valueOf() - that.time_now);
};
var update_time = function() {
clock.html(moment(that.time_now).utc().format("YYYY-MM-DD HH:mm") + " GMT");
};
update_time();
clearInterval(clock_handle);
clock_handle = setInterval(function() {
increase_time();
update_time();
}, 500);
},
};
and in my WS open event
if(isReady()=== true){
if (clock_started === false) {
page.header.start_clock_ws();
}
}
In my WS onmessage event
if(type ==='time'){
page.header.time_counter(response);
}
Base on your suggestion, i modified my increase_time_by to
var increase_time_by = function() {
that.time_now += (moment().valueOf() - that.time_now);
};
It seems fine now. Would test further and see.
Instead of incrementing the clock by the value of the interval, just update the clock to the current time with each pass. Then it won't matter if you fire exactly 1000 ms apart or not.
You actually may want to run more frequently, such as every 500 ms, to give a smoother feel to the clock ticking.
Basically, it comes down to the precision of the timer functions, or lack thereof. Lots of questions on StackOverflow about that - such as this one.
Based on your comments, I believe you are trying to display a ticking clock of UTC time, based on a starting value coming from a web service. That would be something like this:
var time_from_ws = // ... however you want to retrieve it
var delta = moment().diff(time_from_ws); // the difference between server and client time
// define a function to update the clock
var update_time = function() {
clock.html(moment.utc().subtract(delta).format("YYYY-MM-DD HH:mm") + " GMT");
};
update_time(); // set it the first time
setInterval(update_time, 500); // get the clock ticking
I'm writing an animation looks like number is rising in limited time.
use setInternal and clearInterval to implement it.(I don't want to use Jquery)
the interval time is 1 milliSecond. And limit time is 1000 milli seconds. But it is slower than expected. It went almost 10000 milliseconds.What am I doing wrong?
Here's my code.
<html>
<head>
<title>A numeric test</title>
</head>
<body>
<div id="numberScroll"></div>
<script type="text/javascript">
var limitTime = 100; //milliSeconds
var goalNum = 123456; //the final num
var increament = false; //whether the animation is increasing of not.
var textSize = 30; //size of text
var temNum = increament ? (goalNum * 0.8) : (goalNum * 1.2); //start number
temNum = eval(temNum.toFixed(2));
var increamentNum = (goalNum - temNum) / limitTime;
var numberScroll = document.getElementById("numberScroll");
if(numberScroll === null) {
console.log("No Element Found");
}
numberScroll.style.fontSize = textSize;
numberScroll.innerHTML = temNum;
var intervalId = setInterval(function(){
numberScroll.innerHTML = temNum.toFixed(2);
temNum += increamentNum;
if(increament){
if(temNum >= goalNum) {
clearInterval(intervalId);
numberScroll.innerHTML = goalNum;
}
} else {
if(temNum <= goalNum) {
clearInterval(intervalId);
numberScroll.innerHTML = goalNum;
}
}},1);
</script>
</body>
</html>
I am building simple "Spot the difference" game in jQuery/HTML. There are 5 rounds/stages, each with different pictures and user needs to go through all of them starting from round 1.
I am having this issue with increment firing twice when I am in 2nd round, and then triple times when I am in 3rd round and so on. This cause points to jump up double/triple/... instead of just jump up by 1.
The code is on baby level. I did not make any stuff to refactor it and improve.
I think I don't need to provide HTML for this, as simply looking at logic in JS file should be enough.
For those who prefer pastebin version is here (http://pastebin.com/ACqafZ5G). Full code:
(function(){
var round = 1;
var points = 0;
var pointsTotal = 0;
var pointsDisplay = $(".js-calc");
var pointsTotalDisplay = $(".js-calc-total");
var counterDisplay = $(".js-counter");
var entryPage = $(".entry-page");
var mainMenu = $(".main-menu");
var submitNow = $(".js-now");
var submitResultsFinalBtn = $(".js-submit-results-final");
// rounds-categories
var allRounds = $(".round");
var divRound1 = $(".round1"),
divRound2 = $(".round2"),
divRound3 = $(".round3"),
divRound4 = $(".round4"),
divRound5 = $(".round5");
var allPic = $(".js-pic");
var pic1 = $(".js-pic1"),
pic2 = $(".js-pic2"),
pic3 = $(".js-pic3"),
pic4 = $(".js-pic4"),
picFinish = $(".js-finish");
// on the beginning hide all and leave only entry page
mainMenu.hide();
allRounds.hide();
submitResultsFinalBtn.hide();
// countdown (SEE THE FUNCTION ON THE END)
var myCounter = new Countdown({
seconds: 60, // number of seconds to count down
onUpdateStatus: function(sec){
counterDisplay.html(sec); // display seconds in html
}, // callback for each second
onCounterEnd: function(){
console.log('TIME IS OVER!');
// THIS SHOULD NOT BE HERE, I WOULD PREFER TO MOVE IT SOMEWHERE TO GAME ITSELF
pointsTotalDisplay.html(pointsTotal);
round++; // update to next round
allRounds.hide(); // hide window
mainMenu.show(); // show back again main menu
} // final action
});
var initiateRound = $(".js-initiate");
initiateRound.on("click", function(){ // START GAME
console.log("ROUND " + round + " INITIATED");
points = 0; // reset the points for this round to 0 - not sure this is the way to do it...
console.log(points + " points for this round, " + pointsTotal + " in TOTAL"); // say how many points so far
entryPage.hide();
mainMenu.hide();
allPic.hide();
if( round === 1){
divRound1.show();
pic1.show();
}else if( round === 2){
divRound2.show();
pic2.show();
}else if( round === 3){
divRound3.show();
pic3.show();
}else if( round === 4){
divRound4.show();
pic4.show();
}else if( round === 5){
divRound5.show();
picFinish.show();
initiateRound.hide();
submitNow.hide();
submitResultsFinalBtn.show();
}
counterDisplay.html("60"); //display 60sec on the beginning
myCounter.start(); // and start play time (countdown)
// pointsDisplay.html(points); // display in HTML amount of points for particular round
// if user start collecting points, add them
var mapImage = $('.transparent AREA');
mapImage.each(function(index) {
// When clicked, reveal red circle with missing element
$(this).one("click", function(e) { // YOU CAN CLICK ONLY ONCE!! Using .one() to prevent multiple clicks and eventually scoring more points
e.stopPropagation();
console.log("FIRED");
var theDifference = '#'+$(this).attr('id')+'-diff';
$(theDifference).css('display', 'inline');
if ($(theDifference).data('clicked', true)){ // found circle
// points++;
points += 1;
pointsTotal++;
console.log(points + " points for this round, " + pointsTotal + " in TOTAL");
pointsDisplay.html(points); // display in html amount of points
}
if (points === 6){ // if all points collected (max 6) for this round
myCounter.stop(); // stop countdown
console.log("time stopped, you found all");
setTimeout(function(){ // give him 2sec delay to see last circle marked
allRounds.hide(); // hide window
mainMenu.show(); // show back again main menu
console.log("round " + round + " is finished");
round++; // update to next round
console.log("round " + round + " is activated");
pointsTotalDisplay.html(pointsTotal); // display in HTML total amount of pints
}, 2000);
};
});
});
});
})();
function Countdown(options) {
var timer,
instance = this,
seconds = options.seconds || 10,
updateStatus = options.onUpdateStatus || function () {},
counterEnd = options.onCounterEnd || function () {};
function decrementCounter() {
updateStatus(seconds);
if (seconds === 0) {
counterEnd();
instance.stop();
}
seconds--;
}
this.start = function () {
clearInterval(timer);
timer = 0;
seconds = options.seconds;
timer = setInterval(decrementCounter, 1000);
};
this.stop = function () {
clearInterval(timer);
};
}
Are you sure you're not stacking the $('.transparent AREA') from a round to another ?
This would explain why you score multiple times:
var mapImage = $('.transparent AREA');
mapImage.each(function(index) {
// ...
points++;
// ...
});
Solved!
mapImage.each should be outside of initiateRound