JavaScript modifying a variable in one file and reading it in another - javascript

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

Related

How to detect if user has open more than one window or tab on the same session?

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);

My javascript on another site, what domain is it checking cookies for?

I am having some cookie issues and am trying to troubleshoot.
So...
I have a script that I put on other website domains
<script type="text/javascript" src="http://siteA.com/script.php"></script>
Lets say I put this script on siteB
in http://siteA.com/script.php I have it check for a cookie with this code
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) != -1) return c.substring(name.length, c.length);
}
return "";
}
function checkCookie() {
var id = getCookie("mycookiename");
if (id == "1234") {
redirect()
} else {
something()
}
}
So my question is, is this javascript checking for the cookie on siteA or siteB?
(Client-side) JavaScript code (on a webpage) always executes in the context of the document it is loaded into, so it will have access to the cookies belonging to the document.
You could generate the JavaScript using server side code (written in any language you like) and that server side code would have access to the cookies for the URI hosting the JS (and could inject the data into the JavaScript file). (This is usually not a good idea).
It will check on siteB's cookie (the page that is running the code). If it wouldn't it would lead to security issues. Also CDN libraries wouldn't work as they would check the cookie on the CDN's domain, not on the domain you really want to check.

javascript to raise popup window on third page accessed

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);

Update multiple windows via javascript

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();
}
}

How can I swap a div based on a cookie using Javascript?

I'm updating a wordpress site for a customer. I've had to turn on server side caching because the site is so slow due to so many plugins. There is nothing I can do about this and can't disable the plugins.
One of the plugins requires the user to enter an email to download a file. If the plugin sees a valid email, it sets a session variable. Then the page reloads. If that session variable is set, the site displays a download button rather than the enter email form field and button.
Since server side caching is enabled, this functionality is lost. So, what I want to do is set a cookie instead, then check that cookie client side, and swap the content of the div ( id="download" ). I don't do much with Javascript and am having trouble getting this working.
I've set the cookie like this in PHP:
setcookie( 'show_download', 1 );
I've set the new content of the div ( dynamically generated ) like this:
setcookie( 'new_content', '<div class="btn-ss-downloads"><a target="_blank" href="/wp-content/plugins/ss-downloads/services/getfile.php?file=4v-zR6fc6f/9vaROBr/dTJd/Tg/D 0-dT.vBx">Download Series 20 Datasheet</a></div>' );
I've got a function to read the cookie in Javascript that I got from another post:
<script type="text/javascript">
function readCookie(name) {
var ca = document.cookie.split(';');
var nameEQ = name + "=";
for(var i=0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1, c.length); //delete spaces
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return "";
}
</script>
The functionality that seems correct is to call readCookie( 'show_download' );. If the value = 1, swap the content of <div id="download"></div> with the content stored in the new_content cookie.
How do I make this work in Javascript given the pieces I have presented here? I'd like to just add a javascript function to my Wordpress header if that will work here. It seems that I could just run this function after the page has rendered / loaded. I'm not terribly familiar with the order of operations with the browser and javascript. Please help.
Is this what you're looking for?
(<head>)
<script type='text/javascript'>
var showDownload = localStorage.getItem("showDownload") //or readCookie()
if (showDownload == 1) {
$(document).ready(function(){
$("div.btn-ss-downloads").html("<a target='_blank'...</a>")
)};
}
</script>
(</head>)
See http://api.jquery.com/html/ and https://developer.mozilla.org/en/DOM/Storage#localStorage
This uses jQuery, which you can include using:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.pack.js"></script>
(This is one of the few times I'd advocate using jQuery for something so simple, because $(document).ready is so nice!)
Why are you not considering AJAX?
If the requirement is to check validity of an address and then do certain server actions to display a button back, it looks like a good place to use AJAX.
$.post("downloader.php", { eml: mail_id })
.done(function(data){
if(data != "")
$("div.btn-ss-downloads").html('Download');
});
This assumes the downloader.php does the necessary checks and returns the download URL. You can separate this logic (which seems to be part of the main page now) into downloader.php

Categories