Troubleshooting JS Shipping Countdown Timer - javascript

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>

Related

Check if time is within time bounds with minutes

looking for help in changing the working hours from 8 to 5 to 8:30 to 5:30. would appreciate some help with amending the existing JavaScript function:
<html>
<head>
<script>
onload = function ( )
{
var now = new Date();
var weekday = now. getDay();
var hours = now.getHours();
if ((hours >= 8) && (hours <= 5)) && ((weekday >=1) && (weekday <= 5))
{
document.getElementById("status").src="open.png";
}
else
{
document.getElementById("status").src="closed.png";
}
}
</script>
</head>
<body>
<img id="status" src="">
</body>
</html>
Since .getHours() returns an integer, check the hour and the minutes accordingly using .getMinutes().
It's a bit messy, but it's easy to understand. I've broken it down below the snippet.
const cur = new Date();
const minutes = cur.getMinutes();
const h = cur.getHours();
const d = cur.getDay();
let closed = true;
if ((d >= 1) && (d <= 5)) {
if (h > 8 && h < 17) {
if (h == 8 && minutes < 30 || h == 17 && minutes > 30) {
closed = true;
} else {
closed = false;
}
} else {
closed = true;
}
} else {
closed = true;
}
console.log("Closed? : " + closed);
(d >= 1) && (d <= 5) - this checks whether the weekday is within the bounds of Monday (1) and Friday (5)
(h > 8 && h < 17) - is the current hour within the bounds 8 AM and 5 PM (8 and 17 respectively)?
h == 8 && minutes < 30 || h == 17 && minutes > 30 - if the current hour is 8, check if the minutes is smaller than 30. We need to ensure that the minutes is 30 or greater (8:30+). If the current hour is 5, check if the minutes is greater than 30. We need to ensure that the minutes is 30 or less (5:30-). If any of these are satified, we know it is closed.
Here's a comprehensive snippet with logs:
const cur = new Date();
const minutes = cur.getMinutes();
const h = cur.getHours();
const d = cur.getDay();
let closed = true;
if ((d >= 1) && (d <= 5)) {
console.log("Weekday is within Monday and Friday? check");
if (h > 8 && h < 17) {
console.log("Hour is between 8 AM and 5PM? check");
if (h == 8 && minutes < 30 || h == 17 && minutes > 30) {
console.log("Minutes is more then 30 if hour is 8 or minutes is less than 30 if hour is 15? fail");
closed = true;
} else {
console.log("Minutes is more then 30 if hour is 8 or minutes is less than 30 if hour is 15? check");
closed = false;
}
} else {
console.log("Hour is between 8 AM and 5PM? fail");
closed = true;
}
} else {
console.log("Weekday is within Monday and Friday? fail");
closed = true;
}
console.log("Closed? : " + closed);
Here's what it should look like in your particular example:
<html>
<head>
<script>
onload = function() {
const cur = new Date();
const minutes = cur.getMinutes();
const h = cur.getHours();
const d = cur.getDay();
let closed = true;
if ((d >= 1) && (d <= 5)) {
if (h > 8 && h < 17) {
if (h == 8 && minutes < 30 || h == 17 && minutes > 30) {
closed = true;
} else {
closed = false;
}
} else {
closed = true;
}
} else {
closed = true;
}
if (closed) {
document.getElementById("status").src = "closed.png";
} else {
document.getElementById("status").src = "open.png";
}
}
</script>
</head>
<body>
<img id="status" src="">
</body>
</html>
first of all, you mistakenly added extra bracket in your if expression:
if ((hours >= 8) && (hours <= 5)) && ((weekday >=1) && (weekday <= 5))
I ecountered this seemingly easy to solve in past, until you need to compare the minutes inbetween, you will run to unecessary complex logic.
the cleanest way to solve this is convert into "seconds from midnight" which makes easier for comparison between two time. (this technique similar to UNIX TIME technique use by lots of date system nowdays, you can google it)
in smaller project its ok to do following:
var now = new Date();
var weekday = now.getDay();
function getSecond(hours, minutes){
return ( (hours * 60 * 60) + (minutes * 60) ); //this will return the total seconds past midnight
}
//converting to seconds to certain point of time is used by "timestamp" technique, you can google bout it
let openSeconds = getSecond(8,30);
let closeSeconds = getSecond(17,30);
let nowSeconds = getSecond( now.getHours(), now.getMinutes());
console.log(openSeconds + ' ' + closeSeconds + ' ' + nowSeconds);
if( (weekday >= 1) && (weekday <= 5) ){ //Weekday validation
if(openSeconds < nowSeconds && nowSeconds <= closeSeconds){ //inclusive, ( < or <= ) you decide
document.getElementById("status").src = "open.png";
}else{
document.getElementById("status").src = "closed.png";
}
}
in bigger project, i always always recommend to use dayjs or moment js to deal with timezones like explained in video:
https://www.youtube.com/watch?v=-5wpm-gesOY
Adapting the code you posted:
window.onload = function () {
var now = new Date();
var weekday = now.getDay();
var hours = now.getHours();
var minutes = now.getMinutes();
var status = document.getElementById('status');
// if Monday - Friday
if (weekday >= 1 && weekday <= 5) {
// if before 8am OR after 5pm
if (hours < 8 || hours > 17) {
status.src = 'closed.png';
}
// if less than 30 minutes past 8am, OR
// if 30+ minutes past 5pm
else if (minutes < 30 && hours === 8 || minutes >= 30 && hours === 17) {
status.src = 'closed.png';
}
// if 30 or more minutes past any hour between 8am and 4pm,
// or up to 29 minutes past 5pm, you're open!
else {
status.src = 'open.png';
}
}
};

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.

