Is it possible to cause the browser to cache a user action? - javascript

I've added a button on a website so the user can leave it in "night mode". But if he goes to a new story, the site will have night mode turned off.
Is it possible to have the browser cache this information, so that once it leaves the mode in night mode, the other news it accesses are already with this class?
var menu = document.querySelector('body.single-news');
var button = document.querySelector('button#skin-btn');
button.addEventListener('click', function() {
var open = menu.classList.contains('light-skin');
menu.classList.toggle('light-skin');
});
Removing the "light-skin" class activates the night mode.

You can see a few examples on how to do so using localStorage and sessionStorage here.
But generally, you can create a custom variable stored by the browser.
The localStorage object has no expiration date whereas the sessionStorage object is deleted when the browser tab in question is closed.
Usage:
localStorage.setItem("myVariableName", "myVariableValue");
or
localStorage.myVariableName = "myVariableValue";
and retrieved via
var x = localStorage.getItem("myVariableName");
or
var x = localStorage.myVariableName;
The syntax for sessionStorage is identical.

Related

Javascript: How to make sure window.open returns same window, if already opened

I am working on a web based application, in which I have to open popup window. I am using window.open() method to open the popup, like this:
window.open(url, "popupWin");
where url contains the URL I would like my popup window to navigate to. Now, the problem is, if I execute window.open() from multiple tabs (with same or different URLs), at least on Chrome, it might / might not give you the same window which was opened earlier. This behaviour is inconsistent, I mean, either it should get me fresh window every time, or it should get me previously opened window every time.
I need to persist the same popup window for entire domain. How can I do that?
Well looks like there is a direction to go or at least to give it a try.
It fully remains on localStorage which gives you ability to share the knowledge across your tabs within a single domain.
The code I give below does not work yet (it is only a direction), so don't expect too much from running it as it is.
What it does: it saves the popups by the url in a localStorage and when you try to open a new one with the same url it won't do that. If you don't want to distinguish them by URL it is even simpler: store boolean in a localStorage instead of an object.
What it does not do but should:
it should listen to the popup onunload (close) event and reset the localStorage information accordingly. Best for you here is just to set your localStorage boolean value to false
it should listen to the current tab onunload (reload, close) event and also reset something according to Your logic. As I understand the best for you would be just check whether this tab is the last one from your domain (you can also do this using localStorage, e.g. on every new tab adding its identifier, e.g. creation timestamp and destroying it on tab close) and if it is set your localStorage boolean value to false.
This, I think, would be enough to solve the problem. And finally a small piece of code:
// get the localstorage url map
function getOpenPopups() {
var obj = localStorage.getItem('mypopups');
return obj ? JSON.parse(obj) : {};
}
// set the localstorage url map
function setOpenPopups(object) {
localStorage.setItem('mypopups', JSON.stringify(object))
}
// open the popup
function popup(url, title) {
var popups = getOpenPopups();
// check whether popup with this url is already open
// if not then set it and open the popup
if (!popups[url]) {
popups[url] = true;
setOpenPopups(popups);
return window.open('abc', 'cde');
}
else {
return false;
}
}
jsFiddle
From w3c documentation we can see that window.open() returns a reference to the newly created window, or null if the call failed. That means we can keep it in memory and check for closed flag of that window.
var newWindow = window.open('/some/path', 'TestWindow');
// ...
if (!newWindow.closed) {
}
Keep in mind that if window with following name exists, page will be loaded in the same window without opening new one.
Other variants of name parameter like _blank, _self, _top, _parent you can find in official docs too.

sessionStorage is gone when browser is refreshed - Javascript

I am trying to keep some data in sessionStorage, but if I refresh the page or leave from a link then come back, the sessionStorage no longer exists.
I am new to sessionStorage, so sorry if this is an obvious fix.
Essentially I store an array into the sessionStorage.
$scope.addPlant = function(plant) {
for (i = 0; i < $scope.userPlantList.length; i++) {
if ($scope.userPlantList[i] === plant) {
alert("You have already added this plant");
return;
}
}
$scope.userPlantList.push($scope.currentPlant);
sessionStorage.setItem("Plants",JSON.stringify($scope.userPlantList));
};
And then when I want to see what is all stored
$scope.retreiveList = function() {
var retrieved = sessionStorage.getItem("Plants");
$scope.userPlantList = JSON.parse(retrieved);
}
And this works fine when I do not refresh the page/app at all.
Question: How can I get my sessionStorage to last during a refresh/immediate re-visit?
Check if the data are really gone by looking at the developer tools
If you using chrome: F12 -> Resources tab -> Session Storage.
sessionStorage lives with the browser tab. whenever you close a tab the sessionstorage data will be wiped out.
if you want something that will be shared across tabs, look for localStorage.
I would recommend using the $window provider from angular
// set
$window.sessionStorage.setItem('Plants', angular.toJson($scope.userPlantList));
// get
$scope.userPlantList = angular.fromJson($window.sessionStorage.getItem('Plants')) || [];

