Javascript Countdown with PHP - javascript

I want to have a countdown associated with a particular button on my PHP page and i am using following code based on javascript
But,it resets the target value on page reload,so how to have the same without the target value getting reset.Can i do something with session ??
<html>
<body>
<p>Time remaining: <span id="countdownTimer"><span>00:00.<small>00</small></span></p>
<script type="text/javascript">
if (document.getElementById('countdownTimer')) {
pad = function(n, len) { // leading 0's
var s = n.toString();
return (new Array( (len - s.length + 1) ).join('0')) + s;
};
function countDown() {
var now = new Date();
if ( (now.getDay() >= 0) && (now.getDay() <= 6) ) { // Monday to Friday only
var target = 23; // 15:00hrs is the cut-off point
if (now.getHours() < target) { // don't do anything if we're past the cut-off point
var hrs = (target - 1) - now.getHours();
if (hrs < 0) hrs = 0;
var mins = 59 - now.getMinutes();
if (mins < 0) mins = 0;
var secs = 59 - now.getSeconds();
if (secs < 0) secs = 0;
var str = pad(hrs, 2) + ':' + pad(mins, 2) + '.<small>' + pad(secs, 2) + '</small>';
document.getElementById('countdownTimer').innerHTML = str;
}
}
}
var timerRunning = setInterval('countDown()', 1000);
}
</script>
</body>
</html>

Instead of evaluating your variable 'now' as such:
var now = new Date();
Evaluate it like this (assuming our browser supports LocalStorage):
if (!localStorage.myDate)
localStorage.myDate = (new Date()).toString();
var now = new Date(localStorage.myDate);
This way, we only ever evaluate the current date on first load. After that, we refer to a serialized string version of that date and pass that as an argument when we create our 'now' variable.
If we want to support older browser (cough IE), we can use userData or simply do something very similar with cookies.

So essentially, you want to capture 'now' once, and not have that change, correct?
function getNow(){ //call this rather than use var now = new Date();
if (window.localStorage){
if (!localStorage.now){
localStorage.now = new Date();
}
return localStorage.now;
}else{
return new Date();
}
}
Pardon if I've got a bit of syntax out (I'm not sure if you'd have to convert a date to store it in localStorage), but that's the gist of it. For IE7 and below support you'd need to use cookies, but the concept remains the same.
Also, I think you have a mistake in:
if ( (now.getDay() >= 0) && (now.getDay() <= 6) )
That will always be true, try:
if ( (now.getDay() > 0) && (now.getDay() < 6) )

Related

A dynamic delivery time counter for WooCommerce as a shortcode

