Is there any default way in JavaScript to check user activity. If not how to address this issue.
There is no default way of doing this in java script. One way to address this issue is using JavaScript events.
this.lastActiveTime = new Date();
window.onclick = function () {
this.lastActiveTime= new Date();
};
window.onmousemove = function () {
this.lastActiveTime= new Date();
};
window.onkeypress = function () {
this.lastActiveTime= new Date();
};
window.onscroll = function () {
this.lastActiveTime= new Date();
};
let idleTimer_k = window.setInterval(CheckIdleTime, 10000);
function CheckIdleTime() {
//returns idle time every 10 seconds
let dateNowTime = new Date().getTime();
let lastActiveTime = new Date(this.lastActiveTime).getTime();
let remTime = Math.floor((dateNowTime-lastActiveTime)/ 1000);
// converting from milliseconds to seconds
console.log("Idle since "+remTime+" Seconds Last active at "+this.lastActiveTime)
}
<div> APP Here <br/><br/><br/><br/><br/><br/>make activity here<br/><br/><br/><br/><br/>Till here </div>
Here is the short example of the functionality where something will happen if user was inactive for around 10 minutes.
Upon init of the app:
window.lastActivity = Date.now();
document.addEventListener('click', function(){
window.lastActivity = Date.now();
})
Somewhere in particular service:
var TIMEOUT = 600000 //10 mins
var activityChecker = setInterval(check, 3000);
function check() {
var currentTime = Date.now();
if (currentTime - window.lastActivity > TIMEOUT) {
// do something useful, for example logout or whatever
}
}
This approach is nice because it doesn't depend on some timers which are working incorrectly if user minimize browser or switch to another tab, etc.
We just check current timestamp with the lastActivity timestamp every few seconds.
You can change 'click' event in my code with any other type of event you need or with any other condition which is suitable for you to consider user as active.
Related
I am currently working with a javascript that is supposed to remove some unwanted cookies, but for some reason aren't they removed when told to?..
only after certain amount of times trying to remove them, they seem to be removed.. some sort of delayed effect?
here is the code:
const name = 'test_u';
const name1 = 'test_te_s';
function eraseCookie(name) {
document.cookie = name+'=; Max-Age=-99999999;';
}
function removeCookies(cookieA, cookieB) {
setInterval(function() {
if (document.cookie.includes(cookieA) || document.cookie.includes(cookieB))
{
eraseCookie(cookieA);
eraseCookie(cookieB);
var date = new Date();
var timestamp = date.getTime();
console.log(timestamp)
}
},10000);
}
removeCookies(name, name1);
example from console log output:
1555420706478
1555420716477
1555420726487
1555420736487
1555420746497
1555420756487
It runs 6 times before its removed? but why though?
why aren't they removed immediately?
Because you have setInterval which means that that code will be run after some time that you provide, and keep repeating it by that interval. So just remove that setInterval:
function removeCookies(cookieA, cookieB) {
if (document.cookie.includes(cookieA) || document.cookie.includes(cookieB)) {
eraseCookie(cookieA);
eraseCookie(cookieB);
var date = new Date();
var timestamp = date.getTime();
console.log(timestamp)
}
}
And if you want to keep repeating it try this one:
removeCookies(name, name1);
setInterval(() => {
removeCookies(name, name1);
}, 10000);
or
function removeCookies(cookieA, cookieB) {
if (document.cookie.includes(cookieA) || document.cookie.includes(cookieB)) {
eraseCookie(cookieA);
eraseCookie(cookieB);
var date = new Date();
var timestamp = date.getTime();
console.log(timestamp)
}
setInterval(() => {
removeCookies()
}, 10000);
}
removeCookies(name, name1);
so it will first call removeCookies, and then it will keep repeating.
Here is a very simple program that I wrote:
function () {
var app = SpreadsheetApp ;
var tableur = app.getActiveSpreadsheet() ;
var feuille = tableur.getActiveSheet();
var now = new Date();
Utilities.sleep(900000)
feuille.getRange("A1000").setValue(now);
feuille.getRange("B1000:O1000").setValue("1000000");
feuille.getRange("P1000").setValue("Prudent");
feuille.getRange("Q1000").setValue("10");
feuille.getRange("R1000").setValue("10");
feuille.getRange("S1000").setValue("NON");
}
However, I want the code to wait 15 minutes before it continues. Google has a restriction of 5 minutes, which is why I read a lot about this issue but I couldn't find any solution. I actually used Utilities.sleep (900000) but it doesn't work.
I appeal to your kindness to explain to a beginner like me how to circumvent the restriction if ever this is possible! :)
function onEdit(e) {
var triggerTime = new Date();
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperty("lastTrigger", triggerTime);
}
function doSomething() {
var scriptProperties = PropertiesService.getScriptProperties();
var lastTrigger = new Date(scriptProperties.getProperty("lastTrigger"));
var lastTriggerUnix = lastTrigger.getTime() / 1000; // using unix time for a more straightforward time comparison
var nowUnix = (new Date()).getTime() / 1000;
var FIFTEEN_MINUTES = 15 * 60;
if ((nowUnix - lastTriggerUnix) >= FIFTEEN_MINUTES) {
scriptProperties.deleteProperty("lastTrigger");
var app = SpreadsheetApp ;
var tableur = app.getActiveSpreadsheet() ;
var feuille = tableur.getSheetByName("RĂ©ponses"); // getActiveSheet() can yield unexpected results
var app = SpreadsheetApp ;
var now = new Date()
feuille.getRange("A10").setValue(now);
feuille.getRange("B10:O10").setValue("1000000");
feuille.getRange("P10").setValue("Prudent");
feuille.getRange("Q10").setValue("10");
feuille.getRange("R10").setValue("10");
feuille.getRange("S10").setValue("NON");
}
}
Is there something I forgot?
Given the new information that you want the doSomething() script to run roughly 15 minutes after the spreadsheet was last edited, here's my modification, but using the same general principle.
Create an onEdit() simple trigger that saves the edit time to the Properties Service (this is done by simply including the onEdit function, which Google interprets automatically). Separately, create a manual trigger to run the doSomething() function every 5 minutes or so. When that function runs, it will check the last edit time and execute your desired actions if the difference between the last edit and now is greater than or equal to your desired length.
function onEdit(e) {
var triggerTime = new Date();
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperty("lastTrigger", triggerTime);
}
function doSomething() {
var scriptProperties = PropertiesService.getScriptProperties();
var lastTrigger = new Date(scriptProperties.getProperty("lastTrigger"));
var lastTriggerUnix = lastTrigger.getTime() / 1000; // using unix time for a more straightforward time comparison
var nowUnix = (new Date()).getTime() / 1000;
var FIFTEEN_MINUTES = 15 * 60;
if ((nowUnix - lastTriggerUnix) >= FIFTEEN_MINUTES) {
scriptProperties.deleteProperty("lastTrigger");
// Do what you need to do here
}
}
You should use the Properties Service to save now, then use a Trigger to run the script every 15 minutes. (The first time you run it, the timings might be slightly off.)
function doSomething() {
var app = SpreadsheetApp ;
var tableur = app.getActiveSpreadsheet() ;
var feuille = tableur.getSheetByName("Sheet2"); // getActiveSheet() can yield unexpected results
var scriptProperties = PropertiesService.getScriptProperties();
var storedNow = scriptProperties.getProperty("now") || new Date(); // Get the stored time. If it doesn't exist, create a new one.
var now = new Date(storedNow); // The value is stored as a String in the Properties Service, so convert to Date.
feuille.getRange("A10").setValue(now);
feuille.getRange("B10:O10").setValue("1000000");
feuille.getRange("P10").setValue("Prudent");
feuille.getRange("Q10").setValue("10");
feuille.getRange("R10").setValue("10");
feuille.getRange("S10").setValue("NON");
now = new Date(); // Create a new date to be used when the function runs again
scriptProperties.setProperty("now", now); // Save the new date
}
As noted in the trigger documentation, you can create the trigger from the Edit menu > Current project's triggers.
I tested this on a 5-minute interval and received the below outputs. As I manually ran the function the first time, its time value is not consistent with the subsequent iterations.
4/6/2018 10:32:15
4/6/2018 10:33:32
4/6/2018 10:38:32
4/6/2018 10:43:32
4/6/2018 10:48:32
I'm working on a Pomodoro-esque timer. The timer must be able to do the following:
When 'Start' button is pressed:
Start 5 second timer. Times will change, of course)
After timer expires, send AJAX event with start and end timestamp
Start a 3 second timer.
After timer expires, start a new 5 second timer. (Loop step 1 to 3 a total of FOUR times)
At the end of the fourth loop, start a 7 second timer.
After the 7 second timer expires, start the 5-3 loop again.
When 'Stop' button is pressed:
Cancel the timer, reset it back to the default state.
This is the code I have now:
HTML
<html>
<head>
<meta charset="UTF-8">
<title>Pomodoro Test</title>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<div id="test"></div>
<div id="timer">5</div>
<button id="start">Start</button>
<button id="reset">Reset</button>
<div id="startTime"></div>
<div id="endTime"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script src="functions.js"></script>
</body>
</html>
JavaScript:
var timer = 5;
var flag = 0;
var startTime;
var endTime;
var intervalTimer;
function update() {
if (timer-- > 0) {
$("#timer").html(timer); // retrieve value from html
} else {
endTime = new Date();
//alert("Start Time = " + startTime + "\nEnd Time = " + endTime);
$("#endTime").html("End time: " + endTime.toTimeString());
resetTimer();
// TODO: send ajax call to server, sending startTime and endTime
// so that these can be saved to database
}
}
function loopingTimer() {
while(flag === 0) {
startTime = new Date();
$("#startTime").html("Start time: " + startTime.toTimeString());
startTimer();
i++;
setTimeout(function() {
if(i < 5) {
loopingTimer();
}
}, 3001)}};
$("#start").click(function() {
loopingTimer();
});
$("#reset").click(function() {
flag = 1;
});
function startTimer() {
intervalTimer = window.setInterval(update, 500);
}
function resetTimer() {
stopTimer();
timer = 5;
$("#timer").text(timer);
}
function stopTimer() {
window.clearInterval(intervalTimer);
}
I find it extremely difficult to get the desired functionality, I've been tinkering with this code for 2 days. I sincerely hope you guys can help me out.
Cake.
The while loop, in the loopingTimer function, does (simplified):
while (userDidntStop) {
startTimer();
}
The break condition is that the user clicks on a button. If the user does so after 500 loopings (a very very very short time), then this loop will have created about 500 timers. The biggest issue is here: avoid running timers (or intervals the same) within loops.
Another issue is that startTime is reset in the almost-infinite loop. You could merge loopingTimer with startTimer, as they do basically a single thing, which is starting the timer, and thus preventing
Also, you use the timer variable to check for the elapsed time. Browsers do not have the obligation to provide the specified delays (at least for setTimeout, according to the MDN documentation. I think it is also the case for setInterval). Therefore, it is safer to instantiate a new Date(), in order to always have the right time.
Also, it is posible to store the sequence of timers somewhere (ie, in an array), to allow modifying this sequence at any time, and also looping easily through it.
Following these points, I would have written something like the following code. Remember that this is an illustration, it might not produce your desired behavior.
var timeLoop = [5, 3, 5, 3, 5, 3, 5, 3, 7]; // seconds
var timeIterator = timeLoop.length;
var startTime;
var endTime;
var intervalTimer;
function sendTimer() { // once the timer ends, send it
// send AJAX request with startTime and endTime here
}
function updateTimer() { // main timer loop
var now = Date.now(); // make sure you have the right time
var diff = endTime - now;
if (diff <= 0) { // if endTime is past, stop and send the timer
diff = 0;
clearInterval(intervalTimer);
sendTimer();
}
// Update the displayed time using diff (ms)
}
function resetTimer() { // to call on $("#reset").click
if (endTime > Date.now()) {
endTime = Date.now();
updateTimer(); // reset the displayed time, and stop updateTimer
// note that this will call sendTimer() with the _aborted_ time
}
}
function startTimer() { // to call on $("#start").click
resetTimer();
// We will loop throught the timeLoop every time we start the timer
if (timeLoop.length < ++timeIterator) {
timeIterator = 0;
}
startTime = Date.now();
endTime = startTime + 1000 * timeLoop[timeIterator];
intervalTimer = setInterval(updateTimer, 500);
}
It's actually a follow up to this question I want to display elements from json based on their time and duration and interval is interupted by settimeout - I accepted the answer there made by #Daniel Flint - his code is quite clear and can be found here http://jsfiddle.net/nauzilus/rqctam5r/
However, there's one more thing that I wanted to add - a simple div <div id="time"></div> that would contain a new date time object initialized during opening the page and then it being incremented every second just to show the current time constantly. I thought about writing there a javascript:
var actualTime = new Date(substractedDate); // taken from the server
function updateTimeBasedOnServer(timestamp) {
var calculatedTime = moment(timestamp);
var dateString = calculatedTime.format('h:mm:ss A');
$('#time').html(dateString + ", ");
};
var timestamp = actualTime.getTime();
updateTimeBasedOnServer(timestamp);
setInterval(function () {
timestamp += 1000; // Increment the timestamp at every call.
updateTimeBasedOnServer(timestamp);
}, 1000);
(I provide the time of the server as a timestamp there).
I just noticed that there is a slight mismatch between displaying the time in my div and between the text appearing on the screen, possibly because I increment both of the values in two different places.
So my question is - how can I "merge" #Daniel Flint's code with mine and increment both values only in one place?
One thing that jumps out here:
timestamp += 1000;
setTimeout/setInterval aren't guaranteed to run at precisely the delay you've entered. Run this in your browsers console:
var last = Date.now(),
time = function() {
var now = Date.now();
console.log(now - last);
last = now;
},
id = setInterval(time, 1000);
On my Mac at home (Chrome/FireFox) it was anywhere from 990 to 1015. Windows machine at work is a bit better (995-1002), but IE was getting up to 1020. It's not a huge difference, but it's not nothing.
So code needs to be able to handle not running exactly every 1000ms. That's why I was running the timer at 500ms intervals, and checking if the start time was less-than-equal to the current time.
I've rejigged the demo to show the time and message in sync:
(function() {
var messages = [];
var time = document.getElementById("current-time");
var display = document.getElementById("message");
function check() {
showMessage(currentMessage());
showTime();
}
function currentMessage() {
var message = null;
if (messages.length) {
var now = toTheSecond(new Date());
var start = toTheSecond(new Date(messages[0].start_time));
var end = toTheSecond(new Date(start.getTime() + ( messages[0].text_duration * 1000 )));
if (start <= now) {
if (end <= now) {
// done with the current message...
messages = messages.slice(1);
// ...but check if there's another one ready to go right now
message = currentMessage();
}
else {
message = messages[0];
}
}
}
return message;
}
function toTheSecond(date) {
date.setMilliseconds(0);
return date;
}
function showMessage(message) {
if (message) {
display.textContent = message.text_content;
}
else {
display.textContent = "no messages";
}
}
function showTime() {
time.textContent = new Date().toLocaleString()
}
function getMessages() {
setTimeout(function() {
var now = new Date();
messages.push(
{"text_content":"aaaaa","text_duration":5,"start_time": new Date(now.getTime() + 3000).toISOString()},
{"text_content":"aawwaaaaa","text_duration":5,"start_time": new Date(now.getTime() + 10000).toISOString()},
{"text_content":"bbaawwaaaaa","text_duration":5,"start_time": new Date(now.getTime() + 15000).toISOString()}
);
}, 1000);
}
setInterval(check, 500);
getMessages();
})();
<span id="current-time"></span> <span id="message">Hello there!</span>
(Putting the code here as well because I recall SO want code in the answers so it's controlled, but there's a demo here: http://jsfiddle.net/nauzilus/ymp0615g/).
This probably isn't as efficient as it could be; the message text is being set every iteration which might cause repaints/reflow. But then again setting the time stamp is going to do that anyway, so meh :)
I want to start a timer when the user clicks on a object, and stop it when the user releases the click. All using javascript/jquery.
The following should get you started
var start_time;
function start() {
start_time = new Date();
}
function end() {
var now = new Date();
alert(now-start_time);
}
$('#element_id').mousedown(start);
$('#element_id').mouseup(end);
the mousedown event will run the start function which sets the start time. the mouseup event will substract the start time from the current time. The result is in milliseconds
$("#element").mousedown(); will let you record when the user clicks, and similarly $("#element").mouseup();will let you record when the button is released.
var start = 0;
$("#element").mousedown(function() { start = new Date(); });
$("#element").mouseup(function() {
var cur = new Date();
alert(cur-start);
}
function myTimer() {
doSomething();
}
$('#thing').mousedown(function() {
$(this).data('timerHandle', setTimeout(myTimer));
});
$('#thing').mouseup(function() {
clearTimeout($(this).data('timerHandle'));
}