Params Not being passed to AJAX correctly - Encoding issue? - javascript

Here is my code:
var params = '_SaveEditUserReq=1' ;
for(i=0; i<document.editUserForm.elements.length; i++)
{
// if(document.editUserForm.elements[i].name.substr(0, 7) == "school|") {
if (document.editUserForm.elements[i].type == 'checkbox') {
// If the id begins with 'school|', take the value if it is checked.
if (document.editUserForm.elements[i].checked) {
console.log("CHECKED!" + document.editUserForm.elements[i].value);
params += "&" + encodeURIComponent(document.editUserForm.elements[i].name) + "=" + encodeURIComponent(document.editUserForm.elements[i].value) ;
console.log(params);
}
}
else {
// Take everything else
params += "&" + document.editUserForm.elements[i].name + "=" + document.editUserForm.elements[i].value ;
}
}
Here is what is being built:
SaveEditUserReq=1&_username=jgald&_orig_username=jgald&password_error_msg=&new_password_ok=YES&new_password=&new_password_text=&new_password_too=&new_password_too_text=&_last_name=TheSirName&_first_name=TheName&_middle_initial=&_profile=Teacher&_email=email#email.com&_teacher=&school%7C=Baker%20Elementary%20School&school%7C=Brookland%20Middle%20School&school%7C=Charles%20M.%20Johnson%20Elementary%20School&=SAVE CHANGES&=CANCEL&_site=TheSite
When it's passed to PHP, the $_POST array only sees the last checkbox checked.
In this case:
[school|] => Charles M. Johnson Elementary School
Can you see what is wrong?

Given multiple key/value pairs with the same name, PHP will discard all but the last one unless the key name ends with the characters [].
If those characters exist, then it will populate $_GET (or post, etc) with an array where the name doesn't include [].
i.e.
foo.php?bar%5B%5D=1&bar%5B%5D=2
will give:
$_GET['foo'][0] == 1;
$_GET['foo'][1] == 2;

From the JavaScript portion, you have two problems
Encoding the name
You do not encode the name, just the value
params += "&" + encodeURIComponent(document.editUserForm.elements[i].name)
should be
params += "&" + document.editUserForm.elements[i].name
Not encoding the value in else
You are not encoding the value in the else!
"=" + document.editUserForm.elements[i].value ;
needs to be
"=" + encodeURIComponent(document.editUserForm.elements[i].value) ;

Related

How can I console.log a Specific cookie with document.cookie without having the value? [duplicate]

