First off, let me preface this question by saying that my professor is firmly entrenched in the past. Our last assignment required us to float links on top of pictures.
You might also say that he's insane as in order to test our pages he requires that all functionality (including cookies) be implemented with "client side technology" i.e. not on the server. He uses Firefox to test the pages, so the single blessing is that he doesn't care about cross-browser compatibility.
That being said, I'm having a problem with our latest assignment. We're making a "shopping cart" system using Javascript and cookies to store the items to be purchased. This is fine, except for some reason in my function that adds a new element to the cookie, assigning something to document.cookie doesn't work.
You can find my entire site here .zip file download (if there's anything that you wonder, "why on earth would you do that? That's crazy!" - that's either a direct assignment or a way to try and minimize the pain.)
This is my code in question that should be modifying the cookie:
var mycookies = new function (){
var cookies = document.cookie.split(';');
var cookie, values;
this.items = [];
for(var x = 0; x < cookies.length; x++){
if(cookies[x] != ""){
cookie = cookies[x].split('=')[0].trim()
values = cookies[x].split('=')[1]
values = values.split(',');
if(!this.items[cookie]){
this.items.push(cookie);
this[cookie] = new function(){};
}
this[cookie].size = values[0];
this[cookie].qty = parseInt(values[1]);
}
}
this.render = function(){
var values, cookies = "", cookie;
for(var x = 0; x < this.items.length; x++){
cookie = this.items[x];
values = [this[cookie].size, this[cookie].qty].join(',');
cookies += cookie + "=" + values + '; ';
}
return cookies;
}
this.clear = function(){
for(var x = 0; x < this.items.length; x++){
delete this[this.items[x]];
}
this.items = [];
document.cookie['expires'] = '26 Aug 1984 01:01:01 UTC;';
}
this.additem = function(){
var i = document.forms[0].size.selectedIndex;
if (this.items[page]){
this[page].size = document.getElementById('size').value;
this[page].qty = document.getElementById('qty').value;
}
else{
this.items.push(page);
this[page] = new function(){};
this[page].size = document.getElementById('size').value;
this[page].qty = document.getElementById('qty').value;
}
console.log(this.render()); // For use with firebug
document.cookie = this.render();
console.log(document.cookie); // For use with firebug
}
}
When I fire this off, firebug provides this output:
expires=12 Aug 2001 01:01:01 UTC,NaN; whitec=Small,3;
expires=12 Aug 2001 01:01:01 UTC,NaN
Now, I would expect 1) my cookie to have expired (I set the expiration manually through firebug, my parsing added the NaN later, - yet there it stays), and 2) the value for the cookie to be changed to the result of this.render()
Other than the obvious fact that client-side cookie behavior is not guaranteed by the w3 spec, am I missing something here? (EDIT - what I mean is when the page is client-side, opened as a file - not served by a server) This is really aggravating - I've tried a multitude of different angles, and no "javascript cookie" search or "modify cookies javascript" leads me to anything useful. Any suggestions about how I can fix it?
Or should I just email my professor with a link to the w3 specs and tell him that requiring us to support cookies client side is stupid?
The workings of document.cookie are not what you apparently think they are. When you set a value into the variable, you set one cookie at a time. Thus, if you wanted to set all the cookies you're holding in your object, you'd loop through your "items" array and set document.cookie successively to each name/value pair (transformed into a "cookieName=cookieValue" string).
This is a fact in all modern browsers. See this Mozilla documentation page for example.
Other comments on the code, since you were nice enough to post it:
cookie = cookies[x].split('=')[0].trim()
values = cookies[x].split('=')[1]
Better to call "split" just once.
this[cookie] = new function(){};
That's essentially equivalent to this[cookie] = {}; to set the property to a new empty object.
Looks something may be bad with the dates ?
Try to set expiration time in the far future when setting the cookie.
Your programming class sounds a bit strange.
But in my experience, manipulating cookies on the client side is really well supported in the browsers.
Quirksmode has a great article about cookies with some examples of helper functions to set and read cookies: http://www.quirksmode.org/js/cookies.html
Related
I am developping an embedded website contained within a windows CE device.
See it as if it was the web configuration interface of your router.
Everything is contained within a really small footprint of memory, the entire website is less than 500KB with every script, html, css and icons.
We have to assume that the user that is going to 'browse' into that interface does not have access to the internet (LAN only) so no 'online' solution here.
I am looking for a solution so the user choose his timezone and the code will get all the DST/STD times and dates for the next 10-20 years at least and downloaded them to the device that will run autonomously after that and at specific dates, will change its time to DST/STD by itself. Current application is custom (not windowce api related) and needs the DST/STD date pairs.
iana.org is maintaining a db for like every location in the world. I also saw that moment-timezone (javascript interface) is 'packaging' this data in a very compact package 25kb zipped.
I need to know if it is possible to:
'Extract' a main tz list from this DB so the user can choose its own tz. I looked at their doc but example didn't work:
var itsTimeZones = moment.tz.names();
2- Extract the next 10-20 years of DST/STD dates/times for a chosen zone ? I haven't saw any documentation anywhere on this topic. But since it's kind of the purpose of such a database, i would say it must be burried in there somewhere, need a way to dig it out.
3- If moment timezone is not the right track to go, anybody has a solution that will fullfill that requirement ?
Thanxs
My solution for extracting DST list for a given zone from moment-timezone.
1. "theTz" is a numerical index from a change on a select in the webpage.
2. select is populated with "List".
var itsTz =
{
"List" : moment.tz.names(), // Get all zone 'Names'
"Transitions" : [],
};
function TimeZoneChanged(theTz)
{
var myZone = moment.tz.zone(itsTz.List[theTz]); // Get zone by its name from List
var myTime = moment.tz(moment(), myZone.name); // Start today
var myResult;
// Build transition list according to new zone selected
itsTz.Transitions = [];
do
{
myResult = GetNextTransition(myZone, myTime);
if(myResult != null)
{
itsTz.Transitions.push(moment(myResult).format("YYYY/MM/DD"));
myTime = moment.tz(myResult, myZone.name); // Get next from date found
}
}while(myResult != null);
}
function GetNextTransition(theZone, theTime)
{
var myResult;
for(var i = 0; i < theZone.untils.length; i++)
{
if(theZone.untils[i] > theTime)
{
theZone.untils[i] == Infinity ? myResult = null : myResult = new moment(theZone.untils[i]).format();
return myResult;
}
}
}
Results for 'America/Toronto:
2017/03/12,
2017/11/05,
2018/03/11,
2018/11/04,
2019/03/10,
2019/11/03,
2020/03/08,
2020/11/01,
2021/03/14,
2021/11/07,
2022/03/13,
2022/11/06,
2023/03/12,
2023/11/05,
2024/03/10,
2024/11/03,
2025/03/09,
2025/11/02,
2026/03/08,
2026/11/01,
2027/03/14,
2027/11/07,
2028/03/12,
2028/11/05,
2029/03/11,
2029/11/04,
2030/03/10,
2030/11/03,
2031/03/09,
2031/11/02,
2032/03/14,
2032/11/07,
2033/03/13,
2033/11/06,
2034/03/12,
2034/11/05,
2035/03/11,
2035/11/04,
2036/03/09,
2036/11/02,
2037/03/08,
2037/11/01,
I was trying to crawl a very old website for a specific tag, I need to get it by it's for= attribute. So I used this piece of code.
var character = document.querySelectorAll("label[for=char_1]");
For some reason it returns an undefined, but I was using this script for a few days now and it worked like a charm. Here's the fun part. Typing that command in browsers console will result in undefined. But typing this alone:
document.querySelectorAll("label[for=char_1]");
Will return a proper NodeList. Why it won't assign to a variable...?
edit: It seems that deleting var and typing character without it will make it work. It's resolved but I would still love to get an answer to "why is this happening"?
edit2:
for (var i = 0; i < 15; i++) {
var character = document.querySelectorAll("label[for=char_" + i +"]");
console.log(character); // this will return [] from the script.
var color = character[0].children[0].style.color;
}
A simple for loop. All I get is Cannot read property 'children' of undefined. But I can type in the very same command document.querySelectorAll... and it will work in the browser and will return NodeList.
I had it working like this in a very hacky script. It worked.
var character1 = document.querySelectorAll("label[for=char_1]");
var characterColor1 = character1[0].children[0].style.color;
edit3:
var character1 = document.querySelectorAll("label[for=char_1]");
var characterColor1 = character1[0].children[0].style.color;
var character2 = document.querySelectorAll("label[for=char_2]");
var characterColor2 = character2[0].children[0].style.color;
// ...
The above code works without a single problem though. I don't think it's DOM not being ready as this code is also run from Greasemonkey script and it works. The only difference is the for loop.
var x = ""; // returns undefined, because it's a var assignment.
var elements = document.querySelectorAll('div');
That's expected behavior when pasted into the console.
edit: It seems that deleting var and typing character without it will make it work. It's resolved
I'm afraid you're creating a global scope variable now. or perhaps characters is an already defined variable in that scope.
Buhah, as I said in edit 3 "the only difference is the for loop". I was so busy trying to find an answer in the DOM-related things that I made the simplest mistake ever done in programming.
See?
char_1
With...
for(var i = 0...)
0! And I was testing char_1 in the browser instead of char_0. Which - truly - returns [] instead of something useful. Time to go on a holiday break I guess, my brain seems to be there already. :)
I am creating a game (like 4 pics 1 word) and it involves having an answer variable. There will be a button that onclick will run a function that checks the user's answer if it matches the value of this variable. There will be one puzzle per page and each puzzle/page will have a different value for answer variable. This variable must have its value set when the page loads. I looked it up and I don't see anything that would help me and I have no idea how I would do this. Thanks in advance.
You might need either localStorage or use Cookies for this case. If you are targeting modern browsers, you are free to use localStorage, which is a concept of HTML5.
When you are using the click event, use this:
localStorage.setItem('scores', [scores-array]);
And then when you are loading the page, try this:
localStorage.getItem('scores');
To learn more about localStorage, use this:
MDN
Dive Into HTML5 - LocalStorage
The other option of Cookies, depends on your browser's privacy settings. Many browsers (not many) would probably disable cookies, but you can use it as an alternate. You have limited data type storage (only strings), which can be initiated using:
document.cookie="scores=" + score_data;
And retrieving them using:
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 "";
}
getCookie(scores);
I am trying to store the highscore of a player local, on his pc itself. I don't know if this is possible and I didn't find a question about it on this site. I just have a var wich contains a number. I want to store it on his pc soo when the player plays the game again in his browser his highscore still will be available.
use localstorage:
window.localStorage.score="20" // storing
window.localStorage.score // getting the score again.
localStorage is not supported by old browser . so use cookie as a fall back.
if(window.localStorage)
window.localStorage.setItem("highscore",1000);
else
document.cookie="highscore=1000; expires=Thu, 31 Dec 2018 12:00:00 UTC";
to retrieve the value
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 "";
}
if(window.localStorage)
var highscore=window.localStorage.getItem("highscore");
else
var highscore=getCookie("highscore");
It's a bit of an odd thing to do, unless we are talking about nodeJS (?) storing to file system or some other local store.
if you'de like to persist a certain value so next load it'll be taken from a stored location on javascript you'll have to do it using cookies,
but than again it'll be cleared every time you are clearing your cookies and will no be shared across multiple browser on your machine.
that being said, this is how you store a value to a cookie using javascript:
document.cookie="somekey=savedValue";
var readValue = document.cookie;
You can also use Cookies besides localStorage.
var expDate=new Date();
var score=20;
expDate.setDate(expDate.getDate()+365); // expiration after one year
// Setting cookie
document.cookie='score='+score+';expires='+expDate;
// Retrieving the cookie
var yourOldScore = document.cookie.match(/score=(.*?)\;/)[1];
I`m writing a script to generate a form in Google Apps Script.
The idea is, that the user should select his/her name from a dropdown list, and then be transferred to the question block for him/her.
Although the questions are the same, there are slight changes in the choices if the dropdowns for some of the questions.
I have an array with the names of the users, and I've defined the questions for every single user.
This is not ideal, as if there is any change in the questions I have to rewrite every block oone by one.
I want to use a loop which generates the question blocks by creating the variables names using the array of the usernames.
I tried the following (this is not the actual code, but throws the same error)
for (a=0; a < 10; a++)
{
eval('var beginning'+a);
}
for (b=0;b<10; b++)
{
eval('beginning' + b) = 1;
}
The first for loop runs fine, but when I try to assign any value it throws an error. (I use here two for loops for debugging only.)
E.g.:
eval('beginning' + b) = 1; //Throws: We're sorry, a server error occurred. Please wait a bit and try again.
eval('beginning' + b + '= 1;'); //Throws: We're sorry, a server error occurred. Please wait a bit and try again.
eval('beginning' + b = 1); //Throws: Invalid assignment left hand side. (line 1, file "Code")
Using eval like this is also fine: choices = eval('lCountries' + Names[i]).getChoices();.
How can I assign values to these variables in a for loop?
Thank you very much in advance.
As far as I read up so far, eval() is almost always a bad choice, should be handled with caution and mostly never used. Using dynamic variables in such way is also a bad programming logic. I've never seen a case where it is a must, and your case obviously isn't. You can easily get around it with an object, just define a generic object var myVariables = {}, and then start assigning its properties dynamically for your variables.
var myVariables = {};
myVariables[ "beginning" ] = 1;
for( i = 0; i < 10; i++){
myVariables[ ("beginning" + i) ] = i;
}
Logger.log( myVariable[ "beginning5" ] ); //Loggs 5