I have several web pages that use " " as a placeholder for javascript function output to display a button label. For example, the following is the html that displays the output if the 'clock()' function,
<div id="clock" class="sidebar"> </div>
This one displays 'Login' until the 'log()' function is called, then changes the label to 'Logout',
<div id="login" class="sidebar"> </div>
The javascript references the IDs to direct the output to the labels. Both of these were working until a few days ago, but now are just blank. No label is displayed. Nothing obvious has changed. No updates to the system, etc. The server is running Ubuntu 16.04 lts and apache2 web server.
I have no idea why these would just quit working or where to begin looking for the problem. I have similar code running on a separate server that still works. Are there any workarounds / alternative methods that would produce the output I want?
edit:
Here is the javascript as requested:
function clock() {
var time = new Date(); //get the date
//find what day of the year it is
var start = new Date(time.getFullYear(), 0, 0);
var day = Math.floor((time - start) / (1000 * 60 * 60 * 24));
var offset = time.getTimezoneOffset() / 60;
if ((time.getHours() + offset) > 23) { day + 1; }
//get the fraction part of the day
var hour = time.getUTCHours() / 24;
var minute = time.getUTCMinutes() / 1440;
var sec = time.getUTCSeconds() / 86400;
var fraction = hour + minute + sec;
//display
$('#clock a').html((day + fraction).toFixed(4));
//change clock fontsize to fit well
var width = $('#clock').css('width');
var size = parseInt(width) / 4.75;
size = size + 'px';
$('#clock').css({'font-size':size});
}
/*makes either a login popout or logs someone out*/
function log() {
if ($('#login').html() == "Login") {
window.open("./login.html", "_blank","width=1000,height=500");
}
else { logout(); }
}
Related
On our site we're trying to execute a script that counts down to midnight everyday, displays a message, and then "resets" at midnight.
The message is basically "Order within X1, Get By X2"
The script calculates X1 to be XX Hours XX Minutes until midnight. X2 is 5 days, after today (if today is the 1st, it would be the 2nd + 5 giving you the 7th, with the exception of Sunday, then it will automatically skip to the Monday immediately after).
The problem though is that for some reason this script refuses to load for the front-end user, yet as a logged in admin I can see the code.
<!-- Allows to add estimated delivery time to the product and/or cart page -->
<div class="dailytimer"><strong>Order within <span id='mycountdown' style="color: #FF0000;"></span>, Get it by <span id="delDate" style="color: #FF0000;"></span></strong></div>
<script>
// First part of output
var myreset = [00,00,00]; // at what time to reset - 19:40:00
// Added myCountDownDiv variable to prevent jquery from walking the DOM o every update
var myCountDownDiv = document.getElementById('mycountdown');
var mycountdown = startCountdown();
function startCountdown(){
var enddate = calculateEndDate();
return setInterval(function(){tickTock(calculateStartDate(),enddate)}, 1000);
}
function calculateStartDate(){ //this needs to be edited if using the server time
return new Date();
}
function calculateEndDate(){
var enddate = new Date();
enddate.setHours(myreset[0]);
enddate.setMinutes(myreset[1]);
enddate.setSeconds(myreset[2]);
return enddate;
}
function tickTock(startdate, enddate){
var diff = enddate.getTime() - startdate.getTime();
d = diff >= 0 ? diff : diff + 24*3600*1000;
var h = Math.floor(d / 3600 / 1000);
var m = Math.floor(d / 60 / 1000) - 60*h;
var s = Math.floor(d / 1000) - 3600*h - 60*m;
printCountdown(h,m,s);
}
function pluralize(word,count){
return (count > 1) ? word+'s ' : word+' ';
}
function printCountdown(h,m,s){
// Updated string concatination. 'and' was deisplayed after the seconds value
var t = h + pluralize(' hour',h)+ m+pluralize(' minute',m);
myCountDownDiv.innerText = t;
// Removed jquery
//$('#mycountdown').html(t);
}
var fromDate = new Date();
fromDate.setDate(fromDate.getDate() + 6);
if (fromDate.is().saturday() || fromDate.is().sunday()) {
fromDate = fromDate.next().monday();
}
document.getElementById('delDate').innerHTML = fromDate.toString('ddd MMMM dS');
</script>
It's using a date JS file I found online to calculate the dates. I'm also pretty sure there's a better way for us to "insert" the code into the page without literally coping it into a html widget inside of elementor (we're using it as a page builder) but I just haven't really thought of one off hand.
Any help would be greatly appreciated as I'm about 5 steps from wanting to just hit delete on the whole thing haha
I'm trying to learn the basics of jQuery by building certain things and now it's my turn for a stopwatch (which will be used by mobile visitors).
I currently have this: codepen
html
<span id="hours"></span> u |
<span id="minutes"></span> m |
<span id="seconds"></span> s
<button onclick="tickTock()">Start</button>
js
function tickTock () {
var start = -1;
function pad(val) { return val > 9 ? val : "0" + val; }
setInterval(function () {
$("#seconds").html(pad(++start % 60));
$("#minutes").html(pad(parseInt(start / 60, 10) % 60));
$("#hours").html(pad(parseInt(start / 3600, 10)));
}, 1000);
}
After testing for a while I've noticed that after a certain period the time shown isn't correct anymore without closing the tab or browser. I want to achieve maximum reliability regarding the time shown and the time which has passed. The deviation only seems to appear on mobile devices.
Since I'm a beginner I don't know where to start. Is it even possible using js/jQuery?
If you could point me in the right direction that would be appreciated.
The set interval is only semi accurate and does not guarentee you the function runs exactly at 1 second intervals. You could start by taking the timestamp of when the function started and then using your ticktock function to subtract the previous timestamp from the current timestamp and then perform the necessary updates to the ui. I'll leave the padding and rounding out to make the example easy to follow.
function ticktock(){
var start = new Date().valueOf();
setInterval(function(){
var now = new Date().valueOf();
var elapsed = (now - start) / 1000;
var seconds = elapsed % 60;
var minutes = (elapsed / 60) % (60);
var hours = (elapsed / (60 * 60)) % (60);
$("#seconds").html(seconds);
$("#minutes").html(minutes);
$("#hours").html(hours);
}, 1000);
}
Your code can be reworked to store the start time, then to display the difference between the current time and the start time, rather than manually incrementing every second.
This way, if your code gets shelved because it's in the background, the correct time will be calculated.
function tickTock () {
var startTime = new Date();
function pad(val) { return val > 9 ? val : "0" + val; }
setInterval(function () {
var currTime = new Date();
var elapsedMs = currTime.getTime() - startTime.getTime();
var elapsedSeconds = elapsedMs * 1000;
$("#seconds").html(pad(elapsedSeconds % 60));
$("#minutes").html(pad(parseInt(elapsedSeconds / 60, 10) % 60));
$("#hours").html(pad(parseInt(elapsedSeconds / 3600, 10)));
}, 1000);
}
I created a little script in Javascript, which is supposed to show to all the clients connected on the page some informations, actually an image every 90 seconds. This function is working perfectly fine on my computer, but as soon as I have to reload the page, all the process restart.
I don't know if there is a way to make the server calling this function, like this
//This should be a "server" variable in which users should be able to add their own image :
var images = [
['Canyon', 'https://www.w3schools.com/css/img_fjords.jpg'],
['Car Jumping', 'http://www.gettyimages.fr/gi-resources/images/Embed/new/embed2.jpg'],
['Birds Flying', 'http://ekladata.com/qWGncUdJ7U5k2vvmc1au-ZLnjlc.jpg'],
];
function Display (imagesarray) {
var rnd = Math.floor((Math.random() * imagesarray.length - 1) + 1);
document.getElementById("image").src = imagesarray[rnd][1];
}
function Timer(countDownDate) {
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = countDownDate - now + 2;
// Time calculations for days, hours, minutes and seconds
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Output the result in an element with id="demo"
document.getElementById("countdown").innerHTML = ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("countdown").innerHTML = "FINISHED !";
Display(images);
}
}, 1000);
}
//This will call the Timer() function to end it in 01:30, and launch it again 10 seconds after the end of the previous call.
var y = setInterval(Timer(new Date().getTime() + 10000), 500);
p {
text-align : center;
font-size : 48px;
margin : 0px;
}
#note {
text-align : center;
font-size : 12px;
margin : 0px;
}
#image {
display : block;
margin : auto;
width : 150px;
height : 150px;
}
<p id="note">Counting only 10 seconds for example</p>
<p id="countdown">00:10</p>
<img id="image" src="http://vignette4.wikia.nocookie.net/destinypedia/images/b/b9/Unknown_License.png/revision/latest?cb=20130810221651">
Does anyone know how this could be managed by the server, so everybody have the same timer and the same picture displayed at the same time ?
Thanks a lot for your help !
[EDIT 1] The backend language I am using is PHP on this project
Breaking news: Time passes the same way all around the world :-D.
So there is no real need of "persistent connection" or so, as long as the users have set-up the time correctly on their computer. You just need to use the same base date for every user. Timestamps are very good at this because there is no time-zone problem with them.
Also note that it might be a better idea not using setTimeout setInterval for measuring time, because setTimeout could be renamed as runAfterAtLeastThatTimeIfYouDontHaveBetterToDo(). In deed, putting a setIterval(()=>{},1000) does not guarantee it will run every 1s, and you might experience desynchronization if the user switch tabs while browsing. You'd better run the interval function more than every seconds -every 10ms for example- if you want it to be accurate.
Usualy, I use requestAnimationFrame for displaying timer.
code :
In this code, I use the same base date for every users (I didn't put any 10s chill-time because I am lazy, but you can see the idea) :
const startDate = 0; // Unix epoch
const interval = 90000; // 90 seconds
var now = Date.now();
var count = (now - startDate) / interval; // should have run {{count}} times since Unix epoch
var next = Math.ceil(count) * interval + startDate; // so the next time it should run is at timestamp {{next}}
function timer() => {
var now = Date.now();
distance = next - now;
if (now >= next) {
document.getElementById("image").src = "http://domain.tld/my-script.php?now=" + now; // the query string parameter is just to avoid browser caching the image
next += interval;
} else {
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
document.getElementById("countdown").innerHTML = ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
}
}
var requestID = window.requestAnimationFame(timer);
// use window.cancelAnimationFrame(requestID) to cancel the timer
A note on the img.src part:
this is the only part where the server is mandatory, you must implement a script that will send the image based on time. I added a queryString ?now=timestamp to avoid browser caching the image, and not keeping it up to date, but the server should rely on it's own date/time to display the image, not the one sent by the user.
PS : Note that I don't have anything against persistent connection via websocket or so, but that sounds a bit overkill for just displaying a timer and an image on a regular basis. If you think all your user have set their computer's time correctly and that it's not a big deal if some are not synched, use this solution. Otherwise, go for websocket.
You need to keep a persistent connection with the server possibly through websockets OR you can easily just send a variable from the server which tells the clients in how many seconds the next appearance should start.
The following code is a countdown timer. It pulls an ending datetime stamp from mySQL and uses it to count to. The issue is that the mysql time may be in a different time zone than the client who is looking at the page with the timer.
I also pull the current timestamp from mySQL with NOW(), thinking that this would allow the timer to count as the user who created it intended.
if I put the NOW() value in this snippet
var timeDiff = target - (new Date());
like so
var nt='2015-03-11 05:12:15'.split(/[- :]/);
var timeDiff = target - (new Date(nt[0],nt[1]-1,nt[2],nt[3],nt[4],nt[5]));
the counter shows the correct time left when the page loads but does not count interactively any longer. I think I need to get the difference in hours between the clients local time and the mySQL NOW() and adjust the date in this line to get the interactive timer to run.
var timeDiff = target - (new Date());
nothing I try seems to work.
This is the working script if the client happens to be int he same time zone.
<script language="javaScript">
document.write(hrs);
function timeDiff(target) {
function z(n) {return (n<10? '0' : '') + n;}
var timeDiff = target - (new Date());
var hours = timeDiff / 3.6e6 | 0;
var minutes = timeDiff % 3.6e6 / 6e4 | 0;
var seconds = timeDiff % 6e4 / 1e3 | 0;
if (hours<0 || minutes<0 || seconds<0) {
document.getElementById('divBody').style.display='none';
document.getElementById('divExpired').style.display='';
return '<b>EXPIRED</b>';
}
else {
return '<b>' + z(hours) + '</b> Hours, <b>' + z(minutes) + '</b> Mins, <b>' + z(seconds) + '</b> Secs';
}
}
function doCountDown(target) {
document.getElementById('timer').innerHTML = '<img src=\"/backhaul/images/my/al-active.png\" class=\"vm2\" /> <span style=\"color:#c40000\"><b>EXPIRES IN</b></span>: ' + timeDiff(target);
var lag = 1020 - (new Date() % 100);
setTimeout(function(){doCountDown(target);}, lag);
}
window.onload = function() {
//Insert Expiratin Date from mySQL into t var
var t='2015-03-12 00:00:00'.split(/[- :]/);
doCountDown(new Date(t[0],t[1]-1,t[2],t[3],t[4],t[5]));
}
</script>
There are many ways of doing this, but I'll elaborate on two ways.
Method 1 : Adjust the time on the client side
One way is what you are trying to do which is to get the current time of the server and find the difference with the client's current time. You can simply adjust the server target time to the client's time. This can be done with
var serverDifference=Date.parse(mysql_data.now)-Date.now()
var target=Date.parse(mysql_data.server_time_in_two_hours)-serverDifference
Then you can input it into your function without problem.
Method 2: Calculate the times remaining, server side
Since you just need a countdown timer, I think it's more appropriate to simply send the seconds left server side. This can be done with SQL using
select timestampdiff(SECOND,now(),end_time) seconds_left from timers;
Then you simply just make a timer that counts down based on the number of seconds left instead of a target date. You can calculate the number of seconds left by deducting the time that the javascript has run from the time received from the server. So something like
var client_start=Date.now()
function timeDiff_fromseconds(target) {
function z(n) {return (n<10? '0' : '') + n;}
var timeDiff =target-(Date.now()-client_start)
var hours = timeDiff / 3.6e6 | 0;
var minutes = timeDiff % 3.6e6 / 6e4 | 0;
var seconds = timeDiff % 6e4 / 1e3 | 0;
if (hours<0 || minutes<0 || seconds<0) {
return '<b>EXPIRED</b>';
}
else {
return '<b>' + z(hours) + '</b> Hours, <b>' + z(minutes) + '</b> Mins, <b>' + z(seconds) + '</b> Secs';
}
}
There is also performance.now() as suggested by #dandavis. This returns the number of milliseconds since the tab opened and is accurate to 1/1000th of a millisecond. And this doesn't change even if the system clock of the client browser changes. For full support, you should use a polyfill (As of the time of this writing, iOS Safari doesn't support it). In this context we can replace Date.now() with it.
JSFiddle Demo:
http://jsfiddle.net/3o3u5r5j/1/
If it is possible to get remaining amount of seconds from database instead of expiry time (meaning to calculate it at the server and send to the client). Then you can use following code (sample). Fiddle
var countDownId;
var timer;
function countDown(){
console.log(timer--);
if(timer<=0){
clearInterval(countDownId);
alert('time expired');
}
}
function startCountDown(secondsToExpire){
var milliseconds = 1 * 1000 ;// 1 second
timer = secondsToExpire;
countDownId = setInterval(function() { countDown();},milliseconds);
}
window.onload = function() {
//Insert remaining time from expiration
var timeRemaining = 5;
startCountDown(timeRemaining);
}
You can tweak this to suit your needs.
Im using this jquery plugin for time count down in my web app. Please help me out to remain the count down time not beginning at first each time.I want to set the cont down for a month (30 days 24h 60min 60 sec).So every time i refresh count down should not be started from the beginning.Thnx
here is the script code to set the time
$('#counter').countdown({
timestamp : (new Date()).getTime() + 30*24*60*60*1000
});
Does everyone need the same end time? For example, if you want to launch your site on March 5, 2014 at 5 PM Eastern, then you want to set the launch time like so:
var ts = new Date(Date.UTC(2014, 2, 7, 22))
$('#counter').countdown({
timestamp : ts
});
Alternatively, if each user needs to see a unique countdown, then you want to persist the time in a cookie. For example, if I open the page 5 minutes after you open the page. Should the timer be 5 minutes apart? If yes, then use the cookie. If no and both of our timers should be the same, then pass to the counter the desired end date.
Note: UTC is set if timezones matter for you.
var today = new Date()
var enddate = new Date(2014,05,01)
function calcDate(date1,date2) {
var datadiff = Math.abs(date1 - date2) / 1000;
// calculate (and subtract) whole days
var days = Math.floor(datadiff / 86400);
datadiff -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(datadiff / 3600) % 24;
datadiff -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(datadiff / 60) % 60;
datadiff -= minutes * 60;
// what's left is seconds
var seconds = Math.floor(datadiff % 60);
var message = " ";
message += days + " days " ;
message += hours + " hours ";
message += minutes + " minutes \n";
message += seconds + " seconds \n";
return message
}
a = calcDate(enddate,today);
alert(a);
If you need persistence, rather than creating a new date object in javascript, pass the date from the backend which should be saved the first time you start the countdown.
There are many ways to persist data. One way might to to store the date into a cookie.
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
date = getCookie('date');
if(!date) {
document.cookie="date=" + new Date().getTime() + 30*24*60*60*1000 + ";";
date = getCookie('date');
}
alert(date);
That should help you persist the date between browser refreshes, but only as long as the cookie lasts.