I have a getter to get the value from a cookie.
Now I have 2 cookies by the name shares= and by the name obligations= .
I want to make this getter only to get the values from the obligations cookie.
How do I do this? So the for splits the data into separate values and puts it in an array.
function getCookie1() {
// What do I have to add here to look only in the "obligations=" cookie?
// Because now it searches all the cookies.
var elements = document.cookie.split('=');
var obligations= elements[1].split('%');
for (var i = 0; i < obligations.length - 1; i++) {
var tmp = obligations[i].split('$');
addProduct1(tmp[0], tmp[1], tmp[2], tmp[3]);
}
}
One approach, which avoids iterating over an array, would be:
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
Walkthrough
Splitting a string by token will produce either, an array with one string (same value), in case token does not exist in a string, or an array with two strings , in case token is found in a string .
The first (left) element is string of what was before the token, and the second one (right) is what is string of what was after the token.
(NOTE: in case string starts with a token, first element is an empty string)
Considering that cookies are stored as follows:
"{name}={value}; {name}={value}; ..."
in order to retrieve specific cookie value, we just need to get string that is after "; {name}=" and before next ";". Before we do any processing, we prepend the cookies string with "; ", so that every cookie name, including the first one, is enclosed with "; " and "=":
"; {name}={value}; {name}={value}; ..."
Now, we can first split by "; {name}=", and if token is found in a cookie string (i.e. we have two elements), we will end up with second element being a string that begins with our cookie value. Then we pull that out from an array (i.e. pop), and repeat the same process, but now with ";" as a token, but this time pulling out the left string (i.e. shift) to get the actual token value.
I would prefer using a single regular expression match on the cookie:
window.getCookie = function(name) {
var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) return match[2];
}
OR Also we are able to use as a function , check below code.
function check_cookie_name(name)
{
var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
console.log(match[2]);
}
else{
console.log('--something went wrong---');
}
}
Improved thanks to Scott Jungwirth in the comments.
The methods in some of the other answers that use a regular expression do not cover all cases, particularly:
When the cookie is the last cookie. In this case there will not be a semicolon after the cookie value.
When another cookie name ends with the name being looked up. For example, you are looking for the cookie named "one", and there is a cookie named "done".
When the cookie name includes characters that are not interpreted as themselves when used in a regular expression unless they are preceded by a backslash.
The following method handles these cases:
function getCookie(name) {
function escape(s) { return s.replace(/([.*+?\^$(){}|\[\]\/\\])/g, '\\$1'); }
var match = document.cookie.match(RegExp('(?:^|;\\s*)' + escape(name) + '=([^;]*)'));
return match ? match[1] : null;
}
This will return null if the cookie is not found. It will return an empty string if the value of the cookie is empty.
Notes:
This function assumes cookie names are case sensitive.
document.cookie - When this appears on the right-hand side of an assignment, it represents a string containing a semicolon-separated list of cookies, which in turn are name=value pairs. There appears to be a single space after each semicolon.
String.prototype.match() - Returns null when no match is found. Returns an array when a match is found, and the element at index [1] is the value of the first matching group.
Regular Expression Notes:
(?:xxxx) - forms a non-matching group.
^ - matches the start of the string.
| - separates alternative patterns for the group.
;\\s* - matches one semi-colon followed by zero or more whitespace characters.
= - matches one equal sign.
(xxxx) - forms a matching group.
[^;]* - matches zero or more characters other than a semi-colon. This means it will match characters up to, but not including, a semi-colon or to the end of the string.
If you use jQuery I recommend you to use this plugin:
https://github.com/carhartl/jquery-cookie
https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js
<script type="text/javascript"
src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js">
So you can read cookie like this:
var value = $.cookie("obligations");
Also you can write cookie:
$.cookie('obligations', 'new_value');
$.cookie('obligations', 'new_value', { expires: 14, path: '/' });
Delete cookie:
$.removeCookie('obligations');
Here is a one liner to get a cookie value with a specific name without the need of any external lib:
const value = ('; '+document.cookie).split(`; COOKIE_NAME=`).pop().split(';')[0];
This answer is based on kirlich's brilliant solution. The only compromise of this solution is, that you will get an empty string when the cookie does not exist. In most cases this should not be a deal breaker, though.
4 years later, ES6 way simpler version.
function getCookie(name) {
let cookie = {};
document.cookie.split(';').forEach(function(el) {
let [k,v] = el.split('=');
cookie[k.trim()] = v;
})
return cookie[name];
}
I have also created a gist to use it as a Cookie object. e.g., Cookie.set(name,value) and Cookie.get(name)
This read all cookies instead of scanning through. It's ok for small number of cookies.
I have modified the function that Jonathan provided here, by using regular expression you can get a cookie value by its name like this:
function getCookie(name){
var pattern = RegExp(name + "=.[^;]*")
var matched = document.cookie.match(pattern)
if(matched){
var cookie = matched[0].split('=')
return cookie[1]
}
return false
}
If it returns empty string it means that the cookie exists but has no value, if it returns false then the cookie doesn't exist. I hope this helps.
You can use js-cookie library to get and set JavaScript cookies.
Include to your HTML:
<script src="https://cdn.jsdelivr.net/npm/js-cookie#2/src/js.cookie.min.js"></script>
To create a Cookie:
Cookies.set('name', 'value');
To read a Cookie:
Cookies.get('name'); // => 'value'
A simple way :)
const cookieObj = new URLSearchParams(document.cookie.replaceAll("&", "%26").replaceAll("; ","&"))
cookieObj.get("your-cookie-name")
One liner to convert cookie into JavaScript Object or Map
Object.fromEntries(document.cookie.split('; ').map(v=>v.split(/=(.*)/s).map(decodeURIComponent)))
new Map(document.cookie.split('; ').map(v=>v.split(/=(.*)/s).map(decodeURIComponent)))
My one linear function to get the value cookie by its key.
cookie = key=>((new RegExp((key || '=')+'=(.*?); ','gm')).exec(document.cookie+'; ') ||['',null])[1]
Call cookie function as
cookie('some-key')
Here is a pretty short version
function getCookie(n) {
let a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`);
return a ? a[1] : '';
}
Note that I made use of ES6's template strings to compose the regex expression.
I know it is an old question but I came across this problem too. Just for the record, There is a little API in developers mozilla web page.
Yoy can get any cookie by name using only JS. The code is also cleaner IMHO (except for the long line, that I'm sure you can easily fix).
function getCookie(sKey) {
if (!sKey) { return null; }
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
}
As stated in the comments be aware that this method assumes that the key and value were encoded using encodeURIComponent(). Remove decode & encodeURIComponent() if the key and value of the cookie were not encoded.
function getCookie(name) {
var pair = document.cookie.split('; ').find(x => x.startsWith(name+'='));
if (pair)
return pair.split('=')[1]
}
kirlich gave a good solution. However, it fails when there are two cookie values with similar names, here is a simple fix for this situation:
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length >= 2) return parts.pop().split(";").shift();
}
Use object.defineProperty
With this, you can easily access cookies
Object.defineProperty(window, "Cookies", {
get: function() {
return document.cookie.split(';').reduce(function(cookies, cookie) {
cookies[cookie.split("=")[0]] = unescape(cookie.split("=")[1]);
return cookies
}, {});
}
});
From now on you can just do:
alert( Cookies.obligations );
This will automatically update too, so if you change a cookie, the Cookies will change too.
It seems to me you could split the cookie key-value pairs into an array and base your search on that:
var obligations = getCookieData("obligations");
Which runs the following:
function getCookieData( name ) {
var pairs = document.cookie.split("; "),
count = pairs.length, parts;
while ( count-- ) {
parts = pairs[count].split("=");
if ( parts[0] === name )
return parts[1];
}
return false;
}
Fiddle: http://jsfiddle.net/qFmPc/
Or possibly even the following:
function getCookieData( name ) {
var patrn = new RegExp( "^" + name + "=(.*?);" ),
patr2 = new RegExp( " " + name + "=(.*?);" );
if ( match = (document.cookie.match(patrn) || document.cookie.match(patr2)) )
return match[1];
return false;
}
always works well:
function getCookie(cname) {
var name = cname + "=",
ca = document.cookie.split(';'),
i,
c,
ca_length = ca.length;
for (i = 0; i < ca_length; i += 1) {
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 setCookie(variable, value, expires_seconds) {
var d = new Date();
d = new Date(d.getTime() + 1000 * expires_seconds);
document.cookie = variable + '=' + value + '; expires=' + d.toGMTString() + ';';
}
No requirements for jQuery or anything. Pure old good JavaScript.
Simple function for Get cookie with cookie name:
function getCookie(cn) {
var name = cn+"=";
var allCookie = decodeURIComponent(document.cookie).split(';');
var cval = [];
for(var i=0; i < allCookie.length; i++) {
if (allCookie[i].trim().indexOf(name) == 0) {
cval = allCookie[i].trim().split("=");
}
}
return (cval.length > 0) ? cval[1] : "";
}
Apparently MDN has never heard of the word-boundary regex character class \b, which matches contiguous \w+ that is bounded on either side with \W+:
getCookie = function(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : null;
};
var obligations = getCookie('obligations');
In my projects I use following function to access cookies by name
function getCookie(cookie) {
return document.cookie.split(';').reduce(function(prev, c) {
var arr = c.split('=');
return (arr[0].trim() === cookie) ? arr[1] : prev;
}, undefined);
}
There are already nice answers here for getting the cookie,However here is my own solution :
function getcookie(cookiename){
var cookiestring = document.cookie;
var cookiearray = cookiestring.split(';');
for(var i =0 ; i < cookiearray.length ; ++i){
if(cookiearray[i].trim().match('^'+cookiename+'=')){
return cookiearray[i].replace(`${cookiename}=`,'').trim();
}
} return null;
}
usage :`
getcookie('session_id');
// gets cookie with name session_id
set by javascript
document.cookie = 'cookiename=tesing';
get by jquery with the jquery-cookie plugin
var value = $.cookie("cookiename");
alert(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 "";
}
Pass the cookie name to getCookie() function to get it's value
My solution is this:
function getCookieValue(cookieName) {
var ca = document.cookie.split('; ');
return _.find(ca, function (cookie) {
return cookie.indexOf(cookieName) === 0;
});
}
This function uses the Underscorejs _.find-function. Returns undefined if cookie name doesn't exist
I have done it this way. so that i get an object to access to separate the values.With this u can pass the cookie to the parent and then you can access your values by the keys like
var cookies=getCookieVal(mycookie);
alert(cookies.mykey);
function getCookieVal(parent) {
var cookievalue = $.cookie(parent).split('&');
var obj = {};
$.each(cookievalue, function (i, v) {
var key = v.substr(0, v.indexOf("="));
var val = v.substr(v.indexOf("=") + 1, v.length);
obj[key] = val;
});
return obj;
}
Just use the following function (a pure javascript code)
const getCookie = (name) => {
const cookies = Object.assign({}, ...document.cookie.split('; ').map(cookie => {
const name = cookie.split('=')[0];
const value = cookie.split('=')[1];
return {[name]: value};
}));
return cookies[name];
};
I wrote something that might be easy to use, If anyone has some things to add, feel free to do so.
function getcookie(name = '') {
let cookies = document.cookie;
let cookiestore = {};
cookies = cookies.split(";");
if (cookies[0] == "" && cookies[0][0] == undefined) {
return undefined;
}
cookies.forEach(function(cookie) {
cookie = cookie.split(/=(.+)/);
if (cookie[0].substr(0, 1) == ' ') {
cookie[0] = cookie[0].substr(1);
}
cookiestore[cookie[0]] = cookie[1];
});
return (name !== '' ? cookiestore[name] : cookiestore);
}
Usage
getcookie() - returns an object with all cookies on the web page.
getcookie('myCookie') - returns the value of the cookie myCookie from the cookie object, otherwise returns undefined if the cookie is empty or not set.
Example
// Have some cookies :-)
document.cookie = "myCookies=delicious";
document.cookie = "myComputer=good";
document.cookie = "myBrowser=RAM hungry";
// Read them
console.log( "My cookies are " + getcookie('myCookie') );
// Outputs: My cookies are delicious
console.log( "My computer is " + getcookie('myComputer') );
// Outputs: My computer is good
console.log( "My browser is " + getcookie('myBrowser') );
// Outputs: My browser is RAM hungry
console.log( getcookie() );
// Outputs: {myCookie: "delicious", myComputer: "good", myBrowser: "RAM hungry"}
// (does cookie exist?)
if (getcookie('hidden_cookie')) {
console.log('Hidden cookie was found!');
} else {
console.log('Still no cookie :-(');
}
// (do any cookies exist?)
if (getcookie()) {
console.log("You've got cookies to eat!");
} else {
console.log('No cookies for today :-(');
}
A functional approach to find existing cookies. It returns an array, so it supports multiple occurrences of the same name. It doesn't support partial key matching, but it's trivial to replace the === in the filter with a regex.
function getCookie(needle) {
return document.cookie.split(';').map(function(cookiestring) {
cs = cookiestring.trim().split('=');
if(cs.length === 2) {
return {'name' : cs[0], 'value' : cs[1]};
} else {
return {'name' : '', 'value' : ''};
}
})
.filter(function(cookieObject) {
return (cookieObject.name === needle);
});
}
Get cookie by name just pass the name of cookie to below function
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 "";
}