How do you detect and prevent a user from accessing a web app from multiple browser tabs using php/javascript?

I have a web app that I would like to restrict to a single browser tab or window. So the idea is a user logs in and if they open a link in a tab/window or open a new browser tab/window it kills their session. I know many are against this but that's how the app needs to be.
The controller checks if the user is logged in via:
if (!isset($_SESSION['user_logged_in'])) {
Session::destroy();
header('location: '.URL.'login');
}
I have tried setting $_SESSION['user_logged_in'] to false if its true but then obviously you don't go any further than one page.
Is there a way to destroy the session when a new browser tab or window is opened? I'm guessing probably jquery/javascript but not across that side of things.
It's very complex to achieve, unfortunately.
And almost impossible to do it true cross-browser and supported by every browser.
Technically, every new browser tab doesn't differ from the latter, form server's point of view. They share cookies and session too.
The only things that differ is JavaScript session. Say, an example: a site that is fully AJAX-based. First page is always login page. Then everything's changed with AJAX. If you dare to open another tab with this site it will open the first page which is always logging you out be default, for example. This can make it possible, but it's very complex.
New technologies stack like localStorage might make this possible, where you can communicate between tabs sending messages in localStorage. But this isn't fully cross-browser and isn't supported by all browsers versions.
So if you are ok with only limited choice of latest browsers — then dig on localStorage and postMessage.
Just to piggy back on what Oleg said, it would be incredibly difficult since HTTP is stateless and browser tabs share data. One potential way of doing it COULD be on the front end, but a very specific set of circumstances would need to be present and they could easily be bypassed. IF the application is a SPA and the primary body is only loaded once, you could potentially generate a key on the body load and send that with each request. Then, if the body is reloaded (say in a new tab or new window), you could generate a new key which would start a new session.
However, the real question is why you would want to do this. Your user experience will suffer and no real security gains exist.
I have some solution and I want share it with you.
To restrict user to only one tab per session, you may use cookie. I describe here how you may build your webapp in order to archieve that goal.
Each time the web module needs to render the auth/login page, create and store a cookie with a given name. Let's call it browserName. The value of the cookie must be a generated value. You may use java.util.UUID if your programming language is java.
When the browser finished loading your auth/login page, set the browser's name with the generated cookie value. You have to know how to read cookie using JavaScript.
Each time the user load other page than auth/login page, check whether the current browser's name is that one stored in the cookie. If they are differents, prompt user and then you can run a snipt that reset session and redirect to auth/login page.
The following is an example of implementing what I've said.
Snipt to be added in the method that runs before your login page in shown Map<String, Object> v$params = new TreeMap<>();
v$params.put("path", "/");
FacesContext.getCurrentInstance()
.getExternalContext()
.addResponseCookie("browserName", UUID.randomUUID().toString(), v$params);
The mini JavaScript library that help you with cookie and other. Add it globally in your webapp.
/**
* http://stackoverflow.com/questions/5639346/shortest-function-for-reading-a-cookie-in-javascript
*/
(function() {
function readCookie(name, c, C, i) {
if (cookies) {
return cookies[name];
}
c = document.cookie.split('; ');
cookies = {};
for (i = c.length - 1; i >= 0; i--) {
C = c[i].split('=');
cookies[C[0]] = C[1];
}
return cookies[name];
}
window.readCookie = readCookie; // or expose it however you want
})();
// function read_cookie(k,r){return(r=RegExp('(^|;
// )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
function read_cookie(k) {
return (document.cookie.match('(^|; )' + k + '=([^;]*)') || 0)[2];
}
/**
* To be called in login page only
*/
function setupWebPage(){
window.name = read_cookie("browserName");
}
/**
* To be called in another pages
*/
function checkWebPageSettings(){
var curWinName = window.name;
var setWinName = read_cookie("browserName");
if( curWinName != setWinName){
/**
* You may redirect the user to a proper page telling him that
* your application doesn't support multi tab/window. From this page,
* the user may decide to go back to the previous page ou loggout in
* other to have a new session in the current browser's tab or window
*/
alert('Please go back to your previous page !');
}
}
Add this to your login page <script type="text/javascript">
setupWebPage();
</script>
Add this to your other page template <script type="text/javascript">
checkWebPageSettings();
</script>

