I have the following code and I am wondering how to put it all on one function and give the id's of the span a unique id. So that way I dont have to have multiple instances off the same code each time. Right now if I want to have 3 countdowns I have to add his code three times and change the span id to a unique ID if i don't it will only work onces. So basically I want to be able to turn the JavaScript into one function so that I can call it without having to copy and paste it multiple times and also be able to have more than one countdown on a page by giving the span its own unique(random) id.
<script>
function showRemaining() {
<?php echo "var end = new Date('". $row['expires'] ."');"; ?>
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour *24
var timer;
var now = new Date();
var distance = end - now;
if (distance < 0 ) {
clearInterval( timer );
document.getElementById('countdown').innerHTML = 'EXPIRED!';
return;
}
var days = Math.floor(distance / _day);
var hours = Math.floor( (distance % _day ) / _hour );
var minutes = Math.floor( (distance % _hour) / _minute );
var seconds = Math.floor( (distance % _minute) / _second );
document.getElementById('countdown').innerHTML = 'Days: ' + days + ' ';
document.getElementById('countdown').innerHTML += 'Hours: ' + hours + ' ';
document.getElementById('countdown').innerHTML += 'Minutes: ' + minutes + ' ';
document.getElementById('countdown').innerHTML += 'Seconds: ' + seconds;
}
timer = setInterval(showRemaining, 1000);
</script>
<span id="countdown"></span>
Here's a few approaches I would recommend to make this function more reusable.
Pass the time of expiry as an argument, instead of hard-coding it to some database value that's printed by PHP code.
Break the implicit timer and UI (span) connection. Pass the element where this timer would be updated explicitly.
Manage the timer interval within the function itself. Right now it's spread between the function and global code (setInterval), which will make it difficult to reuse.
Here's the updated interface I propose for this function.
/*
#param expiryTime timestamp when this countdown will expire
#param elementToUpdate a reference to a DOM element that shows the timer
*/
function showRemainingTime(expiryTime, elementToUpdate)
Say if you have two spans with id's a and b which need to show this timer, then you would use this function as,
showRemainingTime(1325544453556, document.getElementById('a'));
showRemainingTime(1218290387102, document.getElementById('b'));
Related
Im trying to write a program where the user enters their birthday and a countdown timer appears and counts down the months days hours and seconds until their birthday. Right now it is not not working and any help would be great! Thanks!
<body>
<script>
var end = new Date();
document.getElementById("myDate").value = end;
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var _month = _day * 30;
var timer;
function showRemaining() {
var now = new Date();
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementById('countdown').innerHTML = 'EXPIRED!';
return;
}
var months = Math.floor(distance / _month);
var days = Math.floor((distance % _month) / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('countdown').innerHTML = months + 'months ';
document.getElementById('countdown').innerHTML += days + 'days ';
document.getElementById('countdown').innerHTML += hours + 'hrs ';
document.getElementById('countdown').innerHTML += minutes + 'mins ';
document.getElementById('countdown').innerHTML += seconds + 'secs';
}
timer = setInterval(showRemaining, 1000);
</script>
Enter your birthday:
<br>
<input type="date" id="myDate">
<br>
<br>
<input type="button" onclick="showRemaining()" value="Enter">
<div id="countdown"></div>
</body>
There are a number of issues with your code as identified in other answers, I'll paraphrase:
The script runs before the elements exist in the DOM, so attempts to reference them return null and you'll get errors attempting to set its properties.
end is set as the page loads, so it's always in the past in respect to when the function runs, so end - now is either
zero (probably initially) or negative (more than 1 millisecond after assigning to end).
The button will allow multiple instance of setInterval to be running, so you'll get some pretty confusing results since they're all trying to set the value of countdown
The calculation is flawed as there aren't exactly 30 days in every month, nor 24 hours in every day if the host observes daylight saving. Fixing that isn't hard, but I'm not going to fix it here.
Don't use input type Date, support is patchy. You can test for support and handle cases where it isn't, but it's all a bit much for this exercise.
So, don't start the timer until the button is pressed (or some other event after the page is loaded), stop any timer that is currently running and reset end at the same time.
Note that setInterval will drift as it doesn't run at exactly every second, so every now and then it will skip two seconds. Also, invalid date input should be dealt with. Both can be fixed, but out of scope here. ;-)
// Don't set the value for end until the button is pressed.
var end; // = new Date();
// document.getElementById("myDate").value = end;
// Also need a global timer reference so it can be cancelled when required
var timer;
// Since listener is attached by addEventListener, event will only be passed
// if the call comes from the button
function showRemaining(event) {
// Function to cancel the timer
function stopTimer(){
if (timer) {
clearInterval(timer);
end = timer = null;
}
}
// Keep these local
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var _month = _day * 30;
// If click came from the button or timer isn't set, restart the timer
if (event || !timer) {
stopTimer();
timer = setInterval(showRemaining, 1000);
}
// Get the current date
var now = new Date();
// Get the value of countdown and parse it, see parsing function
// If end isn't set, set it
if (!end) end = parseDateDMY(document.getElementById("myDate").value);
var distance = end - now;
// If gone past end, stop the timer
if (distance < 0) {
stopTimer();
document.getElementById('countdown').innerHTML = 'EXPIRED!';
} else {
var months = Math.floor(distance / _month);
var days = Math.floor((distance % _month) / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
// Write the time remaining directly to the element
document.getElementById('countdown').innerHTML = months + 'months ' +
days + 'days ' +
hours + 'hrs ' +
minutes + 'mins ' +
seconds + 'secs';
}
}
// No need to do this, wait for button click
// timer = setInterval(showRemaining, 1000);
// Parse date string in format d/m/y
function parseDateDMY(s) {
var b = s.split(/\D/);
var d = new Date(b[2], --b[1], b[0]);
return d && d.getMonth() == b[1]? d : new Date(NaN);
}
// Add listener to button
window.onload = function() {
document.getElementById('startButton').addEventListener('click',showRemaining,false);
}
Enter your birthday:<br>
<input type="text" id="myDate" value="21/6/2016">d/m/y<br>
<input type="button" id="startButton" value="Start counting"><br>
<div id="countdown"></div>
You have made quite a few mistakes,
The script loads before the elements load. So, it does not work properly. Always incude scripts at the last or use window.onload = (function() { [Your code] }());. This executes only after the dom loads.
The setInterval function must always execute only if "not EXPIRED!". Keep it within the function so it only runs again if the countdown must go on.
The main problem, you were comparing date strings to 0. You can rather use
Date.now() which returns the total milliseconds from Jan 1, 1970. And use Date("User Input String which you provided") to get the total milliseconds from Jan 1, 1970 till that date and see the difference which is very accurate.
I recommend using separate input boxes or a more formatted input. Read more about these here.
Also try using 'buttonElement.addEventListener("click", showRemaining);`.
This should work:
<body>
<script>
var end = new Date();
document.getElementById("myDate").value = end;
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var _month = _day * 30;
var timer;
function showRemaining() {
var now = Date.now(); //CHANGE
end = new Date(document.getElementById("myDate").value); //CHANGE
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementById('countdown').innerHTML = 'EXPIRED!';
return;
}
var months = Math.floor(distance / _month);
var days = Math.floor((distance % _month) / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('countdown').innerHTML = months + 'months ';
document.getElementById('countdown').innerHTML += days + 'days ';
document.getElementById('countdown').innerHTML += hours + 'hrs ';
document.getElementById('countdown').innerHTML += minutes + 'mins ';
document.getElementById('countdown').innerHTML += seconds + 'secs';
timer = setInterval(showRemaining, 1000); //CHANGE
}
</script>
<!-- CHANGE -->
Enter your birthday:
<br />
<input type="date" id="myDate">
<br /><br />
<input type="button" onclick="showRemaining()" value="Enter">
This snippet fixes your issue. The issue was two-fold.
document.getElementById("myDate").value = end; This statement is reversed. You want need the value of the field to be put into end. This statement also executes immediately, which is of no use. This has been replaced by two things (1) the initDate function, to make the date field have an initial value (if that's what you were trying to do), and (2) the event listener on the button. This way, when the user has selected a date and clicks the button, you know that a value has been set, and can confidently start the timer.
Dates. The date value given by the input you have is in the format YYYY-mm-dd, which needs to be split() on the hyphens to create a new Date() correctly. The Date library can be tricky to work with. When creating dates it can be hard to determine if they're going to be UTC or local. And that issue can screw you up pretty easily, so watch that.
This code should be what you're looking for and should help clarify some of the points you may not have understood when writing the original code. It's not perfect necessarily (due to the fact that a month is hardcoded in as 30 days), but it depends on what you are looking for. Let me know if you have any other questions.
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var _month = _day * 30;
var timer;
initDate();
document.getElementById('startButton').addEventListener("click", function() {
document.getElementById('value').innerHTML = document.getElementById("myDate").value;
var splitValues = document.getElementById("myDate").value.split('-');
var end = new Date(splitValues[0], splitValues[1] - 1, splitValues[2]);
clearInterval(timer);
showRemaining(end);
timer = setInterval(showRemaining, 1000, end);
});
function showRemaining(end) {
var now = new Date();
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementById('countdown').innerHTML = 'EXPIRED!';
return;
}
var months = Math.floor(distance / _month);
var days = Math.floor((distance % _month) / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('countdown').innerHTML = months + 'months ';
document.getElementById('countdown').innerHTML += days + 'days ';
document.getElementById('countdown').innerHTML += hours + 'hrs ';
document.getElementById('countdown').innerHTML += minutes + 'mins ';
document.getElementById('countdown').innerHTML += seconds + 'secs';
}
function initDate() {
var defaultDate = new Date();
var month;
if(defaultDate.getMonth() + 1 > 9) {
month = "" + (defaultDate.getMonth() + 1);
} else {
month = '0' + (defaultDate.getMonth() + 1);
}
document.getElementById("myDate").value = defaultDate.getFullYear() + '-' + month + '-' + defaultDate.getDate();
}
<input id="myDate" type="date">
<button id="startButton">Start Countdown</button>
<div id="value"></div>
<div id='countdown'></div>
I have included the "more accurate" version below, since it was easy to change.
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var timer;
initDate();
document.getElementById('startButton').addEventListener("click", function() {
document.getElementById('value').innerHTML = document.getElementById("myDate").value;
var splitValues = document.getElementById("myDate").value.split('-');
var end = new Date(splitValues[0], splitValues[1] - 1, splitValues[2]);
clearInterval(timer);
showRemaining(end);
timer = setInterval(showRemaining, 1000, end);
});
function showRemaining(end) {
var now = new Date();
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementById('countdown').innerHTML = 'EXPIRED!';
return;
}
var days = Math.floor(distance / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('countdown').innerHTML = days + ' days ';
document.getElementById('countdown').innerHTML += hours + ' hrs ';
document.getElementById('countdown').innerHTML += minutes + ' mins ';
document.getElementById('countdown').innerHTML += seconds + ' secs';
}
function initDate() {
var defaultDate = new Date();
var month;
if (defaultDate.getMonth() + 1 > 9) {
month = "" + (defaultDate.getMonth() + 1);
} else {
month = '0' + (defaultDate.getMonth() + 1);
}
document.getElementById("myDate").value = defaultDate.getFullYear() + '-' + month + '-' + defaultDate.getDate();
}
<input id="myDate" type="date">
<button id="startButton">Start Countdown</button>
<div id="value"></div>
<div id='countdown'></div>
Right, basically I have a countdown timer that doesn't do exactly what it says on the tin.
The PHP outputs correctly, but once it's echo'd within the Javascript, the date constantly changes.
I will load the page, and it will show one ETA, and I'll refresh and it could jump forward an hour or jump back several hours?
I just need the timer to countdown to the 20th March 2015.
The PHP Code
<?php
$futureDate = '2015-03-20';
$d = new DateTime($futureDate);
?>
The Javascript
$('#counter').countdown({
timestamp : (new Date()).getTime() + <?php echo $d->diff(new DateTime())->format('%a*%h*%i*%s*1000'); ?>
});
Here's a Live Preview
Preview
Please, somebody help lol
you can use something like this in javascript
how to countdown to a date
var end = new Date('03/20/2015 0:0 AM');
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var timer;
function showRemaining() {
var now = new Date();
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementById('counter').innerHTML = 'EXPIRED!';
return;
}
var days = Math.floor(distance / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('counter').innerHTML = days + 'days ';
document.getElementById('counter').innerHTML += hours + 'hrs ';
document.getElementById('counter').innerHTML += minutes + 'mins ';
document.getElementById('counter').innerHTML += seconds + 'secs';
}
timer = setInterval(showRemaining, 1000);
Replace your javascript with
$('#counter').countdown({
timestamp : new Date('2015/03/20')
});
As it is now you're overcomplicating things - you just need to set the date of the countdown to when you want it to finish.
I am making a game with php mysql and jquery which involves finding out 5 differences in two images within 30 seconds. Everything works fine but some users are able to submit scores(time taken to find all 5 differences) like 0.008 seconds which is next to impossible even if you play the same image multiple times and touch the screen with all 5 fingers.
Any idea how this could be possible? Just theory wise. Below is the count down timer code.
var end = new Date();
var temp = new Date();
end.setSeconds(temp.getSeconds()+30);
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour *24;
var timer;
function showRemaining()
{
var now = new Date();
var distance = end - now;
if (distance < 0 ) {
}
var days = Math.floor(distance / _day);
var hours = Math.floor( (distance % _day ) / _hour );
var minutes = Math.floor( (distance % _hour) / _minute );
var seconds = Math.floor( (distance % _minute) / _second );
var milliseconds = Math.floor(distance % _second);
var countdownElement = document.getElementById('elapsed_time');
//countdownElement.innerHTML = seconds + ':' + milliseconds;
seconds=seconds+1;
//countdownElement.innerHTML = '00:' + seconds.toString();
var strmil = milliseconds.toString();
if(strmil.length==3){
strmil=strmil.substring(0, strmil.length - 1);
}
countdownElement.innerHTML = seconds + ':' + strmil;
if( seconds==0){
// handle expiry here..
clearInterval( timer ); // stop the timer from continuing ..
countdownElement.innerHTML = '00:00';
setTimeout(function(){
window.location='go to a page which shows the you timed out';
}, 1000);
}
}
if( $('#elapsed_time').length ){
timer = setInterval(showRemaining, 10);
}
Gathered from information the comments you gave me I think the problem is located where you perform your checks. The following probably happens in the application when this error occurs.
When the game starts it starts the timer.
The application then constantly checks if the differences have been found yet
An error occurs here and the application instantly receives that all the differences have been found.
The game stops the timer and shows the victory popup with around 0.001-0.008 seconds.
This entire process takes around 0.001-0.008 seconds which explains the score.
So you should probably check for the bug in the part where it checks the differences. The code you posted works fine and the bug is not found there.
Keep browser compatibility issues in mind, maybe the bug only occurs on certain browsers.
The following script counts down but it won't stop counting when it reaches the end time.
When it reaches zero, it start again from 60:00 to 0 (another hour).
When i skip the part
$time = str_replace(' ', 'T', $db[time]);
and do it like this:
var end = new Date('<?=$db[time]?>');
The counter is stopping correctly, but then the counter wont work at IE or Firefox only in Chrome.
Anyone know how to stop this counter:S Thanx!
$db[time] = Timestamp field in the database (2013-10-03 11:32:39)
The Script:
$time = str_replace(' ', 'T', $db[time]);
Java script
<script>
var end = new Date('<?=$time?>');
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var timer;
function showRemaining() {
var now = new Date();
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementById('countdown').innerHTML = 'ITS NOW TIME!</font><BR><BR>';
return;
}
var days = Math.floor(distance / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('countdown').innerHTML = '<font color="orange">' + minutes + ':';
document.getElementById('countdown').innerHTML += '<font color="orange">' + seconds + ' minutes</font>';
}
timer = setInterval(showRemaining, 1000);
</script>
I suggest you use
var countInterval = setInterval(function() { countdown(secondsRemaining); },1000) instead.
This way you won't have to play around with Date or Time objects. Just keep a count inside countdown() and clearInterval(countInterval) once you reach 60.
I'm a little suspicious of your innerHTML usage. Where is this script located in the HTML? I have a feeling it's getting re-evaluated after setting innerHTML. You could test the theory by putting a console.log("Started!") statement next to setInterval.
Also, look here:
document.getElementById('countdown').innerHTML = 'ITS NOW TIME!</font><BR><BR>';
You're "setting" (replacing) the innerHTML of an element so it will contain: text, and then a close-font tag. That might mess up your DOM. Finally, you shouldn't be setting innerHTML twice in two lines - set it once in a function, perhaps based on a variable.
(To clarify: Using innerHTML on its own isn't the worst thing - but with malformed HTML, or by adjusting an element too high in the heirarchy, it can have unintended effects)
Is it possible to use this script with server time instead of client time. (For checking if time is past) It now uses client time and thats a problem. (Maybe with php??)
<script>
var end = new Date('02/19/2012 10:1 AM');
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var timer;
function showRemaining() {
var now = new Date();
var distance = end - now;
if (distance < 0) {
clearInterval(timer);
document.getElementById('countdown').innerHTML = 'EXPIRED!';
return;
}
var days = Math.floor(distance / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('countdown').innerHTML = days + 'days ';
document.getElementById('countdown').innerHTML += hours + 'hrs ';
document.getElementById('countdown').innerHTML += minutes + 'mins ';
document.getElementById('countdown').innerHTML += seconds + 'secs';
}
timer = setInterval(showRemaining, 1000);
</script>
<div id="countdown"></div>
You can get time from ajax request, or use something like this:
<?php
$now = date('d-m-Y');
$end= "01-01-2013"
$date = strtotime($end) - strtotime($now);
$days = date('d', $date);
$monthes= date('m', $date);
$years= date('Y', $date);
?>
<script>
var days = "<?= $days ?>";
var monthes= "<?= $monthes?>";
var years= "<?= $years?>";
document.getElementById('countdown').innerHTML = days+ ' days';
document.getElementById('countdown').innerHTML += monthes+ ' monthes';
document.getElementById('countdown').innerHTML += years+ ' years';
</script>
Puku's answer will return a fixed date, instead of server time. He seems to have fixed it.
I propose:
<script>
var date = <? echo time(); ?>;
// etc...
</script>
This will fetch the amount of (server) seconds since the Unix epoch IIRC and stuff it in the variable 'date' as an int. Note everything between <? and ?> is PHP and thus executed on the server.
Note I didn't use abbreviated syntax, like puku. I don't have it by default and I can't change that, so I thought it'd be nice to use this notation for those with the same problem.
Found an example similar with Ajax at http://www.roseindia.net/ajax/ajax-first-example.shtml
[UPDATE] After comments stating my previous post this didn't work, i've reviewed everying and changed the JavaScript and PHP file (giving full code now). This code now works. I've tried to keep it as similar as possible to the original example and the link previously provided instead of optimizing things (I'll leave that to you).
<script>
var end = new Date('02/19/2014 10:1 AM');
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var timer;
var distance;
function startShowRemaining(strnow) {
var now = new Date(strnow);
distance = end - now;
//To prevent 1 sec. lag, we make first a direct call to showRemaining
showRemaining();
//Then each second, we decrement count and show info
timer = setInterval(countRemaining, 1000);
}
function countRemaining() {
distance = distance - 1000; //we substract a second (1000 ms) with each call
showRemaining();
}
function showRemaining() {
if (distance < 0) {
clearInterval(timer);
document.getElementById('countdown').innerHTML = 'EXPIRED!';
return;
}
var days = Math.floor(distance / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
document.getElementById('countdown').innerHTML = days + ' days ';
document.getElementById('countdown').innerHTML += hours + ' hrs ';
document.getElementById('countdown').innerHTML += minutes + ' mins ';
document.getElementById('countdown').innerHTML += seconds + ' secs';
}
function postRequest(strURL) {
var xmlHttp;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
var xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttp.open('POST', strURL, true);
xmlHttp.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
startShowRemaining(xmlHttp.responseText);
}
}
xmlHttp.send(strURL);
}
postRequest('time.php');
</script>
<div id="countdown"></div>
And create file: time.php
<?php
print date("d/m/Y H:i:s");
?>
PHP file is called once to get current date, then the "distance" var is decremented each second to prevent further Ajax calls that uses bandwidth and... can take more than one second anyway. A different function for decrementing is used, so we can call showRemaining immediatly without decrementing it (You could also start increasing 1000 in the first call and use only one function..).
Anyway I prefer Puku approach to just use PHP to write the right value for the "now" var, it is simpler. This one is nice only as an example of Ajax use.