How to get the a sting in javascipt? [duplicate]

I have a getter to get the value from a cookie.
Now I have 2 cookies by the name shares= and by the name obligations= .
I want to make this getter only to get the values from the obligations cookie.
How do I do this? So the for splits the data into separate values and puts it in an array.
function getCookie1() {
// What do I have to add here to look only in the "obligations=" cookie?
// Because now it searches all the cookies.
var elements = document.cookie.split('=');
var obligations= elements[1].split('%');
for (var i = 0; i < obligations.length - 1; i++) {
var tmp = obligations[i].split('$');
addProduct1(tmp[0], tmp[1], tmp[2], tmp[3]);
}
}
One approach, which avoids iterating over an array, would be:
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
Walkthrough
Splitting a string by token will produce either, an array with one string (same value), in case token does not exist in a string, or an array with two strings , in case token is found in a string .
The first (left) element is string of what was before the token, and the second one (right) is what is string of what was after the token.
(NOTE: in case string starts with a token, first element is an empty string)
Considering that cookies are stored as follows:
"{name}={value}; {name}={value}; ..."
in order to retrieve specific cookie value, we just need to get string that is after "; {name}=" and before next ";". Before we do any processing, we prepend the cookies string with "; ", so that every cookie name, including the first one, is enclosed with "; " and "=":
"; {name}={value}; {name}={value}; ..."
Now, we can first split by "; {name}=", and if token is found in a cookie string (i.e. we have two elements), we will end up with second element being a string that begins with our cookie value. Then we pull that out from an array (i.e. pop), and repeat the same process, but now with ";" as a token, but this time pulling out the left string (i.e. shift) to get the actual token value.
I would prefer using a single regular expression match on the cookie:
window.getCookie = function(name) {
var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) return match[2];
}
OR Also we are able to use as a function , check below code.
function check_cookie_name(name)
{
var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) {
console.log(match[2]);
}
else{
console.log('--something went wrong---');
}
}
Improved thanks to Scott Jungwirth in the comments.
The methods in some of the other answers that use a regular expression do not cover all cases, particularly:
When the cookie is the last cookie. In this case there will not be a semicolon after the cookie value.
When another cookie name ends with the name being looked up. For example, you are looking for the cookie named "one", and there is a cookie named "done".
When the cookie name includes characters that are not interpreted as themselves when used in a regular expression unless they are preceded by a backslash.
The following method handles these cases:
function getCookie(name) {
function escape(s) { return s.replace(/([.*+?\^$(){}|\[\]\/\\])/g, '\\$1'); }
var match = document.cookie.match(RegExp('(?:^|;\\s*)' + escape(name) + '=([^;]*)'));
return match ? match[1] : null;
}
This will return null if the cookie is not found. It will return an empty string if the value of the cookie is empty.
Notes:
This function assumes cookie names are case sensitive.
document.cookie - When this appears on the right-hand side of an assignment, it represents a string containing a semicolon-separated list of cookies, which in turn are name=value pairs. There appears to be a single space after each semicolon.
String.prototype.match() - Returns null when no match is found. Returns an array when a match is found, and the element at index [1] is the value of the first matching group.
Regular Expression Notes:
(?:xxxx) - forms a non-matching group.
^ - matches the start of the string.
| - separates alternative patterns for the group.
;\\s* - matches one semi-colon followed by zero or more whitespace characters.
= - matches one equal sign.
(xxxx) - forms a matching group.
[^;]* - matches zero or more characters other than a semi-colon. This means it will match characters up to, but not including, a semi-colon or to the end of the string.
If you use jQuery I recommend you to use this plugin:
https://github.com/carhartl/jquery-cookie
https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js
<script type="text/javascript"
src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js">
So you can read cookie like this:
var value = $.cookie("obligations");
Also you can write cookie:
$.cookie('obligations', 'new_value');
$.cookie('obligations', 'new_value', { expires: 14, path: '/' });
Delete cookie:
$.removeCookie('obligations');
Here is a one liner to get a cookie value with a specific name without the need of any external lib:
const value = ('; '+document.cookie).split(`; COOKIE_NAME=`).pop().split(';')[0];
This answer is based on kirlich's brilliant solution. The only compromise of this solution is, that you will get an empty string when the cookie does not exist. In most cases this should not be a deal breaker, though.
4 years later, ES6 way simpler version.
function getCookie(name) {
let cookie = {};
document.cookie.split(';').forEach(function(el) {
let [k,v] = el.split('=');
cookie[k.trim()] = v;
})
return cookie[name];
}
I have also created a gist to use it as a Cookie object. e.g., Cookie.set(name,value) and Cookie.get(name)
This read all cookies instead of scanning through. It's ok for small number of cookies.
I have modified the function that Jonathan provided here, by using regular expression you can get a cookie value by its name like this:
function getCookie(name){
var pattern = RegExp(name + "=.[^;]*")
var matched = document.cookie.match(pattern)
if(matched){
var cookie = matched[0].split('=')
return cookie[1]
}
return false
}
If it returns empty string it means that the cookie exists but has no value, if it returns false then the cookie doesn't exist. I hope this helps.
You can use js-cookie library to get and set JavaScript cookies.
Include to your HTML:
<script src="https://cdn.jsdelivr.net/npm/js-cookie#2/src/js.cookie.min.js"></script>
To create a Cookie:
Cookies.set('name', 'value');
To read a Cookie:
Cookies.get('name'); // => 'value'
A simple way :)
const cookieObj = new URLSearchParams(document.cookie.replaceAll("&", "%26").replaceAll("; ","&"))
cookieObj.get("your-cookie-name")
One liner to convert cookie into JavaScript Object or Map
Object.fromEntries(document.cookie.split('; ').map(v=>v.split(/=(.*)/s).map(decodeURIComponent)))
new Map(document.cookie.split('; ').map(v=>v.split(/=(.*)/s).map(decodeURIComponent)))
My one linear function to get the value cookie by its key.
cookie = key=>((new RegExp((key || '=')+'=(.*?); ','gm')).exec(document.cookie+'; ') ||['',null])[1]
Call cookie function as
cookie('some-key')
Here is a pretty short version
function getCookie(n) {
let a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`);
return a ? a[1] : '';
}
Note that I made use of ES6's template strings to compose the regex expression.
I know it is an old question but I came across this problem too. Just for the record, There is a little API in developers mozilla web page.
Yoy can get any cookie by name using only JS. The code is also cleaner IMHO (except for the long line, that I'm sure you can easily fix).
function getCookie(sKey) {
if (!sKey) { return null; }
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
}
As stated in the comments be aware that this method assumes that the key and value were encoded using encodeURIComponent(). Remove decode & encodeURIComponent() if the key and value of the cookie were not encoded.
function getCookie(name) {
var pair = document.cookie.split('; ').find(x => x.startsWith(name+'='));
if (pair)
return pair.split('=')[1]
}
kirlich gave a good solution. However, it fails when there are two cookie values with similar names, here is a simple fix for this situation:
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length >= 2) return parts.pop().split(";").shift();
}
Use object.defineProperty
With this, you can easily access cookies
Object.defineProperty(window, "Cookies", {
get: function() {
return document.cookie.split(';').reduce(function(cookies, cookie) {
cookies[cookie.split("=")[0]] = unescape(cookie.split("=")[1]);
return cookies
}, {});
}
});
From now on you can just do:
alert( Cookies.obligations );
This will automatically update too, so if you change a cookie, the Cookies will change too.
It seems to me you could split the cookie key-value pairs into an array and base your search on that:
var obligations = getCookieData("obligations");
Which runs the following:
function getCookieData( name ) {
var pairs = document.cookie.split("; "),
count = pairs.length, parts;
while ( count-- ) {
parts = pairs[count].split("=");
if ( parts[0] === name )
return parts[1];
}
return false;
}
Fiddle: http://jsfiddle.net/qFmPc/
Or possibly even the following:
function getCookieData( name ) {
var patrn = new RegExp( "^" + name + "=(.*?);" ),
patr2 = new RegExp( " " + name + "=(.*?);" );
if ( match = (document.cookie.match(patrn) || document.cookie.match(patr2)) )
return match[1];
return false;
}
always works well:
function getCookie(cname) {
var name = cname + "=",
ca = document.cookie.split(';'),
i,
c,
ca_length = ca.length;
for (i = 0; i < ca_length; i += 1) {
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 setCookie(variable, value, expires_seconds) {
var d = new Date();
d = new Date(d.getTime() + 1000 * expires_seconds);
document.cookie = variable + '=' + value + '; expires=' + d.toGMTString() + ';';
}
No requirements for jQuery or anything. Pure old good JavaScript.
Simple function for Get cookie with cookie name:
function getCookie(cn) {
var name = cn+"=";
var allCookie = decodeURIComponent(document.cookie).split(';');
var cval = [];
for(var i=0; i < allCookie.length; i++) {
if (allCookie[i].trim().indexOf(name) == 0) {
cval = allCookie[i].trim().split("=");
}
}
return (cval.length > 0) ? cval[1] : "";
}
Apparently MDN has never heard of the word-boundary regex character class \b, which matches contiguous \w+ that is bounded on either side with \W+:
getCookie = function(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : null;
};
var obligations = getCookie('obligations');
In my projects I use following function to access cookies by name
function getCookie(cookie) {
return document.cookie.split(';').reduce(function(prev, c) {
var arr = c.split('=');
return (arr[0].trim() === cookie) ? arr[1] : prev;
}, undefined);
}
There are already nice answers here for getting the cookie,However here is my own solution :
function getcookie(cookiename){
var cookiestring = document.cookie;
var cookiearray = cookiestring.split(';');
for(var i =0 ; i < cookiearray.length ; ++i){
if(cookiearray[i].trim().match('^'+cookiename+'=')){
return cookiearray[i].replace(`${cookiename}=`,'').trim();
}
} return null;
}
usage :`
getcookie('session_id');
// gets cookie with name session_id
set by javascript
document.cookie = 'cookiename=tesing';
get by jquery with the jquery-cookie plugin
var value = $.cookie("cookiename");
alert(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 "";
}
Pass the cookie name to getCookie() function to get it's value
My solution is this:
function getCookieValue(cookieName) {
var ca = document.cookie.split('; ');
return _.find(ca, function (cookie) {
return cookie.indexOf(cookieName) === 0;
});
}
This function uses the Underscorejs _.find-function. Returns undefined if cookie name doesn't exist
I have done it this way. so that i get an object to access to separate the values.With this u can pass the cookie to the parent and then you can access your values by the keys like
var cookies=getCookieVal(mycookie);
alert(cookies.mykey);
function getCookieVal(parent) {
var cookievalue = $.cookie(parent).split('&');
var obj = {};
$.each(cookievalue, function (i, v) {
var key = v.substr(0, v.indexOf("="));
var val = v.substr(v.indexOf("=") + 1, v.length);
obj[key] = val;
});
return obj;
}
Just use the following function (a pure javascript code)
const getCookie = (name) => {
const cookies = Object.assign({}, ...document.cookie.split('; ').map(cookie => {
const name = cookie.split('=')[0];
const value = cookie.split('=')[1];
return {[name]: value};
}));
return cookies[name];
};
I wrote something that might be easy to use, If anyone has some things to add, feel free to do so.
function getcookie(name = '') {
let cookies = document.cookie;
let cookiestore = {};
cookies = cookies.split(";");
if (cookies[0] == "" && cookies[0][0] == undefined) {
return undefined;
}
cookies.forEach(function(cookie) {
cookie = cookie.split(/=(.+)/);
if (cookie[0].substr(0, 1) == ' ') {
cookie[0] = cookie[0].substr(1);
}
cookiestore[cookie[0]] = cookie[1];
});
return (name !== '' ? cookiestore[name] : cookiestore);
}
Usage
getcookie() - returns an object with all cookies on the web page.
getcookie('myCookie') - returns the value of the cookie myCookie from the cookie object, otherwise returns undefined if the cookie is empty or not set.
Example
// Have some cookies :-)
document.cookie = "myCookies=delicious";
document.cookie = "myComputer=good";
document.cookie = "myBrowser=RAM hungry";
// Read them
console.log( "My cookies are " + getcookie('myCookie') );
// Outputs: My cookies are delicious
console.log( "My computer is " + getcookie('myComputer') );
// Outputs: My computer is good
console.log( "My browser is " + getcookie('myBrowser') );
// Outputs: My browser is RAM hungry
console.log( getcookie() );
// Outputs: {myCookie: "delicious", myComputer: "good", myBrowser: "RAM hungry"}
// (does cookie exist?)
if (getcookie('hidden_cookie')) {
console.log('Hidden cookie was found!');
} else {
console.log('Still no cookie :-(');
}
// (do any cookies exist?)
if (getcookie()) {
console.log("You've got cookies to eat!");
} else {
console.log('No cookies for today :-(');
}
A functional approach to find existing cookies. It returns an array, so it supports multiple occurrences of the same name. It doesn't support partial key matching, but it's trivial to replace the === in the filter with a regex.
function getCookie(needle) {
return document.cookie.split(';').map(function(cookiestring) {
cs = cookiestring.trim().split('=');
if(cs.length === 2) {
return {'name' : cs[0], 'value' : cs[1]};
} else {
return {'name' : '', 'value' : ''};
}
})
.filter(function(cookieObject) {
return (cookieObject.name === needle);
});
}
Get cookie by name just pass the name of cookie to below function
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 "";
}