How to delete a localStorage item when the browser window/tab is closed?

My Case: localStorage with key + value that should be deleted when browser is closed and not single tab.
Please see my code if its proper and what can be improved:
//create localStorage key + value if not exist
if (localStorage) {
localStorage.myPageDataArr = {
"name" => "Dan",
"lastname" => "Bonny"
};
}
//when browser closed - psedocode
$(window).unload(function() {
localStorage.myPageDataArr = undefined;
});
should be done like that and not with delete operator:
localStorage.removeItem(key);
Use with window global keyword:-
window.localStorage.removeItem('keyName');
You should use the sessionStorage instead if you want the key to be deleted when the browser close.
You can make use of the beforeunload event in JavaScript.
Using vanilla JavaScript you could do something like:
window.onbeforeunload = function() {
localStorage.removeItem(key);
return '';
};
That will delete the key before the browser window/tab is closed and prompts you to confirm the close window/tab action. I hope that solves your problem.
NOTE: The onbeforeunload method should return a string.
localStorage.removeItem(key); //item
localStorage.clear(); //all items
There is a very specific use case in which any suggestion to use sessionStorage instead of localStorage does not really help.
The use-case would be something as simple as having something stored while you have at least one tab opened, but invalidate it if you close the last tab remaining.
If you need your values to be saved cross-tab and window, sessionStorage does not help you unless you complicate your life with listeners, like I have tried.
In the meantime localStorage would be perfect for this, but it does the job 'too well', since your data will be waiting there even after a restart of the browser.
I ended up using a custom code and logic that takes advantage of both.
I'd rather explain then give code. First store what you need to in localStorage, then also in localStorage create a counter that will contain the number of tabs that you have opened.
This will be increased every time the page loads and decreased every time the page unloads. You can have your pick here of the events to use, I'd suggest 'load' and 'unload'.
At the time you unload, you need to do the cleanup tasks that you'd like to when the counter reaches 0, meaning you're closing the last tab.
Here comes the tricky part: I haven't found a reliable and generic way to tell the difference between a page reload or navigation inside the page and the closing of the tab.
So If the data you store is not something that you can rebuild on load after checking that this is your first tab, then you cannot remove it at every refresh.
Instead you need to store a flag in sessionStorage at every load before increasing the tab counter.
Before storing this value, you can make a check to see if it already has a value and if it doesn't,
this means you're loading into this session for the first time, meaning that you can do the cleanup at load if this value is not set and the counter is 0.
use sessionStorage
The sessionStorage object is equal to the localStorage object, except that it stores the data for only one session. The data is deleted when the user closes the browser window.
The following example counts the number of times a user has clicked a button, in the current session:
Example
if (sessionStorage.clickcount) {
sessionStorage.clickcount = Number(sessionStorage.clickcount) + 1;
} else {
sessionStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "You have clicked the button " +
sessionStorage.clickcount + " time(s) in this session.";
Try using
$(window).unload(function(){
localStorage.clear();
});
Hope this works for you
There are five methods to choose from:
setItem(): Add key and value to localStorage
getItem(): Retrieve a value by the key from localStorage
removeItem(): Remove an item by key from localStorage
clear(): Clear all localStorage
key(): Passed a number to retrieve nth key of a localStorage
You can use clear(), this method when invoked clears the entire storage of all records for that domain. It does not receive any parameters.
window.localStorage.clear();
for (let i = 0; i < localStorage.length; i++) {
if (localStorage.key(i).indexOf('the-name-to-delete') > -1) {
arr.push(localStorage.key(i));
}
}
for (let i = 0; i < arr.length; i++) {
localStorage.removeItem(arr[i]);
}
8.5 years in and the original question was never actually answered.
when browser is closed and not single tab.
This basic code snippet will give you the best of both worlds. Storage that persists only as long as the browser session (like sessionStorage), but is also shareable between tabs (localStorage).
It does this purely through localStorage.
function cleanup(){
// place whatever cleanup logic you want here, for example:
// window.localStorage.removeItem('my-item')
}
function tabOpened(){
const tabs = JSON.parse(window.localStorage.getItem('tabs'))
if (tabs === null) {
window.localStorage.setItem('tabs', 1)
} else {
window.localStorage.setItem('tabs', ++tabs)
}
}
function tabClosed(){
const tabs = JSON.parse(window.localStorage.getItem('tabs'))
if (tabs === 1) {
// last tab closed, perform cleanup.
window.localStorage.removeItem('tabs')
cleanup()
} else {
window.localStorage.setItem('tabs', --tabs)
}
}
window.onload = function () {
tabOpened();
}
window.onbeforeunload = function () {
tabClosed();
}
why not used sessionStorage?
"The sessionStorage object is equal to the localStorage object, except that it stores the data for only one session. The data is deleted when the user closes the browser window."
http://www.w3schools.com/html/html5_webstorage.asp
Although, some users already answered this question already, I am giving an example of application settings to solve this problem.
I had the same issue. I am using https://github.com/grevory/angular-local-storage module in my angularjs application. If you configure your app as follows, it will save variable in session storage instead of local storage. Therefore, if you close the browser or close the tab, session storage will be removed automatically. You do not need to do anything.
app.config(function (localStorageServiceProvider) {
localStorageServiceProvider
.setPrefix('myApp')
.setStorageType('sessionStorage')
});
Hope it will help.
Here's a simple test to see if you have browser support when working with local storage:
if(typeof(Storage)!=="undefined") {
console.log("localStorage and sessionStorage support!");
console.log("About to save:");
console.log(localStorage);
localStorage["somekey"] = 'hello';
console.log("Key saved:");
console.log(localStorage);
localStorage.removeItem("somekey"); //<--- key deleted here
console.log("key deleted:");
console.log(localStorage);
console.log("DONE ===");
} else {
console.log("Sorry! No web storage support..");
}
It worked for me as expected (I use Google Chrome).
Adapted from: http://www.w3schools.com/html/html5_webstorage.asp.
I don't think the solution presented here is 100% correct because window.onbeforeunload event is called not only when browser/Tab is closed(WHICH IS REQUIRED), but also on all other several events. (WHICH MIGHT NOT BE REQUIRED)
See this link for more information on list of events that can fire window.onbeforeunload:-
http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
After looking at this question 6 years after it was asked, I found that there still is no sufficient answer to this question; which should achieve all of the following:
Clear Local Storage after closing the browser (or all tabs of the domain)
Preserve Local Storage across tabs, if at least one tab remains active
Preserve Local Storage when reloading a single tab
Execute this piece of javascript at the start of each page load in order to achieve the above:
((nm,tm) => {
const
l = localStorage,
s = sessionStorage,
tabid = s.getItem(tm) || (newid => s.setItem(tm, newid) || newid)((Math.random() * 1e8).toFixed()),
update = set => {
let cur = JSON.parse(l.getItem(nm) || '{}');
if (set && typeof cur[tabid] == 'undefined' && !Object.values(cur).reduce((a, b) => a + b, 0)) {
l.clear();
cur = {};
}
cur[tabid] = set;
l.setItem(nm, JSON.stringify(cur));
};
update(1);
window.onbeforeunload = () => update(0);
})('tabs','tabid');
Edit: The basic idea here is the following:
When starting from scratch, the session storage is assigned a random id in a key called tabid
The local storage is then set with a key called tabs containing a object those key tabid is set to 1.
When the tab is unloaded, the local storage's tabs is updated to an object containing tabid set to 0.
If the tab is reloaded, it's first unloaded, and resumed. Since the session storage's key tabid exists, and so does the local storage tabs key with a sub-key of tabid the local storage is not cleared.
When the browser is unloaded, all session storage will be cleared. When resuming the session storage tabid won't exists anymore and a new tabid will be generated. Since the local storage does not have a sub-key for this tabid, nor any other tabid (all session were closed), it's cleared.
Upon a new created tab, a new tabid is generated in session storage, but since at least one tabs[tabid] exists, the local storage is not cleared
This will do the trick for objects.
localStorage.removeItem('key');
Or
localStorage.setItem('key', 0 );
You can simply use sessionStorage. Because sessionStorage allow to clear all key value when browser window will be closed .
See there : SessionStorage- MDN
This is an old question, but it seems none of the answer above are perfect.
In the case you want to store authentication or any sensitive information that are destructed only when the browser is closed, you can rely on sessionStorage and localStorage for cross-tab message passing.
Basically, the idea is:
You bootstrap from no previous tab opened, thus both your localStorage and sessionStorage are empty (if not, you can clear the localStorage). You'll have to register a message event listener on the localStorage.
The user authenticate/create a sensitive info on this tab (or any other tab opened on your domain).
You update the sessionStorage to store the sensitive information, and use the localStorage to store this information, then delete it (you don't care about timing here, since the event was queued when the data changed). Any other tab opened at that time will be called back on the message event, and will update their sessionStorage with the sensitive information.
If the user open a new tab on your domain, its sessionStorage will be empty. The code will have to set a key in the localStorage (for exemple: req). Any(all) other tab will be called back in the message event, see that key, and can answer with the sensitive information from their sessionStorage (like in 3), if they have such.
Please notice that this scheme does not depend on window.onbeforeunload event which is fragile (since the browser can be closed/crashed without these events being fired). Also, the time the sensitive information is stored on the localStorage is very small (since you rely on transcients change detection for cross tab message event) so it's unlikely that such sensitive information leaks on the user's hard drive.
Here's a demo of this concept: http://jsfiddle.net/oypdwxz7/2/
There are no such the way to detect browser close so probably you can't delete localStorage on browser close but there are another way to handle the things you can uses sessionCookies as it will destroy after browser close.This is I implemented in my project.
if(localStorage.getItem("visit") === null) {
localStorage.setItem('visit', window.location.hostname);
console.log(localStorage.getItem('visit'));
}
else if(localStorage.getItem('visit') == 'localhost'){
console.log(localStorage.getItem('visit'));
}
else {
console.log(localStorage.getItem('visit'));
}
$(document).ready(function(){
$("#clickme").click(function(){
localStorage.setItem('visit', '0');
});
});
window.localStorage.removeItem('visit');
window.addEventListener('beforeunload', (event) => {
localStorage.setItem("new_qus_id", $('.responseId').attr('id'));
var new_qus_no = localStorage.getItem('new_qus_id');
console.log(new_qus_no);
});
if (localStorage.getItem('new_qus_id') != '') {
var question_id = localStorage.getItem('new_qus_id');
} else {
var question_id = "<?php echo $question_id ; ?>";
}
you can try following code to delete local storage:
delete localStorage.myPageDataArr;

Js - detect if was page called from history [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can you detect/redirect a back button press through javascript?
I am developing a small web application. In my application I must know when the user clicks the "back" button, so I can run some javascript code. Is there any such way to detect it?
thank you
Ok, so I discovered that the JS API cannot access the history object's next property without elevated permissions, which got me thinking in another direction.
Form fields are automatically fetched from the browser's cache, thus holding historic data. while this is true, javascript code is run independently each time.
So I created a small hidden field to hold a timestamp and compare it against the javascript's generated datatime.
Here is the code, I am sure it can be much better implemented, though time is short:
$(document).ready(function () {
var date = new Date();
var clientMiliseconds = date.getTime();
clientMiliseconds = roundTime(clientMiliseconds);
var serverTimeStamp = $('#' + '<%= hfTimeStamp.ClientID %>').val();
serverTimeStamp = roundTime(serverTimeStamp);
alert(serverTimeStamp == clientMiliseconds);
});
function roundTime(time) {
time = Math.floor(time);
//since the server renders the time components a few seconds before the page is downloaded
//which also depends on where you assign the date on the serverside
//we've got a small inaccuracy of few seconds. we neglect these seconds, assuming that it would take the user
//a few seconds to click the back button
time = time / 10000;
time = Math.floor(time);
return time;
}
You can't do that. you can bind an event so that something happens when your user navigates away from the page (use onbeforeunload or unload() to do that) but there is no way to know where he has gone

Categories

Resources