I've created a shortcode for Wordpress using a javascript counter.
Back End - Counter works fine:
Front End - Counter doesn't work (no console errors...):
My code for the shortcode:
// Delivery Counter Time
function bb__delivery_counter_function() {
?>
<script type='text/javascript'>
if (document.getElementById('countdownTimer')) {
pad = function(n, len) { // leading 0's
var s = n.toString();
return (new Array( (len - s.length + 1) ).join('0')) + s;
};
var timerRunning = setInterval(
function countDown() {
var target = 12; // 12:00hrs is the cut-off point
var now = new Date();
//Put this in a variable for convenience
var weekday = now.getDay();
if(weekday == 0){//Sunday? Add 24hrs
target += 24;
}//keep this before the sunday
if(weekday == 6){//It's Saturday? Add 48hrs
target += 48;
}
//If between Monday and Friday,
//check if we're past the target hours,
//and if we are, abort.
if((weekday>=1) && (weekday<=5)){
if (now.getHours() > target) { //stop the clock
target += 24;
}
}
var hrs = (target - 1) - now.getHours();
if (hrs < 0) hrs = 0;
var mins = 59 - now.getMinutes();
if (mins < 0) mins = 0;
var secs = 59 - now.getSeconds();
if (secs < 0) secs = 0;
var str = pad(hrs, 2) + ':' + pad(mins, 2) + '.<small>' + pad(secs, 2) + '</small>';
document.getElementById('countdownTimer').innerHTML = str;
}, 1000
);
}
</script>
<?php
return '<div id="countdownTimer"></div>';
}
add_shortcode('bb__delivery_counter', 'bb__delivery_counter_function');
When I add the shortcode in Elementor theme everything works fine in the "back end" so the counter counts in the Elementor Admin view.
But if I try to access the page through the front end, the Javascript doesn't work. Any ideas why this is happening?
There are some mistakes in your code. You need to buffer the Javascript to return it as it should be for a shortcode and now JS wait until DOM is loaded using jQuery (as jQuery library is already loaded in WordPress/WooCommerce). Also I have simplified a bit your code:
// Delivery Counter Time
add_shortcode('bb__delivery_counter', 'shortcode_delivery_counter_func');
function shortcode_delivery_counter_func() {
ob_start(); // Start buffering
?>
<script type='text/javascript'>
jQuery(function($) {
function pad(n, len) { // leading 0's
var s = n.toString();
return (new Array( (len - s.length + 1) ).join('0')) + s;
};
setInterval( function() {
var target = 12, // 12:00hrs is the cut-off point
now = new Date(),
weekday = now.getDay();
if (weekday == 6) { // On Saturday: Adds 48hrs
target += 48;
}
// On sundays | And from monday to Friday after the cut-off : Adds 24hrs
else if ( weekday == 0 || now.getHours() > target ) {
target += 24;
}
var hrs = (target - 1) - now.getHours(),
mins = 59 - now.getMinutes(),
secs = 59 - now.getSeconds();
if (hrs < 0) hrs = 0;
if (mins < 0) mins = 0;
if (secs < 0) secs = 0;
$('#countdownTimer').html( pad(hrs, 2) + ':' + pad(mins, 2) + '.<small>' + pad(secs, 2) + '</small>' );
}, 1000 );
});
</script>
<?php
return '<div id="countdownTimer"></div>' . ob_get_clean(); // return buffered JS with html
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

SCORM 1.2 Javascript functions

I am working with Adobe Captivate to create as simple SCORM compliant package. The requirement is that I need to track only the time (total_time) that the user (the learner) is viewing a video.
I have striped the media playback on the page and inserted two buttons. One to start playing the video and another to pause it. I am now looking for a javascript function that I can call in order to start the time, (on the page load and the click of the PLAY button and stop it on the PAUSE.
Does such a command exist and is this the best way to do this?
Thanks
While I don't have a Captivate course to test this out on, I used some documentation about the SCORM code for captivate
I created four functions - one when the movie is started, one when paused, one when the course is about to be closed and the time needs to be calculated and one that formats the time for scorm which is a simple HH:MM:SS.S. format.
Note: that you mentioned total_time or cmi.core.total_time, this is a read only
attribute, a course should send the session time and the LMS computes the
cmi.core.total_time
References: see here or
here (scroll until you see cmi.core.session_time)
Add the following code at the end of the script tag:
var mod_elapsedSeconds = 0;
var mod_startTime;
function sco_start(){
if ( mod_startTime != 0 )
{
var currentDate = new Date().getTime();
mod_elapsedSeconds += ( (currentDate - mod_startTime) / 1000 );
}
mod_startTime = new Date().getTime();
}
function sco_pause(){
if ( mod_startTime != 0 )
{
var currentDate = new Date().getTime();
mod_elapsedSeconds += ( (currentDate - mod_startTime) / 1000 );
}
mod_startTime = 0;
}
function onB4LMSFinish(){
if ( mod_startTime != 0 )
{
var currentDate = new Date().getTime();
mod_elapsedSeconds += ( (currentDate - mod_startTime) / 1000 );
var formattedTime = convertTotalSeconds( mod_elapsedSeconds );
}
else
{
formattedTime = "00:00:00.0";
}
Captivate_DoFSCommand( "cmi.core.session_time", formattedTime );
}
function convertTotalSeconds(ts)
{
var sec = (ts % 60);
ts -= sec;
var tmp = (ts % 3600); //# of seconds in the total # of minutes
ts -= tmp; //# of seconds in the total # of hours
// convert seconds to conform to CMITimespan type (e.g. SS.00)
sec = Math.round(sec*100)/100;
var strSec = new String(sec);
var strWholeSec = strSec;
var strFractionSec = "";
if (strSec.indexOf(".") != -1)
{
strWholeSec = strSec.substring(0, strSec.indexOf("."));
strFractionSec = strSec.substring(strSec.indexOf(".")+1, strSec.length);
}
if (strWholeSec.length < 2)
{
strWholeSec = "0" + strWholeSec;
}
strSec = strWholeSec;
if (strFractionSec.length)
{
strSec = strSec+ "." + strFractionSec;
}
if ((ts % 3600) != 0 )
var hour = 0;
else var hour = (ts / 3600);
if ( (tmp % 60) != 0 )
var min = 0;
else var min = (tmp / 60);
if ((new String(hour)).length < 2)
hour = "0"+hour;
if ((new String(min)).length < 2)
min = "0"+min;
var rtnVal = hour+":"+min+":"+strSec;
return rtnVal;
}
Change the tag that looks something like this:
<body bgcolor="#f5f4f1" onunload="Finish();">
to:
<body bgcolor="#f5f4f1" onunload="onB4LMSFinish();Finish();">
Add these functions to your start and pause buttons:
sco_start(); // for starting the video
sco_pause(); // for pausing
As I mentioned, I don't have the captivate course code. If you posted that somewhere, I could help you further.

Javascript countdown timer can't set half past hour

I'm trying to use a countdown timer to count to a certain time everyday (monday to friday). So far everything works, except it can only be set to count to a certain hour (based on the 24 hour clock) without a half hour included. So for example, if I wanted to count to 4PM, I'd set var target = 16; but if I wanted 4:30 and I tried to set var target = 1630; it doesn't work. Unfortunately I don't have much experience with javascript, but I believe the problem is either with the way it's evaluating the target time using the getHours function but not sure where to take it from there.
if (document.getElementById('countdownTimer')) {
pad = function(n, len) { // leading 0's
var s = n.toString();
return (new Array( (len - s.length + 1) ).join('0')) + s;
};
function countDown() {
var now = new Date();
if ( (now.getDay() >= 1) && (now.getDay() <= 5) ) { // Monday to Friday only
var target = 15; // 15:00hrs is the cut-off point
if (now.getHours() < target) { // don't do anything if we're past the cut-off point
var hrs = (target - 1) - now.getHours();
if (hrs < 0) hrs = 0;
var mins = 59 - now.getMinutes();
if (mins < 0) mins = 0;
var secs = 59 - now.getSeconds();
if (secs < 0) secs = 0;
var str = pad(hrs, 2) + ':' + pad(mins, 2) + '.<small>' + pad(secs, 2) + '</small>';
document.getElementById('countdownTimer').innerHTML = str;
}
}
}
var timerRunning = setInterval('countDown()', 1000);
}
If you're ok with considering another method, the following javascript will count down (in seconds) to any date in the future (and count up after the date has passed).
// new Date(year, month, day, hours, minutes, seconds, milliseconds)
var target = new Date(2014, 0, 30, 12, 30, 0, 0)
function countdown(id, targetDate){
var today = new Date()
targetDate.setDate(today.getDate())
targetDate.setFullYear(today.getFullYear())
targetDate.setMonth(today.getMonth())
var diffMillis = targetDate - today
if (diffMillis >= 0){
document.getElementById(id).innerHTML = millisToString(diffMillis)
}
}
setInterval(function(){countdown('seconds', target)},1000)
It uses the javascript date object, so you can literally use any date.
Updated example to do:
format the countdown using hours:minutes:seconds etc
stop the timer after the date is reached
Updated: updated code to override the targetDate to today's date.
Example: http://jsfiddle.net/kKx7h/5/
For 4:30PM, try var target = 16.5 instead of var target = 1630;
You now need to add another variable for the minutes. We can have target as an object literal rather than declare two variables for time:
var target={hour: 15, minute:30};
if ( (now.getHours() < target.hour) && () now.getMinutes() < target.minute ){

How to work out time difference between two times on a 24 hour clock

I have a problem with some code I have been producing in JavaScript. I want to calculate the difference between two times on a 24 hour clock. The data comes from two input time fields:
<input type="time" id="start" />
<input type="time" id="end" />
Because of this the times come in a string 00:00, which doesn't help for number calculations.
The way I worked it out was to minus the start from the end. This works perfectly if the the end time is greater, however if the end time is past 11:00 (00:00), I end up with a negative number. I have tried adding 24 to the result if the end is lower than the start but I still get a negative number. This may seem like a dumb question but I was never that good at maths.
var numHours;
if(time_end < time_start){
numHours = parseInt(t_e.substring(0,2)) - parseInt(t_s.substring(0,2)) + 24;
}else{
numHours = parseInt(t_e.substring(0,2)) - parseInt(t_s.substring(0,2));
}
There is probably (definitely) a better way of doing this but how can I get this to work. Also could I calculate the minutes as well to get more accurate time difference.
The solutions provided aren't accounting for the day boundary effectively. And all of this assumes the difference is less than 24 hours. Meaning that we have an upper boundary on the difference between start and end of 23 hours and 59 minutes, otherwise we are confused by the result. But remember that as described a real use case is that an event starts at 11pm and ends at 1am (from 23:00 to 1:00) and the difference is 2 hours NOT 22 hours.
function calculateTime(e) {
var startTime = $('#start').val();
var endTime = $('#end').val();
var startTimeArray = startTime.split(":");
var startInputHrs = parseInt(startTimeArray[0]);
var startInputMins = parseInt(startTimeArray[1]);
var endTimeArray = endTime.split(":");
var endInputHrs = parseInt(endTimeArray[0]);
var endInputMins = parseInt(endTimeArray[1]);
var startMin = startInputHrs*60 + startInputMins;
var endMin = endInputHrs*60 + endInputMins;
var result;
if (endMin < startMin) {
var minutesPerDay = 24*60;
result = minutesPerDay - startMin; // Minutes till midnight
result += endMin; // Minutes in the next day
} else {
result = endMin - startMin;
}
var minutesElapsed = result % 60;
var hoursElapsed = (result - minutesElapsed) / 60;
alert ( "Elapsed Time : " + hoursElapsed + ":" + (minutesElapsed < 10 ?
'0'+minutesElapsed : minutesElapsed) ) ;
}
And I didn't check, but I believe you could just do this, but I'm not checking it :
var result = endMin - startMin;
if (result < 0 ) result = (24*60) + result;
A simple solution that might work best for this limited use-case is to convert both times into total minutes since the start of the day, and then subtract.
Pseudocode:
startMin = startInputHrs * 60 + startInputMin
endMin = endInputHrs * 60 + endInputMin
timeDifference = endMin - startMin
It's up to you how you want to handle a negative result. Maybe give the user an error message, and tell them that the start time has to come before the end time?
I'm a beginner, and some whiz is probably going to come up with an answer in like 2 lines :), but here it is.....this works. input is a string in the form of "1:20pm-2:30am".
function CountingMinutesI(str) {
split = str.split('-')
startTime = split[0]
endTime = split[1]
// for end time
if (endTime === '12:00am') { endInMinutes = 0}
else if (endTime.charAt(endTime.length-2) === 'a') {
if (endTime.substr(0, 2) === '12') {
endInMinutes = parseInt(endTime.split(':')[1].replace(/[a-z]/gi, ''))
}
else {
endHours = endTime.split(':')[0]
endMins = endTime.split(':')[1].replace(/[a-z]/gi, '')
endInMinutes = (parseInt(endHours)*60) + parseInt(endMins)
}
}
else if (endTime === '12:00pm') {endInMinutes = 720}
else {
endHours = endTime.split(':')[0]
endMins = endTime.split(':')[1].replace(/[a-z]/gi, '')
endInMinutes = (parseInt(endHours)*60 + 720) + parseInt(endMins)
}
// for start time
if (startTime === '12:00am') { startInMinutes = 0}
else if (startTime.charAt(startTime.length-2) === 'a') {
if (startTime.substr(0, 2) === '12') {
startInMinutes = parseInt(startTime.split(':')[1].replace(/[a-z]/gi, ''))
}
else {
startHours = startTime.split(':')[0]
startMins = startTime.split(':')[1].replace(/[a-z]/gi, '')
startInMinutes = (parseInt(startHours)*60) + parseInt(startMins)
}
}
else if (startTime.substr(0,2) === '12') {startInMinutes = 720 + parseInt(startTime.split(':')[1].replace(/[a-z]/gi, ''))}
else {
startHours = startTime.split(':')[0]
startMins = startTime.split(':')[1].replace(/[a-z]/gi, '')
startInMinutes = (parseInt(startHours)*60 + 720) + parseInt(startMins)
}
if (endInMinutes > startInMinutes) {output = endInMinutes - startInMinutes}
else {output = 1440 - (startInMinutes - endInMinutes)}
return output
}

Javascript clock based on custom time

I am using the following script below, and what I am trying to do is to set a custom time to the script and for it to auto update without the need to re-set the time each time. (I only want to set the time once and want my script to keep track of the time and display it)
When I run the script it displays: NaN:NaN:NaN AM
My Code is as follows:
<div id="js_clock"> display clock here </div>
<script language="javascript">
function js_clock(clock_time)
{
var clock_hours = clock_time.getHours();
var clock_minutes = clock_time.getMinutes();
var clock_seconds = clock_time.getSeconds();
var clock_suffix = "AM";
if (clock_hours > 11){
clock_suffix = "PM";
clock_hours = clock_hours - 12;
}
if (clock_hours == 0){
clock_hours = 12;
}
if (clock_hours < 10){
clock_hours = "0" + clock_hours;
}
if (clock_minutes < 10){
clock_minutes = "0" + clock_minutes;
}
if (clock_seconds < 10){
clock_seconds = "0" + clock_seconds;
}
var clock_div = document.getElementById('js_clock');
clock_div.innerHTML = clock_hours + ":" + clock_minutes + ":" + clock_seconds + " " + clock_suffix;
setTimeout("js_clock()", 1000);
}
var serverTime = new Date("09:20:50");
js_clock(serverTime);
</script>
You have a problem creating the date, new Date("09:20:50"); returns Invalid Date.
if you want to set hours minutes and seconds use
new Date(year, month, day [, hour, minute, second, millisecond ])
or take a look here.
Also you forgot to pass a date to the setTimeout, try:
setTimeout(function() {
js_clock(new Date(/*pass hours minutes and seconds here*/))
}, 1000);
I think you've forgotten passing an argument to js_clock(). Maybe you shoud do:
setTimeout(
function() {
//Call the function again updating seconds by 1
js_clock(
new Date(
clock_time.getFullYear(),
clock_time.getMonth(),
clock_time.getDate(),
clock_time.getHours(),
clock_time.getMinutes(),
clock_time.getSeconds() + 1
)
);
},
1000
);
EDIT:
I missed the point this can be done with a single function call:
setTimeout(
function() {
js_clock(new Date(+clock_time + 1000));
},
1000
);
The +clock_time statement converts the Date object to milliseconds from the UNIX Epoch, so updating the time is as simple as summing 1000 milliseconds.
Thanks to user RobG ;-)
Your code has some serious flaws, such as the following.
setTimeout doesn't run at exactly the interval set, but as soon as it can afterward so this clock will slowly drift, sometimes by a lot.
Passing a string to Date and expecting it to be correctly parsed is problematic. In ECMA-262 ed 3 it was entirely implementation dependent, in ES5 the string is required to be a custom version of the ISO8601 long format (but note that not all browsers in use support ES5).
Lastly, if the client is busy, the function may not run for several seconds so the clock needs to be based on the client clock, then ajusted for the time difference.
The following function does all the above.
<script type="text/javascript">
var customClock = (function() {
var timeDiff;
var timeout;
function addZ(n) {
return (n < 10? '0' : '') + n;
}
function formatTime(d) {
return addZ(d.getHours()) + ':' +
addZ(d.getMinutes()) + ':' +
addZ(d.getSeconds());
}
return function (s) {
var now = new Date();
var then;
// Set lag to just after next full second
var lag = 1015 - now.getMilliseconds();
// Get the time difference if first run
if (s) {
s = s.split(':');
then = new Date(now);
then.setHours(+s[0], +s[1], +s[2], 0);
timeDiff = now - then;
}
now = new Date(now - timeDiff);
document.getElementById('clock').innerHTML = formatTime(now);
timeout = setTimeout(customClock, lag);
}
}());
window.onload = function() {
customClock('09:20:50');
}
</script>
<div id="clock"></div>
WAIT! just realised, this is still not showing the correct time. The error is gone, but the time isn't what you are looking for.
window.js_clock = function js_clock(clock_time) {
var clock_hours = clock_time.getHours();
var clock_minutes = clock_time.getMinutes();
var clock_seconds = clock_time.getSeconds();
var clock_suffix = "AM";
if (clock_hours > 11) {
clock_suffix = "PM";
clock_hours = clock_hours - 12;
}
if (clock_hours === 0) {
clock_hours = 12;
}
if (clock_hours < 10) {
clock_hours = "0" + clock_hours;
}
if (clock_minutes < 10) {
clock_minutes = "0" + clock_minutes;
}
if (clock_seconds < 10) {
clock_seconds = "0" + clock_seconds;
}
var clock_div = document.getElementById('js_clock');
clock_div.innerHTML = clock_hours + ":" + clock_minutes + ":" + clock_seconds + " " + clock_suffix;
setTimeout("js_clock(new Date())", 1000);
}
var serverTime = new Date("09:20:50");
window.js_clock(serverTime);​

Categories

Resources