indexOf() in javascript

Okay so i have started learning javascript from the book Beginning Javascript 5th ed, just confused by a js script
function getCookieValue(name) {
var value = document.cookie;
var cookieStartsAt = value.indexOf(" " + name + "=");
if (cookieStartsAt == -1) {
cookieStartsAt = value.indexOf(name + "=");
}
if (cookieStartsAt == -1) {
value = null;
} else {
cookieStartsAt = value.indexOf("=", cookieStartsAt) + 1;
var cookieEndsAt = value.indexOf(";", cookieStartsAt);
if (cookieEndsAt == -1) {
cookieEndsAt = value.length;
}
value = unescape(value.substring(cookieStartsAt,
cookieEndsAt));
}
return value;}
My question is how does the indexOf operator works here( i know how it works and used it previously) ??
The above program is defined below by the book which goes as :
The first task of the function is to get the document.cookie string and store it in the value variable
var value = document.cookie;
Next, you need to find out where the cookie with the name passed as a parameter to the function
is within the
value string. You use the inde x Of() method of the String object to find this
information, as shown in the following line:
var cookieStartsAt = value.indexOf(" " + name + "=");
The method will return either the character position where the individual cookie is found or ‐1 if no
such name, and therefore no such cookie, exists. You search on
" " + name + "=" so that you don’inadvertently find cookie names or values containing the name that you require. For example, if you
have
xFoo, Foo, and yFoo as cookie names, a search for Foo without a space in front would match
xFoo first, which is not what you want!
What the just just happened here?? How did they achieve the location of the name using indexOf() ?? please explain ? I couldn't understand the xfoo,foo,yfoo example ?? Looking for a simpler example.
document.cookie contains a string like cookiename=cookievalue
indexOf is getting the position of the begining of the value part of the cookie
var cookieStartsAt = value.indexOf("cookiename=");
That allows you to use that number to get the value portion of the string with substring()

