I am creating a website for a client at the moment, we decided an easy way to store "items" which will be passed down to a subdomain from the root would be to store them as cookies. This works perfectly fine in a normal browser, yet when I tested it on a native device browser it didn't work as smoothly. I am wondering where some of these problems may have been coming from and hoping you wonderful developers can lend a man a hand.
The idea is that on the frontend when a "Your Order" side drawer is pressed, a function runs grabbing the cookies and then sorts them into their specified content area's -> Downloadable Content, Requested Material and Bespoke Content. I have created two separate functions for this, one that was the original working piece and another more tailored and "good practice".
Tried having the "Value" of the cookie containing the values that need to be stored such as, [itemname],[itemlocation], [itemdescription], [itemtype].
The second function stores the item data in an object, the object is then JSON.stringified and iterated over in a for loop. This is then taken out of a string with JSON.parse() and further iterated over in an .each() iterating over the index(key) and val(value).
FIRST FUNCTION:
$('section#review-downloads a.toggle-btn').bind('click tap', function() {
let cookies;
let itemSplit;
var section = $('section#review-downloads');
if(section.hasClass('active')) {
section.removeClass('active');
setTimeout(function() {
$('section#review-downloads .selected-items div').find('p').remove();
}, 900);
} else {
section.addClass('active');
$.each(document.cookie.split(';'), function() {
cookies = this.split('=');
let trimId = cookies[0].trim();
vals = cookies[1].replace(/[\])}[{(]/g, '');
if(!(cookies[0] === "envFilter")) {
$.each(vals.split('[ ]'),function() {
itemSplit = this.split(',');
let itemId = trimId;
let itemName = itemSplit[0];
let itemUrl = itemSplit[1];
let itemType = itemSplit[2];
let itemDesc = itemSplit[3];
if(itemType === ' Downloadable Content ') {
$('<p id="selected-item-'+itemId+'"><strong>'+itemName+'</strong>'+itemDesc+'</p>').appendTo('section#review-downloads .review-container .selected-items .downloadable-content');
} else if (itemType === ' Requested Materials ') {
$('<p id="selected-item"><strong>'+itemName+'</strong>'+itemDesc+'</p>').appendTo('section#review-downloads .review-container .selected-items .requested-material');
} else if (itemType === ' Bespoke Content ') {
$('<p id="selected-item"><strong>'+itemName+'</strong>'+itemDesc+'</p>').appendTo('section#review-downloads .review-container .selected-items .bespoke-content');
}
});
};
});
}
return false;
});
THE SECOND FUNCTION (best practice)
$('div.support-item-wrapper div.order-add').bind('click tap', function() {
let id = $(this).data('id');
let name = $(this).data('title');
let file = $(this).data('file');
let type = $(this).data('type');
let desc = $(this).data('description').replace(/(\r\n|\n|\r)/gm, "");
let url = $(this).data('url');
let cookieVal = {
name: name,
file: file,
type: type,
desc: desc,
url: url
};
let string = JSON.stringify(cookieVal);
setCookie('product-'+id, string, 1);
});
$('section#review-downloads a.toggle-btn').bind('click tap', function() {
var section = $('section#review-downloads');
if(section.hasClass('active')) {
section.removeClass('active');
} else {
section.addClass('active');
let decoded_user_product;
cookie_values = document.cookie.split(';');
for(i = 0; i < cookie_values.length; i++) {
cookie_split = cookie_values[i].split("=");
cookie_key = cookie_split[0].trim();
cookie_value = cookie_split[1].trim();
// console.log(cookie_value);
if(cookie_key != "envFilter") {
decoded_user_product = JSON.parse(cookie_value);
}
$.each(decoded_user_product, function(index, val) {
// console.log("index:" + index + "& val:" + val);
if(index === "name") {
console.log(val);
} else if (index === "type") {
console.log(val);
} else if (index === "desc") {
console.log(val);
}
});
}
// console.log(decoded_user_product);
};
});
On Desktop, the results are perfectly fine. Each item is easily console.log()'able and has been easily sorted in the FIRST FUNCTION.
On Mobile, the same results were as to be expected. But after realising it hadn't worked I used chrome://inspect along with a lot of console.logs to come to the conclusion that I may be too inexperienced to understand what parts of my code are unable to run on a native browser.
I am looking for a JavaScript library that parses an XML string and converts it to a JavaScript object. What are some good ones?
The following function parses XML and returns a JavaScript object with a scheme that corresponds to the XML. XML siblings w/ the same name are collapsed into arrays. nodes with names that can be found in the arrayTags parameter (array of tag name strings) always yield arrays even in case of only one tag occurrence. arrayTags can be omitted. Text nodes with only spaces are discarded.
function parseXml(xml, arrayTags) {
let dom = null;
if (window.DOMParser) dom = (new DOMParser()).parseFromString(xml, "text/xml");
else if (window.ActiveXObject) {
dom = new ActiveXObject('Microsoft.XMLDOM');
dom.async = false;
if (!dom.loadXML(xml)) throw dom.parseError.reason + " " + dom.parseError.srcText;
}
else throw new Error("cannot parse xml string!");
function parseNode(xmlNode, result) {
if (xmlNode.nodeName == "#text") {
let v = xmlNode.nodeValue;
if (v.trim()) result['#text'] = v;
return;
}
let jsonNode = {},
existing = result[xmlNode.nodeName];
if (existing) {
if (!Array.isArray(existing)) result[xmlNode.nodeName] = [existing, jsonNode];
else result[xmlNode.nodeName].push(jsonNode);
}
else {
if (arrayTags && arrayTags.indexOf(xmlNode.nodeName) != -1) result[xmlNode.nodeName] = [jsonNode];
else result[xmlNode.nodeName] = jsonNode;
}
if (xmlNode.attributes) for (let attribute of xmlNode.attributes) jsonNode[attribute.nodeName] = attribute.nodeValue;
for (let node of xmlNode.childNodes) parseNode(node, jsonNode);
}
let result = {};
for (let node of dom.childNodes) parseNode(node, result);
return result;
}
Here's a nice xml2json and json2xml converter:
http://goessner.net/download/prj/jsonxml/
Related tutorial: http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html
Here's another one:
http://www.kawa.net/works/js/xml/objtree-e.html
Depending on your needs, you might be able to use a standard parser (see http://www.w3schools.com/XML/tryit.asp?filename=tryxml_parsertest2) and xpath (http://www.w3schools.com/xpath/default.asp) - here's an example:
http://snippets.dzone.com/posts/show/5272
and a few nice tutorials:
http://www.nczonline.net/blog/2009/03/17/xpath-in-javascript-part-1/
https://developer.mozilla.org/en/introduction_to_using_xpath_in_javascript
Going straight to the point (using node-xml2json):
npm install xml2json
Then, use it:
const parser = require('xml2json');
const obj = parser.toJson(xml, { object: true });
Example:
const parser = require('xml2json');
const xml = '<root><person><name>Bob Dylan</name></person></root>';
const obj = parser.toJson(xml, { object: true });
const { person } = obj.root;
person.name; // Bob Dylan
You can also convert from JSON to XML, and much more.
I wanted a simple Typescript version that didn't create additional #text objects and also disregarded attributes. If that's what you need, here's the code:
export class DomFuncs {
static parseNode = (node: Node) => {
const childNodes = node.childNodes;
if (childNodes.length === 0) {
return node.nodeValue;
} else if (childNodes.length === 1 && childNodes[0].nodeType === Node.TEXT_NODE) {
return childNodes[0].nodeValue;
} else {
const obj = {};
childNodes.forEach(childNode => {
const childName = childNode.nodeName;
const childValue = obj[childName];
if (childValue !== undefined) {
if (Array.isArray(childValue)) {
childValue.push(DomFuncs.parseNode(childNode));
} else {
obj[childName] = [childValue, DomFuncs.parseNode(childNode)];
}
} else {
obj[childName] = DomFuncs.parseNode(childNode);
}
});
return obj;
}
};
static xml2obj = (str: string) => {
const dom = (new DOMParser()).parseFromString(str, 'text/xml')
const result = {[dom.nodeName]: DomFuncs.parseNode(dom)};
return result;
}
}
To use it:
DomFuncs.xml2obj(xmlString);
This script currently disregards XML attributes since my converted object didn't require them. If you need that, let me know and I could update the code.
The xml2json javascript file from https://bitbucket.org/surenrao/xml2json is all you need to do this.
Here's the download link for quick download: https://bitbucket.org/surenrao/xml2json/get/0e0989dfe48e.zip
Once included in your project, here's some sample code to get you started:
var xmlStr = "<root><person><name>Bob Dylan</name></person></root>";
var jsObj = X2J.parseXml(xmlStr);
var result = jsObj[0].root[0].person[0].name[0].jValue; //Bob Dylan
I am looking for a JavaScript library that parses an XML string and converts it to a JavaScript object. What are some good ones?
The following function parses XML and returns a JavaScript object with a scheme that corresponds to the XML. XML siblings w/ the same name are collapsed into arrays. nodes with names that can be found in the arrayTags parameter (array of tag name strings) always yield arrays even in case of only one tag occurrence. arrayTags can be omitted. Text nodes with only spaces are discarded.
function parseXml(xml, arrayTags) {
let dom = null;
if (window.DOMParser) dom = (new DOMParser()).parseFromString(xml, "text/xml");
else if (window.ActiveXObject) {
dom = new ActiveXObject('Microsoft.XMLDOM');
dom.async = false;
if (!dom.loadXML(xml)) throw dom.parseError.reason + " " + dom.parseError.srcText;
}
else throw new Error("cannot parse xml string!");
function parseNode(xmlNode, result) {
if (xmlNode.nodeName == "#text") {
let v = xmlNode.nodeValue;
if (v.trim()) result['#text'] = v;
return;
}
let jsonNode = {},
existing = result[xmlNode.nodeName];
if (existing) {
if (!Array.isArray(existing)) result[xmlNode.nodeName] = [existing, jsonNode];
else result[xmlNode.nodeName].push(jsonNode);
}
else {
if (arrayTags && arrayTags.indexOf(xmlNode.nodeName) != -1) result[xmlNode.nodeName] = [jsonNode];
else result[xmlNode.nodeName] = jsonNode;
}
if (xmlNode.attributes) for (let attribute of xmlNode.attributes) jsonNode[attribute.nodeName] = attribute.nodeValue;
for (let node of xmlNode.childNodes) parseNode(node, jsonNode);
}
let result = {};
for (let node of dom.childNodes) parseNode(node, result);
return result;
}
Here's a nice xml2json and json2xml converter:
http://goessner.net/download/prj/jsonxml/
Related tutorial: http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html
Here's another one:
http://www.kawa.net/works/js/xml/objtree-e.html
Depending on your needs, you might be able to use a standard parser (see http://www.w3schools.com/XML/tryit.asp?filename=tryxml_parsertest2) and xpath (http://www.w3schools.com/xpath/default.asp) - here's an example:
http://snippets.dzone.com/posts/show/5272
and a few nice tutorials:
http://www.nczonline.net/blog/2009/03/17/xpath-in-javascript-part-1/
https://developer.mozilla.org/en/introduction_to_using_xpath_in_javascript
Going straight to the point (using node-xml2json):
npm install xml2json
Then, use it:
const parser = require('xml2json');
const obj = parser.toJson(xml, { object: true });
Example:
const parser = require('xml2json');
const xml = '<root><person><name>Bob Dylan</name></person></root>';
const obj = parser.toJson(xml, { object: true });
const { person } = obj.root;
person.name; // Bob Dylan
You can also convert from JSON to XML, and much more.
I wanted a simple Typescript version that didn't create additional #text objects and also disregarded attributes. If that's what you need, here's the code:
export class DomFuncs {
static parseNode = (node: Node) => {
const childNodes = node.childNodes;
if (childNodes.length === 0) {
return node.nodeValue;
} else if (childNodes.length === 1 && childNodes[0].nodeType === Node.TEXT_NODE) {
return childNodes[0].nodeValue;
} else {
const obj = {};
childNodes.forEach(childNode => {
const childName = childNode.nodeName;
const childValue = obj[childName];
if (childValue !== undefined) {
if (Array.isArray(childValue)) {
childValue.push(DomFuncs.parseNode(childNode));
} else {
obj[childName] = [childValue, DomFuncs.parseNode(childNode)];
}
} else {
obj[childName] = DomFuncs.parseNode(childNode);
}
});
return obj;
}
};
static xml2obj = (str: string) => {
const dom = (new DOMParser()).parseFromString(str, 'text/xml')
const result = {[dom.nodeName]: DomFuncs.parseNode(dom)};
return result;
}
}
To use it:
DomFuncs.xml2obj(xmlString);
This script currently disregards XML attributes since my converted object didn't require them. If you need that, let me know and I could update the code.
The xml2json javascript file from https://bitbucket.org/surenrao/xml2json is all you need to do this.
Here's the download link for quick download: https://bitbucket.org/surenrao/xml2json/get/0e0989dfe48e.zip
Once included in your project, here's some sample code to get you started:
var xmlStr = "<root><person><name>Bob Dylan</name></person></root>";
var jsObj = X2J.parseXml(xmlStr);
var result = jsObj[0].root[0].person[0].name[0].jValue; //Bob Dylan
I am looking for a JavaScript library that parses an XML string and converts it to a JavaScript object. What are some good ones?
The following function parses XML and returns a JavaScript object with a scheme that corresponds to the XML. XML siblings w/ the same name are collapsed into arrays. nodes with names that can be found in the arrayTags parameter (array of tag name strings) always yield arrays even in case of only one tag occurrence. arrayTags can be omitted. Text nodes with only spaces are discarded.
function parseXml(xml, arrayTags) {
let dom = null;
if (window.DOMParser) dom = (new DOMParser()).parseFromString(xml, "text/xml");
else if (window.ActiveXObject) {
dom = new ActiveXObject('Microsoft.XMLDOM');
dom.async = false;
if (!dom.loadXML(xml)) throw dom.parseError.reason + " " + dom.parseError.srcText;
}
else throw new Error("cannot parse xml string!");
function parseNode(xmlNode, result) {
if (xmlNode.nodeName == "#text") {
let v = xmlNode.nodeValue;
if (v.trim()) result['#text'] = v;
return;
}
let jsonNode = {},
existing = result[xmlNode.nodeName];
if (existing) {
if (!Array.isArray(existing)) result[xmlNode.nodeName] = [existing, jsonNode];
else result[xmlNode.nodeName].push(jsonNode);
}
else {
if (arrayTags && arrayTags.indexOf(xmlNode.nodeName) != -1) result[xmlNode.nodeName] = [jsonNode];
else result[xmlNode.nodeName] = jsonNode;
}
if (xmlNode.attributes) for (let attribute of xmlNode.attributes) jsonNode[attribute.nodeName] = attribute.nodeValue;
for (let node of xmlNode.childNodes) parseNode(node, jsonNode);
}
let result = {};
for (let node of dom.childNodes) parseNode(node, result);
return result;
}
Here's a nice xml2json and json2xml converter:
http://goessner.net/download/prj/jsonxml/
Related tutorial: http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html
Here's another one:
http://www.kawa.net/works/js/xml/objtree-e.html
Depending on your needs, you might be able to use a standard parser (see http://www.w3schools.com/XML/tryit.asp?filename=tryxml_parsertest2) and xpath (http://www.w3schools.com/xpath/default.asp) - here's an example:
http://snippets.dzone.com/posts/show/5272
and a few nice tutorials:
http://www.nczonline.net/blog/2009/03/17/xpath-in-javascript-part-1/
https://developer.mozilla.org/en/introduction_to_using_xpath_in_javascript
Going straight to the point (using node-xml2json):
npm install xml2json
Then, use it:
const parser = require('xml2json');
const obj = parser.toJson(xml, { object: true });
Example:
const parser = require('xml2json');
const xml = '<root><person><name>Bob Dylan</name></person></root>';
const obj = parser.toJson(xml, { object: true });
const { person } = obj.root;
person.name; // Bob Dylan
You can also convert from JSON to XML, and much more.
I wanted a simple Typescript version that didn't create additional #text objects and also disregarded attributes. If that's what you need, here's the code:
export class DomFuncs {
static parseNode = (node: Node) => {
const childNodes = node.childNodes;
if (childNodes.length === 0) {
return node.nodeValue;
} else if (childNodes.length === 1 && childNodes[0].nodeType === Node.TEXT_NODE) {
return childNodes[0].nodeValue;
} else {
const obj = {};
childNodes.forEach(childNode => {
const childName = childNode.nodeName;
const childValue = obj[childName];
if (childValue !== undefined) {
if (Array.isArray(childValue)) {
childValue.push(DomFuncs.parseNode(childNode));
} else {
obj[childName] = [childValue, DomFuncs.parseNode(childNode)];
}
} else {
obj[childName] = DomFuncs.parseNode(childNode);
}
});
return obj;
}
};
static xml2obj = (str: string) => {
const dom = (new DOMParser()).parseFromString(str, 'text/xml')
const result = {[dom.nodeName]: DomFuncs.parseNode(dom)};
return result;
}
}
To use it:
DomFuncs.xml2obj(xmlString);
This script currently disregards XML attributes since my converted object didn't require them. If you need that, let me know and I could update the code.
The xml2json javascript file from https://bitbucket.org/surenrao/xml2json is all you need to do this.
Here's the download link for quick download: https://bitbucket.org/surenrao/xml2json/get/0e0989dfe48e.zip
Once included in your project, here's some sample code to get you started:
var xmlStr = "<root><person><name>Bob Dylan</name></person></root>";
var jsObj = X2J.parseXml(xmlStr);
var result = jsObj[0].root[0].person[0].name[0].jValue; //Bob Dylan
Just wondering if there is anything built-in to Javascript that can take a Form and return the query parameters, eg: "var1=value&var2=value2&arr[]=foo&arr[]=bar..."
I've been wondering this for years.
The URLSearchParams API is available in all modern browsers. For example:
const params = new URLSearchParams({
var1: "value",
var2: "value2",
arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"
2k20 update: use Josh's solution with URLSearchParams.toString().
Old answer:
Without jQuery
var params = {
parameter1: 'value_1',
parameter2: 'value 2',
parameter3: 'value&3'
};
var esc = encodeURIComponent;
var query = Object.keys(params)
.map(k => esc(k) + '=' + esc(params[k]))
.join('&');
For browsers that don't support arrow function syntax which requires ES5, change the .map... line to
.map(function(k) {return esc(k) + '=' + esc(params[k]);})
If you're using jQuery you might want to check out jQuery.param() http://api.jquery.com/jQuery.param/
Example:
var params = {
parameter1: 'value1',
parameter2: 'value2',
parameter3: 'value3'
};
var query = $.param(params);
console.log(query);
This will print out:
parameter1=value1¶meter2=value2¶meter3=value3
This doesn't directly answer your question, but here's a generic function which will create a URL that contains query string parameters. The parameters (names and values) are safely escaped for inclusion in a URL.
function buildUrl(url, parameters){
var qs = "";
for(var key in parameters) {
var value = parameters[key];
qs += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
}
if (qs.length > 0){
qs = qs.substring(0, qs.length-1); //chop off last "&"
url = url + "?" + qs;
}
return url;
}
// example:
var url = "http://example.com/";
var parameters = {
name: "George Washington",
dob: "17320222"
};
console.log(buildUrl(url, parameters));
// => http://www.example.com/?name=George%20Washington&dob=17320222
Create an URL object and append the values to seachParameters
let stringUrl = "http://www.google.com/search";
let url = new URL(stringUrl);
let params = url.searchParams;
params.append("q", "This is seach query");
console.log(url.toString());
The output will be
http://www.google.com/search?q=This+is+seach+query
With jQuery you can do this by $.param
$.param({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
// -> "action=ship&order_id=123&fees%5B%5D=f1&fees%5B%5D=f2&label=a+demo"
ES2017 (ES8)
Making use of Object.entries(), which returns an array of object's [key, value] pairs. For example, for {a: 1, b: 2} it would return [['a', 1], ['b', 2]]. It is not supported (and won't be) only by IE.
Code:
const buildURLQuery = obj =>
Object.entries(obj)
.map(pair => pair.map(encodeURIComponent).join('='))
.join('&');
Example:
buildURLQuery({name: 'John', gender: 'male'});
Result:
"name=John&gender=male"
querystring can help.
So, you can
const querystring = require('querystring')
url += '?' + querystring.stringify(parameters)
No, I don't think standard JavaScript has that built in, but Prototype JS has that function (surely most other JS frameworks have too, but I don't know them), they call it serialize.
I can reccomend Prototype JS, it works quite okay. The only drawback I've really noticed it it's size (a few hundred kb) and scope (lots of code for ajax, dom, etc.). Thus if you only want a form serializer it's overkill, and strictly speaking if you only want it's Ajax functionality (wich is mainly what I used it for) it's overkill. Unless you're careful you may find that it does a little too much "magic" (like extending every dom element it touches with Prototype JS functions just to find elements) making it slow on extreme cases.
If you don't want to use a library, this should cover most/all of the same form element types.
function serialize(form) {
if (!form || !form.elements) return;
var serial = [], i, j, first;
var add = function (name, value) {
serial.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
}
var elems = form.elements;
for (i = 0; i < elems.length; i += 1, first = false) {
if (elems[i].name.length > 0) { /* don't include unnamed elements */
switch (elems[i].type) {
case 'select-one': first = true;
case 'select-multiple':
for (j = 0; j < elems[i].options.length; j += 1)
if (elems[i].options[j].selected) {
add(elems[i].name, elems[i].options[j].value);
if (first) break; /* stop searching for select-one */
}
break;
case 'checkbox':
case 'radio': if (!elems[i].checked) break; /* else continue */
default: add(elems[i].name, elems[i].value); break;
}
}
}
return serial.join('&');
}
You can do that nowadays with FormData and URLSearchParams without the need to loop over anything.
const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();
Older browsers will need a polyfill, though.
Might be a bit redundant but the cleanest way i found which builds on some of the answers here:
const params: {
key1: 'value1',
key2: 'value2',
key3: 'value3',
}
const esc = encodeURIComponent;
const query = Object.keys(params)
.map(k => esc(k) + '=' + esc(params[k]))
.join('&');
return fetch('my-url', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: query,
})
Source
I'm not entirely certain myself, I recall seeing jQuery did it to an extent, but it doesn't handle hierarchical records at all, let alone in a php friendly way.
One thing I do know for certain, is when building URLs and sticking the product into the dom, don't just use string-glue to do it, or you'll be opening yourself to a handy page breaker.
For instance, certain advertising software in-lines the version string from whatever runs your flash. This is fine when its adobes generic simple string, but however, that's very naive, and blows up in an embarrasing mess for people whom have installed Gnash, as gnash'es version string happens to contain a full blown GPL copyright licences, complete with URLs and <a href> tags. Using this in your string-glue advertiser generator, results in the page blowing open and having imbalanced HTML turning up in the dom.
The moral of the story:
var foo = document.createElement("elementnamehere");
foo.attribute = allUserSpecifiedDataConsideredDangerousHere;
somenode.appendChild(foo);
Not:
document.write("<elementnamehere attribute=\""
+ ilovebrokenwebsites
+ "\">"
+ stringdata
+ "</elementnamehere>");
Google need to learn this trick. I tried to report the problem, they appear not to care.
You don't actually need a form to do this with Prototype. Just use Object.toQueryString function:
Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
I know this is very late answer but works very well...
var obj = {
a:"a",
b:"b"
}
Object.entries(obj).map(([key, val])=>`${key}=${val}`).join("&");
note: object.entries will return key,values pairs
output from above line will be a=a&b=b
Hope its helps someone.
Happy Coding...
The UrlSearchParams API is a great suggestion, but I can't believe nobody mentioned the incredibly useful .get and .set methods. They can be used to manipulate the query string and not only they're very easy to use, they also solve a number of issues you might encounter. For example, in my case I wanted to build a query string without duplicate keys. .set solves this problem for you. Quoting from the MDN docs:
URLSearchParams.set()
Sets the value associated with a given search parameter to the given value. If there are several values, the others are deleted.
Example (from MDN):
let url = new URL('https://example.com?foo=1&bar=2');
let params = new URLSearchParams(url.search);
// Add a third parameter
params.set('baz', 3);
params.toString(); // "foo=1&bar=2&baz=3"
Alternative, shorter syntax:
let url = new URL('https://example.com?foo=1&bar=2');
// Add a third parameter
url.searchParams.set('baz', 3);
url.searchParams.toString(); // "foo=1&bar=2&baz=3"
As Stein says, you can use the prototype javascript library from http://www.prototypejs.org.
Include the JS and it is very simple then, $('formName').serialize() will return what you want!
For those of us who prefer jQuery, you would use the form plugin: http://plugins.jquery.com/project/form, which contains a formSerialize method.
Is is probably too late to answer your question.
I had the same question and I didn't like to keep appending strings to create a URL. So, I started using $.param as techhouse explained.
I also found a URI.js library that creates the URLs easily for you. There are several examples that will help you: URI.js Documentation.
Here is one of them:
var uri = new URI("?hello=world");
uri.setSearch("hello", "mars"); // returns the URI instance for chaining
// uri == "?hello=mars"
uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
// uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"
uri.setSearch("goodbye", "sun");
// uri == "?hello=mars&foo=bar&goodbye=sun"
// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter…
uri.setSearch("foo", ["bar", "baz"]);
uri.setSearch("foo[]", ["bar", "baz"]);`
These answers are very helpful, but i want to add another answer, that may help you build full URL.
This can help you concat base url, path, hash and parameters.
var url = buildUrl('http://mywebsite.com', {
path: 'about',
hash: 'contact',
queryParams: {
'var1': 'value',
'var2': 'value2',
'arr[]' : 'foo'
}
});
console.log(url);
You can download via npm https://www.npmjs.com/package/build-url
Demo:
;(function () {
'use strict';
var root = this;
var previousBuildUrl = root.buildUrl;
var buildUrl = function (url, options) {
var queryString = [];
var key;
var builtUrl;
var caseChange;
// 'lowerCase' parameter default = false,
if (options && options.lowerCase) {
caseChange = !!options.lowerCase;
} else {
caseChange = false;
}
if (url === null) {
builtUrl = '';
} else if (typeof(url) === 'object') {
builtUrl = '';
options = url;
} else {
builtUrl = url;
}
if(builtUrl && builtUrl[builtUrl.length - 1] === '/') {
builtUrl = builtUrl.slice(0, -1);
}
if (options) {
if (options.path) {
var localVar = String(options.path).trim();
if (caseChange) {
localVar = localVar.toLowerCase();
}
if (localVar.indexOf('/') === 0) {
builtUrl += localVar;
} else {
builtUrl += '/' + localVar;
}
}
if (options.queryParams) {
for (key in options.queryParams) {
if (options.queryParams.hasOwnProperty(key) && options.queryParams[key] !== void 0) {
var encodedParam;
if (options.disableCSV && Array.isArray(options.queryParams[key]) && options.queryParams[key].length) {
for(var i = 0; i < options.queryParams[key].length; i++) {
encodedParam = encodeURIComponent(String(options.queryParams[key][i]).trim());
queryString.push(key + '=' + encodedParam);
}
} else {
if (caseChange) {
encodedParam = encodeURIComponent(String(options.queryParams[key]).trim().toLowerCase());
}
else {
encodedParam = encodeURIComponent(String(options.queryParams[key]).trim());
}
queryString.push(key + '=' + encodedParam);
}
}
}
builtUrl += '?' + queryString.join('&');
}
if (options.hash) {
if(caseChange)
builtUrl += '#' + String(options.hash).trim().toLowerCase();
else
builtUrl += '#' + String(options.hash).trim();
}
}
return builtUrl;
};
buildUrl.noConflict = function () {
root.buildUrl = previousBuildUrl;
return buildUrl;
};
if (typeof(exports) !== 'undefined') {
if (typeof(module) !== 'undefined' && module.exports) {
exports = module.exports = buildUrl;
}
exports.buildUrl = buildUrl;
} else {
root.buildUrl = buildUrl;
}
}).call(this);
var url = buildUrl('http://mywebsite.com', {
path: 'about',
hash: 'contact',
queryParams: {
'var1': 'value',
'var2': 'value2',
'arr[]' : 'foo'
}
});
console.log(url);
var params = { width:1680, height:1050 };
var str = jQuery.param( params );
console.log(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Remove undefined params 💪😃
urlParams = obj =>{
const removeUndefined = JSON.parse(JSON.stringify(obj))
const result = new URLSearchParams(removeUndefined).toString();
return result ? `?${result}`: '';
}
console.log(urlParams({qwe: undefined, txt: 'asd'})) // '?txt=asd'
console.log(urlParams({qwe: undefined})) // ''