I want to reset a variable automatically without any user interaction to 0 every midnight.
How to do that in vanilla Javascript?
Or does Chrome have any default method to do it. Because I store that variable in Chrome.storage.local.
What is the best way to do it in either vanilla JS or using chrome apis?
It is impossible to do so automatically without user accessing the page.
But, you can add script to the page which onload check the last time the value was stored and if the time passed you can reset the variable.
Rough code to make this:
const isToday = (someDate) => {
const today = new Date()
return someDate.getDate() == today.getDate() &&
someDate.getMonth() == today.getMonth() &&
someDate.getFullYear() == today.getFullYear()
}
window.onload = function init() {
const { value, date } = JSON.parse(localStorage.getValue('key'));
if (!isToday(date)) {
localStorage.setValue('key', JSON.stringify({ date: new Date(), value: defaultValue}))
}
}
You've said you're storing the value in Chrome.storage.local. Also store the date/time you saved that value. When you load it, if midnight has passed since that time, reset the value to zero.
In case the page has been left open overnight, either always load the value from storage before using it (even if you already have it in a JavaScript variable), or do the same thing at the JavaScript level (remember the date/time and reset the value). Although you can set a timer, pages that sit idle for a long period of time have their timers de-prioritized by modern browsers, so it probably wouldn't be reliable to do this with a timer.
Without server assisting to do that, you may want to implement reset_variable() to be scheduled with helping of setTimeout() https://developer.mozilla.org/en-US/docs/Web/API/setTimeout and setInterval() https://developer.mozilla.org/en-US/docs/Web/API/setInterval - But you have to trigger setInterval() at midnight first, and adjust the interval as 24h. Thus, you have to implement some algorithm to calculate when to start executing (trigger) setInterval() using the setTimeout().
With server assisting, you may want to implement a cron-like job in the server. The job may look like sending some predefined values to reset the variable on the browser.
Therefore, you can do it in diverse ways. The simplest way is over WebSocket https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API.
Explanation:
Browser/Client-side:
Implement a Listener on the browser Ex, message event https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event, whenever you caught a message, process that message if it's the predefined value to reset the variable, then someVar.reset().
Server-side:
Create a handler to connect to the client-side WebSocket Listener -WebSocket supported in most programming languages-.
Implement a cron-like job to execute a function every midnight. I have no idea if you have a server, and if so, which programming language you are using. However, a cron-like job can be implemented in several programming languages, and basically, it can be implemented natively on Unix-like OSs, you may want to ask another question if you need help regarding this.
The function should send a predefined value using the handler of the WebSocket connection.
-you can do some Security validation though-
Related
In the update window I would like to automatically add 30 minutes to the event start date:
$('#updatedialog').dialog({
autoOpen: false,
width: 680,
buttons: {
"update": function () {
var eventToUpdate = {
id: currentUpdateEvent.id,
title: $("#eventName").val(),
description: $("#eventDesc").val(),
color: $("#colorPicker").val(),
start: new Date($("#eventStart").val()),
end: new Date($("#eventEnd").val()),
//end: new Date($("#eventEnd").val(moment(event.start).add(30, "m").format("YYYY-MM-DD[T]HH:mm"))),
//end: new Date($("#eventEnd")).setMinutes($("#eventStart").val() +30),
note: $("#EditEventNote").val(),
/*start: moment($("#eventStart").val(), "DD/MM/YYYY HH:mm"),*/
};
PageMethods.UpdateEvent(eventToUpdate, updateSuccess);
$(this).dialog("close");
currentUpdateEvent.title = $("#eventName").val();
currentUpdateEvent.description = $("#eventDesc").val();
currentUpdateEvent.color = $("#colorPicker").val();
currentUpdateEvent.note = $("#EditEventNote").val();
currentUpdateEvent.start = new Date($("#eventStart").val());
currentUpdateEvent.start.setMinutes(currentUpdateEvent.start.getMinutes() + 30);
$('#calendar').fullCalendar('updateEvent', currentUpdateEvent);
$('#calendar').fullCalendar('refetchEvents');
},
But this code doesn't work.
Firstly this is largely a momentJS issue, not a fullCalendar one.
You need to clone the start date, mutate it by 30 minutes, and then format it for output.
N.B. event.start doesn't actually appear anywhere in your code, so I'm assuming you actually wanted to use the value from the "eventStart" textbox instead. And I've gone back to setting the date format the way we agreed in your earlier question about this code. It's unclear why you've stopped doing it that way, because you already made clear it didn't work to set the start/end dates using new Date(...).
Therefore your code would look this like:
"update": function () {
var start = moment($("#eventStart").val()); //parse the start date
var end = moment(start); //clone the start date to make the end date
end.add(30, "m"); //add 30 minutes to the end date
//create the event object with formatted dates
var eventToUpdate = {
start: start.format("YYYY-MM-DD HH:mm"),
end: end.format("YYYY-MM-DD HH:mm")
//...etc
};
$("#eventEnd").val(end.format("YYYY-MM-DD[T]HH:mm")); //only include this line if you actually want to set the value of the eventEnd textbox.
//...etc
Minimal demo: https://codepen.io/ADyson82/pen/PojKGXY
Relevant documentation:
https://momentjs.com/docs/#/parsing/moment-clone/
https://momentjs.com/docs/#/manipulating/add/
P.S. I want to make a more general point about your approach to programming, based on what you've shown here, and your various previous questions where I've intervened.
This attempt:
//end: new Date($("#eventEnd").val(moment(event.start).add(30, "m").format("YYYY-MM-DD[T]HH:mm")))
contains a jumble of code all packed together in what appears to be a giant piece of guesswork, or possibly a "throw everything at it until something sticks" approach. Neither of those techniques are going to make you a good programmer. Programming is a science / engineering discipline, not an art form or a hit-and-hope game. You need to be methodical and precise. If the best you can say about it is that it "doesn't work", then it's clear you haven't analysed it at all. To solve problems in your code, you need to analyse it and debug it piece by piece.
So what you need to do with that code, to see why it's not working, is take it all apart, read the documentation properly for each of the many functions you've used there, and work out what they output and whether that's relevant to your situation - and/or whether each one gives suitable input to the thing you've included it within.
When testing JavaScript / jQuery code you should also be checking in your browser's Console (in the Developer Tools) for errors, and using the built-in debugger to step through the code line by line to see the values of your variables, and spot where the code and the values don't do what you expected them to. (If you don't know what you expect a particular part of the code to do, then you should either scrap that part and write something you can understand, or go and read documentation and try examples using that code until you do understand it. Otherwise you're just back to guessing again, and that's pointless.)
You can test each part of the code individually to verify your understanding. Putting large numbers of function calls together in one line like in the example above makes it very difficult to debug - for testing, you should split it into invidiual lines and see what each one produces, before deciding whether it's useful to put into the next step. For example if we break down that code into separate steps, we'd end up with:
var moment1 = moment(event.start);
moment1.add("30", "m");
var formattedDate = moment1.format("YYYY-MM-DD[T]HH:mm");
var x = $("eventEnd").val(formattedDate);
var dt = new Date(x);
var eventToUpdate = {
//...
end: dt
}
Now let's pick apart the logical flaws, one by one:
event.start doesn't appear to exist in the context you've shown (unless you've omitted some outer code). So you're probably starting with a blank to begin with. As I mentioned above, I'm guessing you actually meant to use the value from the eventStart textbox instead.
If event.start does exist in this context, then it looks like it probably came from fullCalendar, and fullCalendar v3 (as per its documentation) already gives you dates as momentJS objects - so you don't need to wrap them in the moment() constructor all over again. Whilst it does no harm, it's also inefficient and clutters up your code for no reason.
$("eventEnd").val() will set the value of a field on the page. It's not clear whether this was intentional or not, since your stated objective was to add 30 minutes to the event's start date (presumably to form an end date ready to send to the server, although your wording could be interpreted to mean you actually want to modify the start date itself, not use it as an end date).
.val() doesn't return a value (it only sets a value when used the way you've done it). Therefore x will always be empty.
Because x is empty, new Date(x) won't do anything useful.
You don't want new Date anyway, because you need to send a pre-formatted Date as a string to your server - we already discussed this in one of your previous questions so it's not clear why you've tried this again now - apart from, as I've assumed above - that you still don't really understand any of these individual pieces of code and are still guessing randomly without testing them properly or reading anything about what they do. I will speak candidly and say that you will never achieve anything as a programmer until you learn to do both of those things. Once you start doing them, your tasks will suddenly start to seem a lot easier.
As you can see, once we break this down one by one, it's a lot easier to find the problems on their own than when it's all together in one line and you can't tell which part is doing what. Once you've got something that works, then it's fine to reduce it down into less lines if you think it saves space or makes the code neater. But don't do that until you're sure it's going to do what you want.
I have a variable speed controlled by the user from keyboard, and I want to display it current value all the time.
I tried:
var user_speed= 1; //init
<h3 style="float:left;" id="userspeed"></h3>
document.getElementById("userspeed").innerHTML = user_speed.toFixed(2);
but what I get is only speed = 1 and it never changed.
Is there a way to keep changing the displayed value, without creating a function that fire each time the user change the speed and execute document.getElementById()... again?
Why not use setInterval to update the value like so:
var speed = 1; //init
setInterval(function(){
document.getElementById("userspeed").innerHTML = user_speed.toFixed(2);
}, 1000);
This will update the value every 1 second (1000 ms).
You are only getting the initial value, because you are calling only once that code.
As you said, if you want to change the value you should need to create a call to that function in order to renew the value.
I think there is no way around. You may have to use a function and an event. Because how would you know or trigger some calculation when you dont know on which point the user entered some keys?
See this question
UPDATE: As you maybe know setInterval/setTimeout are evil!
If you take a look at this link, you will see that you should avoid those functions for not very good reasons. Simplified:
... The first argument is a string, you actually pass it some JavaScript that will be evaluated at a global namespace when the timer expires. Read the evils of evals again above and then come back. The good thing is that you are not required to pass in a string of JavaScript code. ...
I am using a jQuery plugin called jQuery Phoenix. It is a plugin that makes localStorage with forms very easy.
My question:
This script auto-saves every second. I have a form with around 275 fields and it saves all of the fields.
(I know saving that many fields that often is a bit overkill, but it's the default setting. I'm going to change it to save on an onblur event but it will still be saving 275 fields every time the person changes fields.)
If it is saving that often, will I run into any type of performance issues in browsers?
I do not know much about localStorage or how it affects performance, especially when saving this many fields of data that often.
As has been mentioned, you can optimise your use of localStorage a fair bit from what is proposed, but that isn't the question.
LocalStorage is pretty fast, as confirmed in some tests written about here:
https://gomakethings.com/how-fast-is-vanilla-js-localstorage/
they were seeing speeds around 12ms to write an object of 10,000 values and read it back again.
I had a play and storing each item on its own, and it tended to be between 70-100ms, but when you're 'only' dealing with around 300 values it's less than 2ms, this was the same if the values were strings or integers.
Here's the code I used, which is largely based on the code in the linked article:
// Timestamp before the test
var start = performance.now();
// Set/get data to localStorage
var count = 10000;
for (var i = 0; i < count; i++) {
localStorage.setItem(`perfTest_${i}`, i);
var result = localStorage.getItem(`perfTest_${i}`);
if (parseInt(result) !== i) {
console.error(`${result} !== ${i}`);
}
}
// Timestamp after the test
var end = performance.now();
// Duration of the test
console.log('It took ' + (end - start) + 'ms.');
The easiest way to run these tests is just to paste them into your browser's console!
Performance is surely going to differ and it will be an issue since internal implementation of localStorage is browser specific.
There is also a time difference between first read and subsequent read.
Beside local storage has a limited capacity(though it can be changed)
Also you wont want to stringify before saving. This will be inefficient.
Note: If all 275 fields are not changing changing simultaneously you can you only save the changed field
I am baffled. I have a "ready" function, from jQuery, which sets an HTML5 sessionStorage variable to the .valueOf() result of a new Date (as shown below). Somehow, though, the variable keeps refreshing and updating the time while my page is open. The sessionStorage variable doesn't even know it's a Date, it just stores the milliseconds, and the "ready" function is only called once at the beginning (I've checked using an alert window). There is no logic in my code to make this happen, but the value on the page stays up-to-date in real time. Any ideas?
// Initialize default date range
if (sessionStorage.minDate == null) {
d = new Date();
sessionStorage.minDate = (d.valueOf() - 172800000);
delete d;
}
if (sessionStorage.maxDate == null) {
d = new Date();
sessionStorage.maxDate = d.valueOf();
delete d;
}
UPDATE:
Still not fixed, but I've tried giving the milliseconds as a literal, and it still does the same thing. So it must have something to do with the fact that I'm creating a new Date later on using the millisecond count.
Any thoughts are much appreciated. I really have to get this working for work.
Apparently I was storing the number of milliseconds as a string, and wasn't parsing it back into an integer, so when I tried to create a new Date with it, javascript didn't know what to make of it and just created a Date with no parameters: the current date and time.
I need to create a countdown clock, that counts down the days, hours, minutes and seconds that are left to a date of my choice, using jQuery or Google App Engine (Python).
I have created a timer using JavaScript but for that I was using the system time.
I need to use the server time. Can anybody give me ideas to build a count down timer using the server UTC time.
I created a timer using Javascript,But in that i used system time.
If that JavaScript really serves your needs, then that JavaScript code could easily be made dynamic as well. In the code, wherever the current system time is initialized, simply insert your server time using your language of choice (Python). In other words: use your server language (Python) to output the script just as it is right now, except for replacing the part that initializes the current time.
In PHP, some pseudocode (not sure about the arguments of the Date() constructor) might look like, for example:
// my_countdown_script.php
[..]
var startTime = new Date( <?php echo time(); ?> );
[..]
Then, rather than including your JavaScript, you would be including the PHP file that inserts the server time like above:
<script type="text/javascript" src="my_countdown_script.php"></script>
The good thing is: this will work in any browser that supports the JavaScript you already created.
(In some later version, your JavaScript could include some initializers that allow you to set the current time after including the library in your HTML. That would allow the actual JavaScript library to be static, and thus to be cached by the browser.)
a good jquery plugin can be found here http://keith-wood.name/countdown.html
all you need to do then is pass in your new date from your scripting language php/asp.net by setting a variable on the page before the initialisation and updating the _calculatePeriods function to take that variable instead of the now one.
<script type="text/javascript" src="js/jquery-1.3.2.js"></script>
<script type="text/javascript" src="js/jquery.countdown.js"></script>
<script type="text/javascript">
$(function () {
var servernow = new Date( <?php echo time(); ?> );
var austDay = new Date();
austDay = new Date(austDay.getFullYear() + 1, 1 - 1, 26);
$('#defaultCountdown').countdown({until: austDay});
$('#year').text(austDay.getFullYear());
});
</script>
from js/jquery.countdown.js
* Calculate the requested periods between now and the target time.
#param inst (object) the current settings for this instance
#param show (string[7]) flags indicating which periods are requested/required
#param now (Date) the current date and time
#return (number[7]) the current time periods (always positive)
by year, month, week, day, hour, minute, second */
_calculatePeriods: function(inst, show, now) {
// Find endpoints
inst._now = servernow;
Josh
You can reliably get server time from http://just-the-time.appspot.com/ -- an app engine app I made to help out a questioner on stack overflow, actually;-). Its simple code is opensourced at http://code.google.com/p/just-the-time/, and I could easily add the functionality you require (a page that, queried with the future date of your choice, returns days, hours, minutes and seconds to it, in some easily usable format) -- just let me know!
jQuery Timers is a plugin I've used in the past, and found to be very good.
Simply set two JavaScript variables to the current and target time for the countdown, and use a jQuery timer to update the "time remaining". If you want, you can add another time that re-synchronises the server and client times as well, every so often - though this probably isn't necessary.
why not simply use the UTC methods of the date object?
see: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date
all local time methods have UTC counterparts
edit: this is meant to be used with his existing implementation in javascript.
If you really want to be sure you get the server time, do an XHR request (for anything) and check the Date header
So basically you need two things:
Page that displays the countdown time using the server time.
Client side updating of the time.
Render your time server side in something like this:
<span id="countdown" title="1245515631554">4 min. and 24 seconds</span>
Where the title is a timestamp of the current time that you can easily parse. You could also parse the text, but that requires more complex code.
Then add some Javascript that gets the time and updates the text every second. Setting a timeout that gets the date, updates it and sets the text.