How to store a variable inside a JavaScript session cookie? - javascript

I want to keep track of how many seconds a user spend on my project website on all of his pages and for doing this I want to use JavaScript session cookies.
This is because I will host it using Github Pages where I have no access to PHP and also because I want to try working with JS cookies (It's the first time I am doing this).
To count the seconds I am using the followings:
var time_spent = 0;
setInterval(function(){
++time_spent;
$('#counter_container span').html(time_spent);
}, 1000);
The above code works where the counter is but as expected is reseting every time I change the page.
I've tried using a js-cookie library (https://github.com/js-cookie/js-cookie) in the following manner:
Cookies.set('time_spent', time_spent);
var counted_time = Cookies.get('time_spent');
console.log(counted_time);
But the counted_time variable is always 'undefined' whatever I've tried.
I would really apreciate any guidance I can get in order to solve this little issue.

I wouldn't use a timer for this. Instead try setting a timestamp when the user enters the page, and then onbeforeunload get the duration and add it to the value stored in the cookie. Something like this:
var load = new Date();
window.onbeforeunload = function() {
var leave = new Date();
var duration = leave.getTime() - load.getTime() / 1000;
var counted_time = parseFloat(Cookies.get('time_spent')) || 0;
Cookies.set('time_spent', counted_time + duration);
}
Working example

Related

How to run a timer on server side

I would like to have a countdown timer always show a countdown for every new user. Basically, if I close the webpage, and reopen it, the timer should still be running. I'm thinking of using the JS variable code functions to define a new client's timezone together with an if statement comment and make it a repeat loop?
Basically, I would want to run a timer on the server side, not the client side.
Has anyone done this before?
Sounds something that you could try to solve with browsers localStorage. If your only requirement is to keep saved time available after you close tab/browser and come back to your page, this is a good fit for you.
Here's a small Codesandbox example code of how to conditionally check and save to localStorage and then start counter based on that value.
https://codesandbox.io/s/4xw97q02m0
EDIT: same code pasted to a post
function setCurrentTime(){
let localStore = window.localStorage.getItem("myTime") // Check if already exists
if(localStore) return localStore
const time = Date.now(); // get current time stamp
window.localStorage.setItem("myTime", time) // Save to localStorage
return time
}
function startCount(){
const time = setCurrentTime()
const elem = document.getElementById("app")
setInterval(() => {
elem.innerHTML = `seconds since time saved:
${Math.floor((Date.now() - time) / 1000)}
`
}, 1000)
}
startCount()
<div id="app"></div>

localStorage doesn't store updated value

I'm writing a script that lets a user know how much time he spent on a page before refreshing it. To this purpose, I increment a time counter with a setInterval function, and store the data in the browser thanks to localStorage. Once the page is refreshed, I retrieve the data stored, and display them. Meanwhile, the time counter goes back to 0 and starts incrementing again.
Unfortunately, something is wrong with my script because localStorage doesn't store the updated time value (it's always -1). What's wrong with my script?
//TimeSpent = -1, so setInterval sets it to 0s instead of 1s when the page opens.
var timeSpent = -1
//Update time every second
var timer = setInterval(()=>{
timeSpent +=1;
}, 1000);
//If first visit, ask to refresh. Else, display timeSpent on previous page by retrieving localStorage data.
function start(){
if (localStorage.timeData){
var timerJson = localStorage.getItem("timeData");
var timerParsed = JSON.parse(timerJson);
console.log(`You spent ${timerParsed.time} seconds on previous page`)
}
else{
console.log("Reload the page and see how much time you spent reading this.")
}
}
//Trig function when page opens.
window.onload = start();
//Before page reloads, store timeSpent in localStorage as a Json file.
var timeData = {
time: timeSpent,
}
function storeData (timeData){
var timerJson = JSON.stringify(timeData)
localStorage.setItem("timeData", timerJson);
}
window.onbeforeunload = storeData (timeData)
Thanks!
window.onbeforeunload must have a value of type function but in your code it is undefined. Hence you should change it to this:
window.onbeforeunload = function storeData (){
var timerJson = JSON.stringify(timeData)
localStorage.setItem("timeData", timerJson);
}
I've also removed the parameter from the function, making it a closure.
UPD. As Jonas Wilms noted, you should do the same wilth onload event and start function.
ALSO. In order to always have the actual (fresh) value of timeSpent, you should do this:
const state = {timeSpent: -1}
And everywhere replace timeSpent with state.timeSpent.
This way the closures will have a link to state object, instead of just taking the initial value of a primitive timeSpent.
This code works well for me:
let timeData = {
time: -1
}
timeData.time = setInterval(()=>{
timeData.time += 1
console.log(timeData.time)
}, 1000);
function start(){
if (localStorage.timeData){
var timerJson = localStorage.getItem("timeData");
var timerParsed = JSON.parse(timerJson);
console.log(`You spent ${timerParsed.time} seconds on previous page`)
}
else{
console.log("Reload the page and see how much time you spent reading this.")
}
}
window.onload = start();
window.onbeforeunload = function () {
var timerJson = JSON.stringify(timeData)
localStorage.setItem("timeData", timerJson);
}
I assume you testing this locally. Since local-storage is stored like a cookie domain based (and you dont have a domain when you test your script locally) the data is simply not saved.
In HTML5, is the localStorage object isolated per page/domain?
Edit: By local i mean a simple Html-File without using a webserver.

