In a web application that makes use of AJAX calls, I need to submit a request but add a parameter to the end of the URL, for example:
Original URL:
Here is what I do. Using my editParams() function, you can add, remove, or change any parameter, then use the built in replaceState() function to update the URL:
window.history.replaceState('object or string', 'Title', 'page.html' + editParams('enable', 'true'));
// background functions below:
// add/change/remove URL parameter
// use a value of false to remove parameter
// returns a url-style string
function editParams (key, value) {
key = encodeURI(key);
var params = getSearchParameters();
if (Object.keys(params).length === 0) {
if (value !== false)
return '?' + key + '=' + encodeURI(value);
else
return '';
}
if (value !== false)
params[key] = encodeURI(value);
else
delete params[key];
if (Object.keys(params).length === 0)
return '';
return '?' + $.map(params, function (value, key) {
return key + '=' + value;
}).join('&');
}
// Get object/associative array of URL parameters
function getSearchParameters () {
var prmstr = window.location.search.substr(1);
return prmstr !== null && prmstr !== "" ? transformToAssocArray(prmstr) : {};
}
// convert parameters from url-style string to associative array
function transformToAssocArray (prmstr) {
var params = {},
prmarr = prmstr.split("&");
for (var i = 0; i < prmarr.length; i++) {
var tmparr = prmarr[i].split("=");
params[tmparr[0]] = tmparr[1];
}
return params;
}
This is very simple solution. Its doesn't control parameter existence, and it doesn't change existing value. It adds your parameter to end, so you can get latest value in your back-end code.
function addParameterToURL(param){
_url = location.href;
_url += (_url.split('?')[1] ? '&':'?') + param;
return _url;
}
Here's a vastly simplified version, making tradeoffs for legibility and fewer lines of code instead of micro-optimized performance (and we're talking about a few miliseconds difference, realistically... due to the nature of this (operating on the current document's location), this will most likely be ran once on a page).
/**
* Add a URL parameter (or changing it if it already exists)
* @param {search} string this is typically document.location.search
* @param {key} string the key to set
* @param {val} string value
*/
var addUrlParam = function(search, key, val){
var newParam = key + '=' + val,
params = '?' + newParam;
// If the "search" string exists, then build params from it
if (search) {
// Try to replace an existance instance
params = search.replace(new RegExp('([?&])' + key + '[^&]*'), '$1' + newParam);
// If nothing was replaced, then add the new param to the end
if (params === search) {
params += '&' + newParam;
}
}
return params;
};
You would then use this like so:
document.location.pathname + addUrlParam(document.location.search, 'foo', 'bar');
/**
* Add a URL parameter
* @param {string} url
* @param {string} param the key to set
* @param {string} value
*/
var addParam = function(url, param, value) {
param = encodeURIComponent(param);
var a = document.createElement('a');
param += (value ? "=" + encodeURIComponent(value) : "");
a.href = url;
a.search += (a.search ? "&" : "") + param;
return a.href;
}
/**
* Add a URL parameter (or modify if already exists)
* @param {string} url
* @param {string} param the key to set
* @param {string} value
*/
var addOrReplaceParam = function(url, param, value) {
param = encodeURIComponent(param);
var r = "([&?]|&)" + param + "\\b(?:=(?:[^&#]*))*";
var a = document.createElement('a');
var regex = new RegExp(r);
var str = param + (value ? "=" + encodeURIComponent(value) : "");
a.href = url;
var q = a.search.replace(regex, "$1"+str);
if (q === a.search) {
a.search += (a.search ? "&" : "") + str;
} else {
a.search = q;
}
return a.href;
}
url = "http://www.example.com#hashme";
newurl = addParam(url, "ciao", "1");
alert(newurl);
And please note that parameters should be encoded before being appended in query string.
http://jsfiddle.net/48z7z4kx/
I like the answer of Mehmet Fatih Yıldız even he did not answer the whole question.
In the same line as his answer, I use this code:
"Its doesn't control parameter existence, and it doesn't change existing value. It adds your parameter to the end"
/** add a parameter at the end of the URL. Manage '?'/'&', but not the existing parameters.
* does escape the value (but not the key)
*/
function addParameterToURL(_url,_key,_value){
var param = _key+'='+escape(_value);
var sep = '&';
if (_url.indexOf('?') < 0) {
sep = '?';
} else {
var lastChar=_url.slice(-1);
if (lastChar == '&') sep='';
if (lastChar == '?') sep='';
}
_url += sep + param;
return _url;
}
and the tester:
/*
function addParameterToURL_TESTER_sub(_url,key,value){
//log(_url);
log(addParameterToURL(_url,key,value));
}
function addParameterToURL_TESTER(){
log('-------------------');
var _url ='www.google.com';
addParameterToURL_TESTER_sub(_url,'key','value');
addParameterToURL_TESTER_sub(_url,'key','Text Value');
_url ='www.google.com?';
addParameterToURL_TESTER_sub(_url,'key','value');
_url ='www.google.com?A=B';
addParameterToURL_TESTER_sub(_url,'key','value');
_url ='www.google.com?A=B&';
addParameterToURL_TESTER_sub(_url,'key','value');
_url ='www.google.com?A=1&B=2';
addParameterToURL_TESTER_sub(_url,'key','value');
}//*/
Ok here I compare Two functions, one made by myself (regExp) and another one made by (annakata).
Split array:
function insertParam(key, value)
{
key = escape(key); value = escape(value);
var kvp = document.location.search.substr(1).split('&');
var i=kvp.length; var x; while(i--)
{
x = kvp[i].split('=');
if (x[0]==key)
{
x[1] = value;
kvp[i] = x.join('=');
break;
}
}
if(i<0) {kvp[kvp.length] = [key,value].join('=');}
//this will reload the page, it's likely better to store this until finished
return "&"+kvp.join('&');
}
Regexp method:
function addParameter(param, value)
{
var regexp = new RegExp("(\\?|\\&)" + param + "\\=([^\\&]*)(\\&|$)");
if (regexp.test(document.location.search))
return (document.location.search.toString().replace(regexp, function(a, b, c, d)
{
return (b + param + "=" + value + d);
}));
else
return document.location.search+ param + "=" + value;
}
Testing case:
time1=(new Date).getTime();
for (var i=0;i<10000;i++)
{
addParameter("test","test");
}
time2=(new Date).getTime();
for (var i=0;i<10000;i++)
{
insertParam("test","test");
}
time3=(new Date).getTime();
console.log((time2-time1)+" "+(time3-time2));
It seems that even with simplest solution (when regexp use only test and do not enter .replace function) it is still slower than spliting... Well. Regexp is kinda slow but... uhh...