Check if time is between two values with hours and minutes in javascript

I need to check if a time is between a start and end time. All times are on the same day, so date is not important. I'm able to compare hours, but I'm unsure how to add in minutes to the start and end times.
var thedate = new Date();
var dayofweek = thedate.getUTCDay();
var hourofday = thedate.getUTCHours();
var minutesofday = date.getMinutes();
function inTime() { if (dayofweek != 0 && dayofweek != 7 && (hourofday > 13 && hourofday < 20)) { return true; } return false; }
If I want to check whether the time is between 13:05 and 19:57, how would I add the minutes to my inTime function? If I add them to the if statement, it fails to work:
function inTime() { if (dayofweek != 0 && dayofweek != 7 && ((hourofday > 13 && minutesofday > 5) && (hourofday < 20 && minutesofday < 57))) { return true; } return false; }
If its 14:04 your condition will fail as 4 is smaller 5. The simplest would probably be to just take the full minutes of the day:
const start = 13 * 60 + 5;
const end = 19 * 60 + 57;
const date = new Date();
const now = date.getHours() * 60 + date.getMinutes();
if(start <= now && now <= end)
alert("in time");
If you're saying you want to check if the time "now" is between two times, you can express those times as minutes-since-midnight (hours * 60 + minutes), and the check is quite straightforward.
For instance, is it between 8:30 a.m. (inclusive) and 5:00 p.m. (exclusive):
var start = 8 * 60 + 30;
var end = 17 * 60 + 0;
function inTime() {
var now = new Date();
var time = now.getHours() * 60 + now.getMinutes();
return time >= start && time < end;
}
console.log(inTime());
The above uses local time; if you want to check UTC instead, just use the equivalent UTC methods.
Convert times to milliseconds and then you can compare easily.
short version:
if(timeToCheck.getTime() >= startTime.getTime() &&
timeToCheck.getTime() <= endTime.getTime()) {
// ...
}
OR:
let startTimeMilli = startTime.getTime();
let endTimeMilli = endTime.getTime();
let timeToCheckMilli = timeToCheck.getTime();
// change >= to > or <= to < as you need
if (timeToCheckMilli >= startTimeMilli && timeToCheckMilli <= endTimeMilli) {
// do your things
}

JavaScript shipping timer countdown

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
);
}

How to add number of days to get the next date from current date without weekends

I want to add some no. of days to get the future date. And weekends should not be included in this. How can I get this?
var startdate = "8-June-2012";
no. of days to add = 10;
enddate should be "22-June-2012"
Try this :
var startDate = "8-June-2012";
startDate = new Date(startDate.replace(/-/g, "/"));
var endDate = "", noOfDaysToAdd = 10, count = 0;
while(count < noOfDaysToAdd){
endDate = new Date(startDate.setDate(startDate.getDate() + 1));
if(endDate.getDay() != 0 && endDate.getDay() != 6){
//Date.getDay() gives weekday starting from 0(Sunday) to 6(Saturday)
count++;
}
}
Here is the demo
function calculateWorkingDayNumbers(startDate, offset)
{
var startDay = startDate.getDay();
if ((startDay % 7) === 1)
{
return ((offset - (offset % 7)) / 7) + ((offset % 7 === 1) ? (1) : (0));
}
else if (offset < 7)
{
if ((startDay === 6))
return 1 + ((offset > 0) ? (1) : (0));
else if (startDay === 0)
return 1 + ((offset === 6) ? (1) : (0));
}
else
{
return calculateWorkingDayNumbers(startDate, (((startDay % 7) + 1) % 7)) + calculateWorkingDayNumbers(startDate.setDate(startDate.getDate() + (((startDay % 7) + 1) % 7)), offset - (((startDay % 7) + 1) % 7));
}
}
This (untested) code is very fast. You could also improve your solution by handling holidays too.

Categories

Resources