How to keep changes made to a class when the page refreshes with Javascript

I have a table of data for the user to look through and make changes. They have the option to delete a row if they want. When they delete a row it sends back to the db what row is to be deleted. For the user the row won't delete right away but it will get a new class 'deleted' that has some styles to let the user know it's being deleted. I also have the page refreshing every 10 minutes and when it refreshes the new added 'deleted' class goes away.
How can I get it that the class will stay on the row when the page refreshes?
Here is the timer function for the timer to know when to refresh the page. I'm using ajax to refresh the page.
function startClock() {
// Get the time to stop the effect
var stopTime = new Date();
stopTime.setMinutes(stopTime.getMinutes() + 10);
// Get a reference to the timer so it can be cancelled later
timer = setInterval(function () {
// Check to see if the timer should stop
var currentTime = new Date();
if (currentTime < stopTime) {
triggerDataTable(); //refresh dataTable
var randomnumber = Math.floor(Math.random() * 100);
} else {
// Stop the timer
clearInterval(timer);
}
}, 600000);
}
Would I use localStorage? If so how would I actually do it? I'm not familiar with storing local values or anything like that.
I'm not 100% sure about this but what about doing something like this:
var deletedRow = $(".deleted");
localStorage.setItem( deletedRow, $(".deleted").val() );
try using sessionstorage over localstorage
Session Storage property maintains a separate storage area for each given origin and for a session .
Local Storage does the same thing, but persists even when the browser is closed and reopened.
sessionStorage.setItem('item', value);
sessionStorage.getItem('item');

"Seen By" feature in Facebook groups

I want to implement a post seen by feature like in FB groups using JS and PHP , I managed to get the seen counts from the scrolling actions but I need to know whether the user just scrolled it down or actually spending time to read it ( some kind of a scroll speed tracker or something similar)
var winTop = $(this).scrollTop();
var $divs = $('.singlePost');
var top = $.grep($divs, function(item) {
return $(item).position().top <= winTop;
});
if (top.length > 0) {
var len = top.length;
var viewingPost = top[len-1]
if( ! $(viewingPost).hasClass("seen")){
var seenData = {"name":"postId", "value":$(viewingPost).attr('data-sharedId')}
parseSeenData( seenData ,viewingPost );
}
}
above is the code which I did to get the seen count,need to get some info regarding user spent enough time on each post to read it.
You could use some sort of timer that times how long each post is "seen" before you actually set it as seen.
Maybe this will help?
I'm thinking you could use something like setTimeout(), and add a view duration property to each post. Use setTimeout to increase the view duration on whatever post is being looked at by one second, every second, and then, after it reaches the value you want, set that post as "seen". Hope this helps, and good luck.

Only listent to last children by date in Firebase

In my app, I use this code to listen only to the children added after the current time:
var start = new Date().getTime();
firebase.database().ref(path).orderByChild('created').startAt(start).on('child_added', function(value){
console.log(value.val());
});
In the browser, this method works well. I see the child only if I start to add it after the current time.
In the smartphone, this method doesn't work. It works only if I start to add a children after a certain amount of seconds. I think that this happens because the current time of the smartphone is different with the current time of the server.
Is there any way to fix this without having to take the last element?
If the clock on your phone is off, this will not work reliably.
Firebase detects the offset of the local clock to the server time and exposes this in a value .info/serverTimeOffset. You can use this to correct for the clock skew as explained in the documentation on clock skew:
var offsetRef = firebase.database().ref(".info/serverTimeOffset");
offsetRef.on("value", function(snap) {
var offset = snap.val();
var estimatedServerTimeMs = new Date().getTime() + offset;
});
Read the linked documentation for a full explanation.

Categories