My site has a timeout set, so after 15 minutes of in-activity a login screen appears asking you to refresh your session.
This works great, but if you have more than one window open on the site it means one page will be refreshed with the login details but the other one will not.
So the question is this, is there a way to execute the following code on each window open at the site?
$jq('#loginbox').hide()
Thanks for any help. I should also state that the other windows will not be opened via JavaScript, the user could have just clicked open in new window / tab on a link
You cannot access windows you didn't open yourself with JS.
Each window should detect that it timed out and display a login dialog. If a user logs in in window A, then window B should be polling the server to detect if a session has been created, and restore itself in that case.
Before you switch to the refresh screen (popup?) you can simply do an ajax call to the server to see the last time the user refreshed - if the user is still legitimately logged in, just reset the timer to the proper time.
If the other window is not opened via JavaScript, you won't be able to access it programmatically. In other words, the original window is not going to be able to call JavaScript functions on the other window.
However, the windows can share cookies if they have the same domain (if they're on the same website). So one possibility would be to have the other window poll for updates to a session cookie, which the original window could write to. Once the session cookie obtained a particular value, the other window could detect this change and react as you saw fit.
Thanks to everyone who posted ideas, I went for the following solution, if anyone can enhance it and post code then I'll accept that as the answer:
$jq(function(){
$jq(window).bind('blur', function(){checkloginrefreshed();});
$jq(window).bind('focus', function(){checkloginrefreshed();});
$jq(document).bind('focusout', function(){checkloginrefreshed();});
$jq(document).bind('focusin', function(){checkloginrefreshed();});
});
function createCookie(name,value,hours) {
if (hours) {
var date = new Date();
date.setTime(date.getTime()+(hours*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name) {
createCookie(name,"",-1);
}
function checkloginrefreshed(){
if (parseInt(readCookie("loginset")) == 1){
eraseCookie("loginset");
$jq('#timeoutwarning').dialog("close");
$jq('#timeoutwarning').html(TIMEOUTLOGINFORM);
clearTimeout(timer);
clearTimeout(timerWarning);
setupTimers();
}
}
Related
We use an internal system (with FF as default browser)
We need to avoid that the user open the same URL in different tabs.
As the tabs share the same PHP session we get a mess.
So actually I'm looking to the way to check programmatically if certain URL is already opened in one of the opened tabs.
Client side (JS) or server side (PHP).
We use now the FF extension "Duplicate Tabs Closer" that helps.
But I'd prefer to keep full control (give warning, choose for which URL it works).
You can write cookie after your page loaded in the first tab, check it on the server side and show the user warning instead of actual page content if this cookie is set and the second tab is opened. To handle the case when a user closes the only opened tab you can remove that cookie in onbeforeunload handler.
Working off of Oleksandr's answer, you can store a map of number of times a url is opened, in a cookie. When a page is opened, increment the number or set it to 0. When a page is closed, decrement it or delete it.
function incrementTabsOpen() {
let tabsOpen = readObjCookie('tabsOpen') || {};
if (tabsOpen[window.location.href]) tabsOpen[window.location.href]++;
else tabsOpen[window.location.href] = 0;
writeObjCookie('tabsOpen', tabsOpen);
}
function decrementTabsOpen() {
let tabsOpen = readObjCookie('tabsOpen') || {};
if (tabsOpen[window.location.href]) tabsOpen[window.location.href]--;
if (tabsOpen[window.location.href] === 0) delete tabsOpen[window.location.href];
writeObjCookie('tabsOpen', tabsOpen);
}
// https://stackoverflow.com/a/11344672/3783155
function readObjCookie(name) {
let result = document.cookie.match(new RegExp(name + '=([^;]+)'));
if (result) result = JSON.parse(result[1]);
return result;
}
function writeObjCookie(name, value) {
document.cookie = name + '=' + JSON.stringify(value);
}
and
window.addEventListener('load', function() {
incrementTabsOpen();
};
window.addEventListener('unload', function() {
decrementTabsOpen();
};
Is there any way to modify a global var within a function and then using it in another page? Let me explain better my situation: I have two HTML files, "Index.html" and "character.html". In Index, I have related this JS code:
var pcharacter = "initialValue";
document.getElementById("barbarianClass").onclick = function(event){
event.preventDefault();
pcharacter = "barbarian"; // the important line here...
location.href = "pages/character.html";
}
The element "barbarianClass" is a link, that's why I blocked the default behavior with preventDefault() until I have given a value to my pcharacter var. Now, I have character.html, that has the following one single JS line code attached:
alert(pcharacter);
In character.html, I have both JS files related, how it should be done:
<script type="text/javascript" src="indexCode.js"></script>
<script type="text/javascript" src="charsCode.js"></script>
The problem is that when I click the link "barbarianClass" and my character.html page shows, the var pcharacter showed in the alert is "initialValue", even when I said it to have the value "barbarian" inside the event attached to the link before opening the page. Of course, I have plans for that variable, but for the question, the alert is easier. Could someone, please, tell me why the initialValue is kept? Is there any obscure rule in JS that says that when you load a JS document, global vars can't be changed anymore or something like that? I doesn't make any sense...
Ummmmmmm...well....banking problems aside :-)
To answer your question - the answer is both yes and no. If what you are going to do is to directly load in a new web page then no - your global variables will disappear like cotton candy at a carny show.
BUT! If instead, you use jQuery's getScript() function, then you can load in a new web page and keep your global variables. All you have to do is to convert your incoming web page into hexadecimal so all of the different letters like the less than sign, single, and double quotes don't muck things up, unconvert it once you have it, and then replace your web page or insert your web page/part as you wish.
To convert it to hex all you need is the bin2hex() function in PHP. To unhex something in Javascript you can go and get my toHex() and fromHex() functions on GitHub.
Also, you might want to think about sending everything back to the server in hex as well so script kiddies have a bit harder time giving themselves a +1000 weapon. Just a thought. It won't slow them down a lot - but every little bit helps. :-)
You can save data in cookie
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
}
return "";
}
http://www.w3schools.com/js/js_cookies.asp
your code will be
/*save data*/
document.getElementById("barbarianClass").onclick = function(event){
event.preventDefault();
setCookie('pcharacter', 'barbarian', 1)
location.href = "pages/character.html";
}
/*get data*/
alert(getCookie('pcharacter'));
What you are trying to do is simply not possible with variables alone , as for the reason highlighted by someone in your comments
Lets assume this is possible - would you want the page that has your bank details being accessed via javascript variables on a different page?
You should use cookies (client-side) or sessions(server-side) to accomplish this task. This is how you set a cookie in javascript:
document.cookie = "pcharacter=barbarian"
and then you can access this cookie in all other pages by this simple function :
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) == 0) return
c.substring(name.length,c.length);
}
return "";
}
console.log(getCookie("pcharacter"));
You can also set an expiry time for your cookies .
You can use localStorage to pass data from one file to another. The basic syntax is:
if (typeof(Storage) !== "undefined") {
// Code for localStorage/sessionStorage.
} else {
// Sorry! No Web Storage support..
}
Setting a value:
localStorage.setItem('myObj', 'My Object');
And getting a value:
localStorage.getItem('myObj');
If localStorage is not supported, you can always fall back to one of the cookies or URL rewriting.
otherwise you can use window.name also
I would like to detect if user has open more than one window or tab on the same session and if he did it - I would like to print an special information on screen.
This limte should oblige only in one special URL, so if user has open two tabs/windows with urls: http://page.com/limite.htm - I would like to print special information. When user has open two windows/tabs with urls: http://page.com/limite.htm and http://page.com/index.htm - everything is OK and I wouldn't show any informations.
Is it possible?
Thanks.
I think the best way to do it is with localStorage. http://www.gwtproject.org/doc/latest/DevGuideHtml5Storage.html
From the link, about localStorage:
Availability to other Windows/tabs: Shared across every window and tab of one browser running same web app
So, you could set an entry when the tab/window is open, and change it when it's closed. When another tab/window is open, you first check this entry value.
Obviously you need to be careful: browser crashes, for example, might not trigger the "on close" part, so the user wouldn't be able to open a new tab, even with none open (localStorage persists!). If you have server sessions, you can ask the user to login again (or run your auth process again), and reset this value. You can also try to use a sessionStorage entry to keep track of this kind of problem. From the link, about sessionStorage:
Persistence: Survives only as long as its originating window or tab.
Also, there is something called "Cross window messaging", that allow you communicate between tabs, but check if it's supported on the browsers you want to support.
http://ajaxian.com/archives/cross-window-messaging-with-html-5-postmessage
I have done something very similar today. I hope this helps.
// helper function to set cookies
function setCookie(cname, cvalue, seconds) {
var d = new Date();
d.setTime(d.getTime() + (seconds * 1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
// helper function to get a cookie
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
// Do not allow multiple call center tabs
if (~window.location.hash.indexOf('#admin/callcenter')) {
$(window).on('beforeunload onbeforeunload', function(){
document.cookie = 'ic_window_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
});
function validateCallCenterTab() {
var win_id_cookie_duration = 10; // in seconds
if (!window.name) {
window.name = Math.random().toString();
}
if (!getCookie('ic_window_id') || window.name === getCookie('ic_window_id')) {
// This means they are using just one tab. Set/clobber the cookie to prolong the tab's validity.
setCookie('ic_window_id', window.name, win_id_cookie_duration);
} else if (getCookie('ic_window_id') !== window.name) {
// this means another browser tab is open, alert them to close the tabs until there is only one remaining
var message = 'You cannot have this website open in multiple tabs. ' +
'Please close them until there is only one remaining. Thanks!';
$('html').html(message);
clearInterval(callCenterInterval);
throw 'Multiple call center tabs error. Program terminating.';
}
}
callCenterInterval = setInterval(validateCallCenterTab, 3000);
}
LocalStorage won't work across protocols - so if the user has your site open in one tab using http, and another tab using https, both those tabs will see separate localStorage objects. Cookies don't have the same issue (they have other issues, e.g. inflating the size of every http request back to your website)
The sample code below maintains a map where the key is a unique browser tab identifier and the value is a timestamp indicating when that tab last confirmed it was still open. The map is stored in a cookie. Its not a perfect approach - each tab updates itself every 3 seconds rather than instantly, and there are race conditions (multiple tabs updating the same cookie) but depending what you're after this may do the trick.
If you ran this code on just a specific page you'd (more or less) know when that page was open more than once in the same browser. Or run it on every page of your website and know when your website was open in multiple tabs.
Cookie reading/writing code is omitted for brevity (but taken from https://stackoverflow.com/a/24103596/4486628), and the encoding of the data in the cookie is done with json for simplicity, but you get the idea.
If you run this code and watch the cookies using FireBug's cookie tab you can see the cookie updating as tabs are opened and closed. Actually doing something like alerting the user when multiple tabs are open is left as an exercise for the reader.
var timePeriod = 3000; // 3 seconds
function tabHandler() {
// ensure the current window has an identifier set
if (!window.name.match(/^MySite[0-9]{3}/)) {
window.name = 'MySite' + Math.round(Math.random() * 1000);
}
// read in the state of all the tabs
var tabCookie = readCookie('tabs') || null;
var tabs = JSON.parse(tabCookie) || {};
// update the timestamp for the current tab
var now = (new Date()).getTime();
tabs[window.name] = now;
// remove tab details that haven't had their timestamp updated
var tooOld = timePeriod * 2;
for (var tabKey in tabs) {
if ((now - tabs[tabKey]) > tooOld) {
delete tabs[tabKey];
}
}
// write back the current state of tabs
createCookie('tabs', JSON.stringify(tabs), 1);
setTimeout(tabHandler, timePeriod);
}
setTimeout(tabHandler, timePeriod);
I have a website created using laravel. I want the user to be able to see a popup the first time he comes to my site.
By first time I mean- the user comes to any page on my site(this is first time), visits some of the linked pages on site(now, these page visits are not first time), opens facebook in the same tab(thus leaving my site) and then again opens my site in the same tab(this is first time again).
The basic reason behind one time popping up is not to bother the user again and again while he is navigating the site. But, once he leaves and comes back again, then I want to treat it like a new visit(and show the pop up again).
I know I can do popup thing with setTimeout() in jQuery. But how to do it just once? Please note that, the pop can appear on any page(if its first page of the current visit), not only on the home page.
you could use document.referrer, and check if the previous page is one of your domain. But not all visitors/browsers will return this value for security reasons.
So this is unreliable.
Use a plugin like jQuery Cookie, then simply do:
if(!$.cookie("popup"))
{
your_popup_function();
$.cookie("popup",true);
}
Edit: since you edited your question regarding your definition of "first time visit", I'd advise the approach Walter Brand suggested, using the referrer. Taken from this post:
document.referrer.indexOf(location.protocol + "//" + location.host) === 0;
Solution without using plugins:
var adCookie = document.cookie.indexOf('ad_displayed')
if (adCookie != -1) {
your_popup_function();
document.cookie = "ad_displayed=1";
}
This is the idea, of course you can set expiry date on the cookie. Read more here
Hi i did this solution while solving the client requirement "to show pop-up only once throughout navigating to different pages of the site" and it works good for me.
I did it using cookie and setting the cookie value to the cookie creation time than i make the difference of the cookie value with current time using javascript setInterval function and compare the difference with the time on which i want to show the pop-up and it's work.
$(document).ready(function()
{
var myVar="";
function getCookie(name)
{
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(document.cookie);
return (value != null) ? unescape(value[1]) : null;
}
function callagain()
{
if(!getCookie("magazine"))
{
var c1= new Date();
var c2=c1.getTime();
document.cookie="magazine="+c2;
}
var cvalue= getCookie("magazine");
var cvalue2=parseInt(cvalue);
myVar=setInterval(function(){ call22(cvalue2);},1000);
}
function call22(abcd)
{
var curdate = new Date();
var curtime = curdate.getTime();
var curtime2=parseInt(curtime);
var result=curtime2 - abcd;
if( (result >30000) && (result < 31000) )
{
alert(“POP UP ONCE THROUGHOUT THE SITE”);
clearInterval(myVar);
}
}
callagain();
});
After a person has toured my website for N pages, I would like to raise a popup window asking them if they would like to subscribe to my newsletter.
I've found sample code to raise a popup after a delay of some seconds, I've found samples for asking only once, but not one that can track the number of pages traversed.
Where can I find sample JS code to raise a window after a certain number of pages have been traversed?
My simple minded analysis is that normally each invocation of the script on N pages would be a different invocation, and hence would not have any record of the previous page's invocation. So each copy would have to read a cookie set by the previous copy, increment it, and store back. Then, when N=3 and whatever other conditions I think are appropriate are satisified, the popup is triggered.
Your analysis is correct! You'll need cookies of some sort, whether tracked server side or just good old fashioned javascript cookies.
Here's the best rundown I've seen of how to implement them: Quirksmode Cookies
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name) {
createCookie(name,"",-1);
}
To update the value of the cookie to track page count - again assuming you aren't doing this server-side - you'll need to reset the cookie and set a new one with the new value. Updating/changing a value of an existing cookie just isn't really a supported operation of cookies.
Or you could just create 3 cookies, I guess. Whatever floats your integer ;)
On clicking Links do a push to the HTML5 history API and check length of history. You may also add an eventhandler to all links on your page.
//first 2 paraemeters could be NULL, last is the URL
history.pushState(data, event.target.textContent, event.target.href);
//check length of history
history.length
more abouth HML5 history API: http://html5doctor.com/history-api/
Edit: actually you should not need the push event for ordinary Links, just test it with console.log(history.length);