Saving CR/LF in json data

I am saving table data to a json object. The table data is coming from txt inputs and textareas in the table cells.
I'm running into a problem with CR/LF characters in the JSON elements holding the textarea data. The JSON data gets saved to the database fine, but when I pass it back to the jQuery function that populates the table using that data, I get this:
SyntaxError: JSON.parse: bad control character in string literal at line 1 column 67 of the JSON data
var array = JSON.parse(notes),
in the console.
I put the JSON data in Notepad++ with Show All Characters on and the CR/LF was at column 67.
Here's a sample of JSON data that I'm working with:
[["","","",""],["","9/23/14","",""],["","30789 detail, x_vendor_no**CR/LF HERE**
20597 header","",""],["","99 del invalid x_vendor_no","",""],["","30780","",""],["","","",""],["","","",""],["","","",""]]
Is there a way to allow CR/LF in the data?
UPDATE
11684's suggestion to use replace to remove the \r part of the CRLF won't work. Here's why:
Here's the complete function that uses the JSON data:
(Updated to work with Update #2 code below)
function PopulateTaskTableWithNotes(tableID,notesArray) {
// JSON parse removed per answer suggestion
var r, c, note;
for (r = 0; r < notesArray.length; ++r) {
for (c = 0; c < notesArray[r].length; ++c) {
note = notesArray[r][c];
$('#' + tableID + ' tr:nth-child(' + (r + 1) + ') td:nth-child(' + (c + 1) + ')').children(':first-child').val(note);
}
}
}
I still get the error on the line that tries to parse the JSON data. The replace function apparently can't "find" characters within an array element.
UPDATE #2
Here's how I am creating the array:
var siteID = $('#ddlUserSites option:selected').val(),
numRows = $('#' + tableID + ' tr').length,
numCols = $('#' + tableID).find('tr:first th').length,
notesArray = new Array(numRows),
rowNum = 1,
note = '',
colNum;
while (rowNum <= numRows) {
notesArray[rowNum] = new Array(numCols);
// Reset colNum for next row iteration
colNum = 1;
while (colNum <= numCols) {
note = '';
if ($('#' + tableID + ' tr:nth-child(' + rowNum + ') td:nth-child(' + colNum + ')').children(':first-child').is('input,textarea')) {
note = $('#' + tableID + ' tr:nth-child(' + rowNum + ') td:nth-child(' + colNum + ')').children(':first-child').val();
}
notesArray[rowNum][colNum] = note;
//console.log('Note for rowNum ' + rowNum + ', colNum ' + colNum + ': ' + note);
colNum++;
}
// Remove first element in current row array
notesArray[rowNum].shift();
rowNum++;
}
// Remove first element in array
notesArray.shift();
JSON.stringify(notesArray); // Added per an answer here
console.log('Final notesArray: ' + $.toJSON(notesArray));
$.ajax({
data: {saveTaskNotes: 'true', userID:userID, siteID:siteID, taskTable:tableID, notes:notesArray},
success: function(data) {
console.log('Save task notes data: ' + data);
}
});
The "Final notesArray" console output looks fine, but now, with stringify added, the function above (PopulateTaskTableWithNotes) console output shows that it's reading through every character in the array as a separate element!
Maybe this will help too, as far as what's happening to the data between the creating and reading functions: the array is being saved to a single MySQL database field and then retrieved for the PopulateTable function via $.ajax() (on both ends).
Having said that, do I need to look at what I'm doing with/to the array in the PHP code?
UPDATE #3
Here's the PHP function that takes the data in and writes to the MySQL db:
function SaveTaskNotes($userID,$siteID,$taskTable,$notes) {
$notes = json_encode($notes);
$insertUpdateTaskNotesResult = '';
$insertTaskNotes = "INSERT INTO userProgress (userProgressUserID,userProgressSiteID,userProgressNotesTable,userProgressNotes) values ($userID,$siteID,'" . $taskTable . "','" . $notes . "')";
$log->lwrite('$insertTaskNotes: ' . $insertTaskNotes);
$resultInsertTaskNotes = #mysqli_query($dbc,$insertTaskNotes);
if ($resultInsertTaskNotes) {
$insertUpdateTaskNotesResult = 'insertTaskNotesSuccess';
} else {
if (mysqli_error($dbc) != '') {
$log->lwrite('INSERT TASK NOTES: An error occurred while attempting to add the task notes. Query: ' . $insertTaskNotes . ', mysqli_error: ' . mysqli_error($dbc));
}
$insertUpdateTaskNotesResult = 'insertTaskNotesFail';
}
echo $insertUpdateTaskNotesResult;
}
And here's the function that gets the data from the db and sends it to the above $.ajax function:
function GetUserTaskNotes($userID,$siteID,$taskTableID) {
$queryGetUserTaskNotes = "SELECT userProgressNotes FROM userProgress WHERE userProgressUserID = $userID AND userProgressSiteID = $siteID AND userProgressNotesTable = '" . $taskTableID . "'";
$log->lwrite('$queryGetUserTaskNotes: ' . $queryGetUserTaskNotes);
$resultGetUserTaskNotes = #mysqli_query($dbc,$queryGetUserTaskNotes);
if ($resultGetUserTaskNotes) {
$taskNotes = mysqli_fetch_assoc($resultGetUserTaskNotes);
$log->lwrite('Retrieved $taskNotes[\'userProgressNotes\']: ' . $taskNotes['userProgressNotes']);
echo $taskNotes['userProgressNotes'];
} else {
if (mysqli_error($dbc) != '') {
$log->lwrite('GET TASK NOTES: An error occurred while attempting to retrieve the task notes. Query: ' . $queryGetUserTaskNotes . ', mysqli_error: ' . mysqli_error($dbc));
}
echo 'getTaskNotesFail';
}
}
In both the save and get functions the $log output shows that the array never changes (with the above js/php code) and pasting the array in to notepad++ shows that the CR/LF is still there throughout.
Don't use JSON.parse, the data is already JSON and Javascript can work with it.
You only need it when passing a string, imagine JSON.parse() beeing like string2json().
I think this might already be a solution to your problem, I've never had issues with new line characters.
As Luis said, the problem is not your client (Javascript, jQuery), besides the JSON.parse, but the providing site is wrong.
Example for PHP:
<?php
echo json_encode(array("test" => "
x"));
PHP properly escapes the characters:
{"test":"\r\n\r\n\r\nx"}
But the source of your data is providing malformed JSON.
To fix the JSON issue, either use prepared statements or use:
$notes = str_replace('\', '\\', json_encode($notes)); // in SaveTaskNotes
Well, the error is on the input data (showed in question). You can't have an CR or LF inside a literal in a JSON string. What you can have are that chars escaped as \r \n. The problem is on other side, where escaped codes are replaced by actual chars and therefore the full JSON string becomes invalid.

Classic ASP: how to convert a RecordSet to json notation using AXE json implementation

i'm doing an application with ajax using jQuery and some other tools, and in some part i want to retrieve data with ajax using a classic ASP backend, i saw that exists a good implementation of a JSON class in AXE (Asp extreme edition) framework, and i used it but currently i don't understand how to use it well.
Edit: based on the correct answer of JSON.Stringify fails on Scripting.Dictionary objects Thread, i decided to make a custom function to process Recordsets.
Edit 2: Now i'm losing the value data when call JSON.stringify inside function JSONStringify(object).
when the Recordset is passed as value to JSONStringify everything is ok but when JSON.stringify is executed, the "value" parameter that must contain the recordset becomes undefined
What i'm expecting (example)
passing a Recordset with from a SQL query SELECT name, tel FROM users a see an output like this
[
{"name":"Jonh Smith", "tel":"12345678"},
{"name":"April Michelson", "tel":"77788802"},
...
]
passing a Dictionary and see something similar based in the elements declared in dictionary.
{
"element1":"value1",
"element2":"value2",
"element3":"value3",
"element4":"value4",
"element5":"value5"
}
and if i like to support other type object i can do it expanding the function
Source Code
getcatalogos.asp
<!--#include file="../includes/conexion.asp" -->
<!--#include file="../includes/json2.asp" -->
<!--#include file="../includes/json-stringify-parser.asp" -->
<%
Response.ContentType = "application/json"
dim aVals(2)
function getCatalogo(tipo, params)
Dim oConn,oCmd,sSQL,oRs,cont2
Dim aData,oPar,cont
dim Info
set oConn = Server.CreateObject("ADODB.Connection")
set oCmd = Server.CreateObject("ADODB.Command")
sWhere = ""
oConn.ConnectionString = strcon
oConn.Open
Set oCmd.ActiveConnection = oConn
select case tipo
case "g"
sSQL = " SELECT cve_gr, descr FROM gr ORDER BY descr ;"
case "z"
sSQL = " SELECT cve_zn, descr FROM zn WHERE cve_gr = ? ORDER BY descr ;"
if IsArray(params) Then
Set oPar=oCmd.CreateParameter (params(0),129,1,2,params(1))
oCmd.Parameters.Append(oPar)
End if
case else
getCatalogo = false
exit function
end select
oCmd.CommandText = sSQL
Set oRs = oCmd.Execute()
if Not oRs.EOF Then
response.write(JSONStringify(oRs))
getCatalogo = true
else
getCatalogo = false
end if
oConn.Close
end function
aVals(0) = "cve_gr"
aVals(1) = request.querystring("gr")
if Not getCatalogo(request.querystring("t"),aVals) Then
%>error<%
end if
%>
json-stringify-parser.asp
<!--#include file="vbsTyper.asp" -->
<script runat="server" language="JScript">
function JSONStringify(object) {
VBSTypeName(object);
return JSON.stringify(object,stringifyData);
}
function stringifyData(holder, key, value) {
var sType = '';
var result;
//response.write('pre...holder=' + holder + ',key=' + key + ',value=' + value);
sType = VBSTypeName(value);
//response.write('post =' + sType);
//response.write(sType);
switch(sType){
case 'Dictionary':
result = '{';
for(var enr = new Enumerator(value); !enr.atEnd(); enr.moveNext()){
key = enr.item();
result += '"' + key + '": ' + JSON.stringify(value.Item(key));
};
result += '}';
return(result);
break;
case 'Recordset':
response.write('here!!!');
var sTemp = '';
result = '{';
while(!value.EOF){
if(Len(result) > 0){
result += ',';
}
result += '{';
for (var i = value.Fields.Count - 1; i >= 0; i--){
if(len(sTemp) > 0){
sTemp += ',';
}
sTemp += '"' + value.Fields(i).name + '":' + JSON.stringify( value.Fields(i).value);
};
result += '}';
}
result += '}';
return result;
break;
default:
//response.write(sType);
return(value);
}
// return the value to let it be processed in the usual way
return result;
}
</script>
vbsTyper.asp
<%
Function VBSTypeName(Obj)
dim sType
sType = Cstr(TypeName(Obj))
response.write(sType)
VBSTypeName = sType
End Function
%>
This:
response.write(JSON.stringify(oRs))
Should read something like this:
Do Until oRS.EOF
response.write(JSON.stringify(oRs("cve_gr") & ":" & oRs("descr"))
oRS.MoveNext
Loop
kind of achieve it...
Short version: i had to modify the json2.asp and hack the stringify() function definition to make it works.
Long Version
later of see every line of code and giving up on the problem. i decided to take a look into json2.asp (AXE Framework) and try to see what it happening there.
look what i see:
from the lines 682 to 687 theres a validation if a custom stringy parser is found but later doesn't do anything ... only returns the Object value.
there's speculation from here, because i don't understand well how works every Javascript implementation, but implying that the original code runs well, that a standart javascript interpreter (read everything else but microsoft here) will force a serialization of the object in this sutuation, but the JScript interpreter try to parse the object and pass the value as null. resulting in that every function that uses a custom stringyfier can't read the object passed in the function.
what i did to resolve ok i inserted this chunk of code before line 688, forcing to execute the custom stringyfier with value directly passed as argument avoiding the implicit parsing.
// Hack & patch to deliver the stringify-ing of the object correctly
// IDK if this is CORRECT or dont but it works in VbScript
if(replacer){
var textval = rep(this,'',value);
value = textval;
}
later i had to do some changes in json-stringify-parser.asp because i had to fix some bugs resulting in this code
<!--#include file="vbsTyper.asp" -->
<script runat="server" language="JScript">
function JSONStringify(object) {
//VBSTypeName(object);
return JSON.stringify(object,stringifyData,4);
}
function stringifyData(holder, key, value) {
var sType = '';
var result;
//response.write('pre...holder=' + holder + ',key=' + key + ',value=' + value);
sType = VBSTypeName(value);
//response.write('post =' + sType);
//response.write(sType);
switch(sType){
case 'Dictionary':
result = '{';
for(var enr = new Enumerator(value); !enr.atEnd(); enr.moveNext()){
key = enr.item();
result += '"' + key + '": ' + JSON.stringify(value.Item(key));
};
result += '}';
return(result);
break;
case 'Recordset':
//response.write('here!!!');
var sTemp;
result = '';
while(!value.EOF){
if(result.length > 0){
result += ',';
}
result += '{';
sTemp=''
for (var i = 0; i < value.fields.Count; i++){
if(sTemp.length > 0){
sTemp += ',';
}
//response.write("i=" + i + ",");
sTemp += '"' + value.fields.item(i).name + '":' + JSON.stringify( value.fields.item(i).value);
};
result += sTemp + '}';
value.moveNext();
}
result = '{' + result + '}';
return result;
break;
default:
//response.write(sType);
return(value);
}
// return the value to let it be processed in the usual way
return result;
}
</script>
the part to parse a Recordset works, the part to parse a dictionary is same like the shown in JSON.Stringify fails on Scripting.Dictionary objects (a.k.a. i haven't tested yet) but for now i'm done with this.
testing my changes with a recordset object results in this output
"{
{\"clave\":\"BC\",\"descripcion\":\"Cal\"},
{\"clave\":\"CT\",\"descripcion\":\"Center\"},
{\"clave\":\"NE\",\"descripcion\":\"Norw\"},
{\"clave\":\"NO\",\"descripcion\":\"Nore\"},
{\"clave\":\"NT\",\"descripcion\":\"North\"},
{\"clave\":\"OC\",\"descripcion\":\"East\"},
{\"clave\":\"OR\",\"descripcion\":\"West\"},
{\"clave\":\"PE\",\"descripcion\":\"Pen\"},
{\"clave\":\"SE\",\"descripcion\":\"Southe\"},
{\"clave\":\"ZM\",\"descripcion\":\"Met\"}
}"
Questions Left
question that i have left withis kind of hack.
it's Ok that the output has (") character at the beggining and the
end and i everything else has escape sencuences ?? or it's something
that should not occurs.
this kind of hack is really wrong ... i can do it better, in this
kind of situation ?
it's something wrong in my conclusion or arguments ??

Categories