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.
Related
Is you'll probably be able to tell I'm a complete JS rookie but I've spent my day working on this code to display a shipping timer, compiled from bits of various other posts on SO (thanks!).
It seemed to be going well until I completed adding all the functionality I needed and now it's not working. When you first run the snippet it works correctly but as soon as it ticks the "day" value displays incorrectly (it should display 'tomorrow' but it switches to 'today') and the timer itself has stopped counting down.
I can't figure out for the life of me where I messed it up so looking for some assistance if possible! Thanks in advance.
JSFiddle: http://jsfiddle.net/c3otusv6/
(function() {
var start = new Date();
start.setHours(14, 0, 0);
var maybePluralize = function maybePluralize(count, noun) {
var suffix = arguments.length <= 2 || arguments[2] === undefined ? 's' : arguments[2];
return count + ' ' + noun + (count !== 1 ? suffix : '');
};
var now = new Date();
var day = now.getDay();
function tick() {
if (day >= 1 && day <= 5 && now < start) {
document.getElementById('ddate').innerHTML = 'today';
} else if (day >= 1 && day <= 4 && now >= start || day == 7) {
document.getElementById('ddate').innerHTML = 'tomorrow';
} else if (day == 5 && now >= start || day == 6) {
document.getElementById('ddate').innerHTML = 'Monday';
}
if (day == 6 || day == 5 && now > start || day == 7 && now < start) {
document.getElementById('countdown').innerHTML = "now";
} else {
if (now > start) { // too late, go to tomorrow
start.setDate(start.getDate() + 1);
}
var remain = (start - now) / 1000;
var hh = Math.floor(remain / 60 / 60 % 60);
var mm = Math.floor(remain / 60 % 60);
document.getElementById('countdown').innerHTML = "in the next <strong>" + maybePluralize(hh, 'hour') + " " + maybePluralize(mm, 'min') + "</strong>";
setTimeout(tick, 1000);
}
}
document.addEventListener('DOMContentLoaded', tick);
})();
If you need to have the function called every second, you need to use setInterval. setTimeout just runs the given function once after the specified number of seconds.
I have made small edit to you fiddle, to make it run every second.
As for the "day" value being incorrect, I think you need to check your if statements. I quite dont understand your business logic.
Also note - Sunday is given by '0' in getDay. And I see you using day == 7, so you might want to check that and do the necessary adjustments. I guess you need to -1 from all your if statements for day.
http://jsfiddle.net/wm9kj8yb/
(function() {
var start = new Date();
var now = new Date();
var day = now.getDay();
start.setHours(14, 0, 0);
function maybePluralize(count, noun) {
var suffix = arguments.length <= 2 || arguments[2] === undefined ? 's' : arguments[2];
return count + ' ' + noun + (count !== 1 ? suffix : '');
};
function tick() {
now = new Date();
day = now.getDay();
if (day >= 1 && day <= 5 && now < start) {
document.getElementById('ddate').innerHTML = 'today';
} else if (day >= 1 && day <= 4 && now >= start || day == 7) {
document.getElementById('ddate').innerHTML = 'tomorrow';
} else if (day == 5 && now >= start || day == 6) {
document.getElementById('ddate').innerHTML = 'Monday';
}
if (day == 6 || day == 5 && now > start || day == 7 && now < start) {
document.getElementById('countdown').innerHTML = "now";
} else {
if (now > start) { // too late, go to tomorrow
start.setDate(start.getDate() + 1);
}
var remain = (start - now) / 1000;
var ss = Math.floor(remain % 60);
remain = Math.floor(remain / 60);
var mm = remain % 60;
remain = Math.floor(remain / 60);
var hh = remain % 60;
document.getElementById('countdown').innerHTML = "in the next <strong>" + maybePluralize(hh, 'hour') + " " + maybePluralize(mm, 'min') + " " + " " + maybePluralize(ss, 'sec') + "</strong>";
}
}
document.addEventListener('DOMContentLoaded', function() {
setInterval(tick, 1000);
});
})();
Order <span id='countdown'></span> for dispatch <span id='ddate'></span>
I have a countdown script that enables me to see how much time there is left until a specific date and time in any given timezone. The script has improved alot from its original state (Much thanks to this community) but it still has some flaws.
The script is currently only able to countdown to a specific hour (Like 2015/12/12 18:00) but NOT to a specific minute (Like 2015/12/12 18:25).
I would like to be able to also specify any given minute of the hour (var minute), but I dont know how. Would greatly apreciate if anyone could help me out.
Edit: The timezone variable (var tz) must be taken into account.
Edit2: Solved the issue I got with the first answer, with this: toDate.setMinutes(minutes-(tz*60));
Full script below:
////////// CONFIGURE THE COUNTDOWN SCRIPT HERE //////////////////
var month = '11'; // '*' for next month, '0' for this month or 1 through 12 for the month
var day = '10'; // Offset for day of month day or + day
var hour = 14; // 0 through 23 for the hours of the day
var tz = -5; // Offset for your timezone in hours from UTC
var lab = 'tzcd'; // The id of the page entry where the timezone countdown is to show
function start() {displayTZCountDown(setTZCountDown(year,month,day,hour,tz),lab);}
// ** The start function can be changed if required **
window.onload = start;
////////// DO NOT EDIT PAST THIS LINE //////////////////
function setTZCountDown(year,month,day,hour,tz)
{
// props to Luke Woodward at Stackoverflow
var now = new Date();
var countdownToYear = now.getFullYear();
var countdownToMonth = now.getMonth();
var countdownToDay = now.getDate();
if (month === '*') {
countdownToMonth += 1;
} else if (month > 0) {
if (month <= now.getMonth()) {
countdownToYear += 1;
}
countdownToMonth = month - 1;
}
if (day.substr(0,1) === '+') {
var day1 = parseInt(day.substr(1), 10);
countdownToDay += day1;
} else {
countdownToDay = day;
}
var toDate = new Date(countdownToYear, countdownToMonth, countdownToDay);
// props to Luke Woodward at Stackoverflow^
toDate.setHours(hour);
toDate.setMinutes(0-(tz*60));
toDate.setSeconds(0);
var fromDate = new Date();
fromDate.setMinutes(fromDate.getMinutes() + fromDate.getTimezoneOffset());
var diffDate = new Date(0);
diffDate.setMilliseconds(toDate - fromDate);
return Math.floor(diffDate.valueOf()/1000);
}
function displayTZCountDown(countdown,tzcd)
{
if (countdown < 0) document.getElementById(tzcd).innerHTML = "<li>0<br><span class='tzcd-format'>day</span></li><li>0<br><span class='tzcd-format'>hours</span></li><li>0<br><span class='tzcd-format'>minutes</span></li><li>0<br><span class='tzcd-format'>seconds</span></li>";
else {var secs = countdown % 60;
if (secs < 10) secs = '0'+secs;
var countdown1 = (countdown - secs) / 60;
var mins = countdown1 % 60;
if (mins < 10) mins = '0'+mins;
countdown1 = (countdown1 - mins) / 60;
var hours = countdown1 % 24;
var days = (countdown1 - hours) / 24;
document.getElementById(tzcd).innerHTML = "<li>" + days + "<br><span class='tzcd-format'>day" + (days == 1 ? '' : 's') + '</span></li>' + "<li>" + hours + "<br><span class='tzcd-format'>hours</span></li> " + "<li>" + mins + "<br><span class='tzcd-format'>minutes</span></li>" +"<li>"+secs+ "<br><span class='tzcd-format'>seconds</span></li>";
setTimeout('displayTZCountDown('+(countdown-1)+',\''+tzcd+'\');',999);
}
}
I wasn't able to test it but this should be it:
////////// CONFIGURE THE COUNTDOWN SCRIPT HERE //////////////////
var month = '11'; // '*' for next month, '0' for this month or 1 through 12 for the month
var day = '10'; // Offset for day of month day or + day
var hour = 14; // 0 through 23 for the hours of the day
var tz = -5; // Offset for your timezone in hours from UTC
var minutes = '10';
var lab = 'tzcd'; // The id of the page entry where the timezone countdown is to show
function start() {displayTZCountDown(setTZCountDown(year,month,day,hour,tz),lab);}
// ** The start function can be changed if required **
window.onload = start;
////////// DO NOT EDIT PAST THIS LINE //////////////////
function setTZCountDown(year,month,day,hour,tz)
{
// props to Luke Woodward at Stackoverflow
var now = new Date();
var countdownToYear = now.getFullYear();
var countdownToMonth = now.getMonth();
var countdownToDay = now.getDate();
if (month === '*') {
countdownToMonth += 1;
} else if (month > 0) {
if (month <= now.getMonth()) {
countdownToYear += 1;
}
countdownToMonth = month - 1;
}
if (day.substr(0,1) === '+') {
var day1 = parseInt(day.substr(1), 10);
countdownToDay += day1;
} else {
countdownToDay = day;
}
var toDate = new Date(countdownToYear, countdownToMonth, countdownToDay);
// props to Luke Woodward at Stackoverflow^
toDate.setHours(hour);
toDate.setMinutes(minutes);
toDate.setSeconds(0);
var fromDate = new Date();
fromDate.setMinutes(fromDate.getMinutes() + fromDate.getTimezoneOffset());
var diffDate = new Date(0);
diffDate.setMilliseconds(toDate - fromDate);
return Math.floor(diffDate.valueOf()/1000);
}
function displayTZCountDown(countdown,tzcd)
{
if (countdown < 0) document.getElementById(tzcd).innerHTML = "<li>0<br><span class='tzcd-format'>day</span></li><li>0<br><span class='tzcd-format'>hours</span></li><li>0<br><span class='tzcd-format'>minutes</span></li><li>0<br><span class='tzcd-format'>seconds</span></li>";
else {var secs = countdown % 60;
if (secs < 10) secs = '0'+secs;
var countdown1 = (countdown - secs) / 60;
var mins = countdown1 % 60;
if (mins < 10) mins = '0'+mins;
countdown1 = (countdown1 - mins) / 60;
var hours = countdown1 % 24;
var days = (countdown1 - hours) / 24;
document.getElementById(tzcd).innerHTML = "<li>" + days + "<br><span class='tzcd-format'>day" + (days == 1 ? '' : 's') + '</span></li>' + "<li>" + hours + "<br><span class='tzcd-format'>hours</span></li> " + "<li>" + mins + "<br><span class='tzcd-format'>minutes</span></li>" +"<li>"+secs+ "<br><span class='tzcd-format'>seconds</span></li>";
setTimeout('displayTZCountDown('+(countdown-1)+',\''+tzcd+'\');',999);
}
}
I have the following JavaScript on my site that shows the amount of time left for an order to be placed for next day delivery.
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 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;
}
}
}, 1000
);
}
The problem with this is that on saturday and sunday it just displays 00:00:00 all the time.
What I would like it to do is count the hours over a weekend as is done on this site for example: http://www.nakedwines.com/full_site
JavaScript is really not my area and I'm totally at a loss on how I can change the code to do this. Any help would be appreciated.
Fiddle is here http://jsfiddle.net/rwet0o5f/
I've moved the now.getDay() into variable and now it should be much more readable.
weekday contains 0 on Sunday, 1 on Monday and 6 on Saturday.
On Saturday we add 48 hours to the time of the deadline,
On Sunday we add only 24 hours.
http://jsfiddle.net/37ox54bk/7/
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 = 15; // 15: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;
}
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
return 0;
}
}
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
);
}
Try this.
Instead of not doing anything when you are past the target time, I just increase the target time to point to a different day (the main difference is the if..else if statements at the beginning of the function)
function countDown() {
var now = new Date();
var target = 15; // 15:00hrs is the cut-off point
if (now.getDay() == 0) { // Sunday - use tomorrow's cutoff
target += 24;
} else if (now.getDay() == 6) { // Saturday - use cutoff 2 days from now
target += 48;
} else if (now.getHours() < target) { // missed the cutoff point. Use tomorrow instead
target += 24;
if (now.getDay() == 5) { // Friday - use Monday cutoff
target += 48;
}
}
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);
I forked the fiddle: http://jsfiddle.net/4vhah8yt/1/
Code #sEver is good. Aj Richardson your code countdown is from new hours - is wrong.
I'd like to affter countdown hide HTML/CSS code.
Full Code: https://codepen.io/kamikstudio/pen/dyzvrQP
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 = 14; // 15: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;
}
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
return 0;
}
}
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 = '<b>' + pad(hrs, 2) + ' </b>hours<b> ' + pad(mins, 2) + ' </b>min<b> ' + pad(secs, 2) + ' </b>sec';
document.getElementById('countdownTimer').innerHTML = str;
}, 1000
);
}
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) )
I'm using Javascript (no jQuery) to create a list of paragraphs to get the best time to go to sleep (based on the REM sleep cycle) and show it on a page, here's the code.
function sleepnow() {
var result = '';
var a = new Date();
var hour = a.getHours();
var minutes = a.getMinutes() + 14;
if (minutes > 60) {
minutes = minutes - 60;
hour = hour + 1;
}
for (var counter = 0; counter < 6; counter++) {
if (minutes < 30) {
minutes = minutes + 30;
} else {
minutes = minutes - 30;
hour = hour + 1;
}
hour = hour + 1;
if (hour >= 24) {
if (hour === 24) {
hour = 0;
} else if (hour === 25) {
hour = 1;
}
}
if (hour > 9) {
result = result + '<p>' + hour;
} else {
result = result + '<p>0' + hour;
}
if (minutes > 9) {
result = result + ':' + minutes + '</p>';
} else {
result = result + ':0' + minutes + '</p>';
}
}
document.getElementById('sleepnow').innerHTML = result;
}
How can I reverse that list to show the farther one first and so on? I tried for an hour with .reverse() but I can't get it to work, it just flips everything, < p > tags included, breaking everything.
I'd separate the data from the html a little more. Instead of building a string, build an array of times. Then you can loop through it in reverse order when you build the html string.
1. create data structure, contains only numbers, no html (model)
2. convert data to html (view)
var html = '';
for (var counter = YOURDATA.length-1; counter >= 0; counter--) {
var t = YOURDATA[counter];
html += ' build your string ' + t + '...';
}
Also this case should be fine, but be careful with special characters in the raw data (&<>\""). Generally you should escape all the data, for an html context.
First of all: The answer is: By using an intermediate accumulator string variable currentOne which accumulates normally and by accumulating in the other order in the result: result = currentOne + result instead of result = result + currentOne. Enjoy:
function sleepnow() {
var result = '';
var a = new Date();
var hour = a.getHours();
var minutes = a.getMinutes() + 14;
if (minutes > 60) {
minutes = minutes - 60;
hour = hour + 1;
}
for (var counter = 0; counter < 6; counter++) {
var currentOne = "";
if (minutes < 30) {
minutes = minutes + 30;
} else {
minutes = minutes - 30;
hour = hour + 1;
}
hour = hour + 1;
if (hour >= 24) {
if (hour === 24) {
hour = 0;
} else if (hour === 25) {
hour = 1;
}
}
if (hour > 9) {
currentOne = currentOne + '<p>' + hour;
} else {
currentOne = currentOne + '<p>0' + hour;
}
if (minutes > 9) {
currentOne = currentOne + ':' + minutes + '</p>';
} else {
currentOne = currentOne + ':0' + minutes + '</p>';
}
result = currentOne + result;
}
document.getElementById('sleepnow').innerHTML = result;
}
Secondly: Please don't make external links without describing what's on the other side thoroughly. External links can expire, become irrelevant, etc.
Third: You made quite a mess in that code right there :)