10

I'm using jQuery 1.12. I want to replace a query string parameter in my window's URL query string, or add the parameter if doesn't exist. I tried the below:

new_url = window.location.href.replace( /[\?#].*|$/, "?order_by=" + data_val )  
window.location.href = new_url 

but what I'm discovering is that this wipes out all previous parameters in the query string, which I don't want. If the query string is:

?a=1&b=2

I would want the new query string to be:

?a=2&b=2&order_by=data

and if the query string was:

?a=2&b=3&order_by=old_data

it would become:

?a=2&b=3&order_by=data
Munawir
  • 3,346
  • 9
  • 33
  • 51
  • Just to know... what do you expect a "replace" function is supposed to do?? – Lelio Faieta Feb 21 '17 at 21:56
  • Check out this question: http://stackoverflow.com/questions/5999118/add-or-update-query-string-parameter – dodov Feb 24 '17 at 07:19
  • in a case like this you need to check, your old query parameter, new query parameter and new query parameter value, if they are empty or invalid (e.g. wrong old query parameter). Also you need to check if current url has query parameters at all. Mostly these are the checks that need to be done in your `add or replace` query parameter function –  Feb 28 '17 at 10:15

11 Answers11

5

A good solution ought to handle all of the following:

  1. A URL that already has an order_by query parameter, optionally with whitespace before the equals sign. This can be further divided into cases where the order_by appears at the start, middle or end of the query string.
  2. A URL that doesn't already have and order_by query parameter but does already have a question mark to delimit the query string.
  3. A URL that doesn't already have and order_by query parameter and doesn't already have a question mark to delimit the query string.

The following will handle the cases above:

  if (/[?&]order_by\s*=/.test(oldUrl)) {
    newUrl = oldUrl.replace(/(?:([?&])order_by\s*=[^?&]*)/, "$1order_by=" + data_val);
  } else if (/\?/.test(oldUrl)) {
    newUrl = oldUrl + "&order_by=" + data_val;
  } else {
    newUrl = oldUrl + "?order_by=" + data_val;
  }

as demonstrated below:

getNewUrl("?a=1&b=2");
getNewUrl("?a=2&b=3&order_by=old_data");
getNewUrl("?a=2&b=3&order_by = old_data&c=4");
getNewUrl("?order_by=old_data&a=2&b=3");
getNewUrl("http://www.stackoverflow.com");

function getNewUrl(oldUrl) {
  var data_val = "new_data";
  var newUrl;
  if (/[?&]order_by\s*=/.test(oldUrl)) {
    newUrl = oldUrl.replace(/(?:([?&])order_by\s*=[^?&]*)/, "$1order_by=" + data_val);
  } else if (/\?/.test(oldUrl)) {
    newUrl = oldUrl + "&order_by=" + data_val;
  } else {
    newUrl = oldUrl + "?order_by=" + data_val;
  }
  console.log(oldUrl + "\n...becomes...\n" + newUrl);
}  
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
5

You could use a jQuery plugin to do the all the heavy lifting for you. It will parse the query string, and also reconstruct the updated query string for you. Much less code to deal with.

Plugin Download Page
Github Repo

// URL: ?a=2&b=3&order_by=old_data

var order_by = $.query.get('order_by');
//=> old_data

// Conditionally modify parameter value
if (order_by) { 
  order_by = 'data';
}

// Inject modified parameter back into query string
var newUrl = $.query.set('order_by', order_by).toString();
//=> ?a=2&b=3&order_by=data

For those using Node.js, there is a package for this available in NPM.

NPM Package
Github Repo

var queryString = require('query-string');
var parsed = queryString.parse('?a=2&b=3&order_by=old_data');  // location.search

// Conditionally modify parameter value
if (parsed.order_by) {
  parsed.order_by = 'data';
}

// Inject modified parameter back into query string
const newQueryString = queryString.stringify(parsed);
//=> a=2&b=3&order_by=data
reptofrog
  • 85
  • 1
  • 13
grizzthedj
  • 7,131
  • 16
  • 42
  • 62
  • I'm using jQuery (1.12). Does jQuery have a plugin that relates to this? –  Feb 27 '17 at 20:43
  • There are jquery plugins that do the same job. You can download one here: https://plugins.jquery.com/query-object/. The "Read The Docs" link on this page will point you to the github repo where there are plenty of examples for parsing and manipulating the query string. Let me know if this meets the need and I will modify my answer. – grizzthedj Feb 28 '17 at 10:23
  • I updated my answer to include the info about the jquery plugin option. – grizzthedj Feb 28 '17 at 10:43
4

something like this?

let new_url = "";

if (window.location.search && window.location.search.indexOf('order_by=') != -1) {
  new_url = window.location.search.replace( /order_by=\w*\d*/, "order_by=" + data_val);
} else if (window.location.search) {
  new_url = window.location.search + "&order_by=" + data_val;
} else {
  new_url = window.location.search + "?order_by=" + data_val;
}
window.location.href = new_url;
Thushan
  • 1,220
  • 14
  • 14
Georgiy Dubrov
  • 408
  • 2
  • 7
  • Hi, This isn't working. If the query string is "?a=1&b=2&order_by=whatever" and I want to make it "?a=1&b=2&order_by=new_data," the result of the above is "?a=1&b=2&order_by=whatever&order_by=new_data" –  Feb 21 '17 at 20:56
  • 1
    This still doesn't work. If the query string did not contain "order_by" it never gets added by invoking the code above. –  Feb 22 '17 at 03:04
  • @Natalia you are right, added condition, new code is above – Georgiy Dubrov Feb 22 '17 at 05:42
  • Thanks. Is there any way to shorten this into one or two lines? This seems quite long –  Feb 22 '17 at 16:37
  • Anyway, the existing lines don't work. If the query string is "a&order_by=abc%20desc", the order_by param is not replaced. I think we should just give up on this one. –  Feb 22 '17 at 22:16
  • @Natalia not, it wouldn't because in regexp for replace codition only digital and string chars, and not included special chars like % or _ – Georgiy Dubrov Feb 22 '17 at 22:36
3

function addOrReplaceOrderBy(newData) {
  var stringToAdd = "order_by=" + newData;

  if (window.location.search == "")
    return window.location.href + stringToAdd;

  if (window.location.search.indexOf('order_by=') == -1)
    return window.location.href + stringToAdd;

  var newSearchString = "";
  var searchParams = window.location.search.substring(1).split("&");
  for (var i = 0; i < searchParams.length; i++) {
    if (searchParams[i].indexOf('order_by=') > -1) {
      searchParams[i] = "order_by=" + newData;
      break;
    }
  }
  return window.location.href.split("?")[0] + "?" + searchParams.join("&");
}

window.location.href = addOrReplaceOrderBy("new_order_by");

A little long but I think it works as intended.

AVAVT
  • 7,058
  • 2
  • 21
  • 44
2

You can remove parameter from query string using URLSearchParams https://developer.mozilla.org/ru/docs/Web/API/URLSearchParams?param11=val

It is not yet supported by IE and Safari, but you can use it by adding polyfill https://github.com/jerrybendy/url-search-params-polyfill

And for accessing or modifying query part of the URI you should use "search" property of the window.location.

Working code example:

  var a = document.createElement("a")
  a.href = "http://localhost.com?param1=val&param2=val2&param3=val3#myHashCode";
  var queryParams = new URLSearchParams(a.search)
  queryParams.delete("param2")
  a.search = queryParams.toString();
  console.log(a.href);
Artem Bozhko
  • 1,744
  • 11
  • 12
1

Try this:

For reading parameters:

const data = ['example.com?var1=value1&var2=value2&var3=value3', 'example.com?a=2&b=2&order_by=data']

const getParameters = url => {
  const parameters = url.split('?')[1],
        regex = /(\w+)=(\w+)/g,
        obj = {}
  let temp
  while (temp = regex.exec(parameters)){
    obj[temp[1]] = decodeURIComponent(temp[2])
  }
  return obj
}

for(let url of data){
  console.log(getParameters(url))
}

For placing only this parameters:

const data = ['example.com?zzz=asd']
const parameters = {a:1, b:2, add: "abs"}

const setParameters = (url, parameters) => {
  const keys = Object.keys(parameters)
  let temp = url.split('?')[0] += '?'
  for (let i = 0; i < keys.length; i++) {
    temp += `${keys[i]}=${parameters[keys[i]]}${i  == keys.length - 1 ? '' : '&'}`
  }
  return temp
}

for (let url of data){
  console.log(setParameters(url, parameters))
}

And finaly for inserting (or replace while exists)

const data = ['example.com?a=123&b=3&sum=126']
const parameters = {order_by: 'abc', a: 11}
const insertParameters = (url, parameters) => {
  const keys = Object.keys(parameters)
  let result = url
  for (let i = 0; i < keys.length; i++){
    if (result.indexOf(keys[i]) === -1) {
      result += `&${keys[i]}=${encodeURIComponent(parameters[keys[i]])}`
    } else {
      let regex = new RegExp(`${keys[i]}=(\\w+)`)
      result = result.replace(regex, `&${keys[i]}=${encodeURIComponent(parameters[keys[i]])}`)
    }
  }
  return result
}

for (let url of data){
  console.log(insertParameters(url, parameters))
}

Hope this works for you ;) After using function just replace window.location.href

Maciej Kozieja
  • 1,812
  • 1
  • 13
  • 32
1

This small function could help.

function changeSearchQueryParameter(oldParameter,newParameter,newValue) {
var parameters = location.search.replace("?", "").split("&").filter(function(el){ return el !== "" });
var out = "";
var count = 0;
if(oldParameter.length>0) {
if(newParameter.length>0 && (newValue.length>0 || newValue>=0)){
 out += "?";
 var params = [];
 parameters.forEach(function(v){
  var vA = v.split("=");
  if(vA[0]==oldParameter) {
   vA[0]=newParameter;
   if((newValue.length>0 || newValue>=0)) {
   vA[1] = newValue;   
   }
  } else {
   count++;
  }
  params.push(vA.join("=")); 
 });
 if(count==parameters.length) {
  params.push([newParameter,newValue].join("="));
 }
  params = params.filter(function(el){ return el !== "" });
  if(params.length>1) {
  out += params.join("&");
  } 
  if(params.length==1) {
  out += params[0];
  } 
 }
} else {
if((newParameter.length>0) && (newValue.length>0 || newValue>=0)){
if(location.href.indexOf("?")!==-1) {
var out = "&"+newParameter+"="+newValue; 
} else {
var out = "?"+newParameter+"="+newValue; 
}
}
}
return location.href+out;
}
// if old query parameter is declared but does not exist in url then new parameter and value is simply added if it exists it will be replaced
console.log(changeSearchQueryParameter("ib","idx",5));
// add new parameter and value in url
console.log(changeSearchQueryParameter("","idy",5));
// if no new or old parameter are present url does not change
console.log(changeSearchQueryParameter("","",5));
console.log(changeSearchQueryParameter("","",""));
1

To use Regex pattern, I prefer this one:

var oldUrl = "http://stackoverflow.com/";
var data_val = "newORDER" ;
var r = /^(.+order_by=).+?(&|$)(.*)$/i ;
var newUrl = "";

var matches = oldUrl.match(r) ;
if(matches===null){
  newUrl = oldUrl + ((oldUrl.indexOf("?")>-1)?"&":"?") + "order_by=" + data_val ;
}else{
  newUrl = matches[1]+data_val+matches[2]+matches[3] ;
}
conole.log(newUrl);

If no order_by exist, matches is null and order_by=.. should come after ? or & (if other parameters exist, new one needs &).

If order_by exist, matches has 3 items, see here

Kamlesh
  • 3
  • 2
MohaMad
  • 2,575
  • 2
  • 14
  • 26
1

Maybe you could try tweaking the regular expression to retrieve only the values you're looking for, then add or update them in a helper function, something like this:

function paramUpdate(param) {

  var url = window.location.href,
      regExp = new RegExp(param.key + '=([a-z0-9\-\_]+)(?:&)?'),
      existsMatch = url.match(regExp);

  if (!existsMatch) {
      return url + '&' + param.key + '=' + param.value
  }

  var paramToUpdate = existsMatch[0],
      valueToReplace = existsMatch[1],
      updatedParam = paramToUpdate.replace(valueToReplace, param.value);

  return url.replace(paramToUpdate, updatedParam);
}

var new_url = paramUpdate({
    key: 'order_by',
    value: 'id'
});
window.location.href = new_url;

Hope it works well for your needs!

gtrenco
  • 365
  • 3
  • 8
0

Based on AVAVT´s answer I improved it so it takes any key, and I also fixed the missing "?" if there was no querystring

function addOrReplace(key, value) {
  var stringToAdd = key+"=" + value;
  if (window.location.search == "")
    return window.location.href + '?'+stringToAdd;

  if (window.location.search.indexOf(key+'=') == -1)
    return window.location.href + stringToAdd;

  var newSearchString = "";
  var searchParams = window.location.search.substring(1).split("&");
  for (var i = 0; i < searchParams.length; i++) {
    if (searchParams[i].indexOf(key+'=') > -1) {
      searchParams[i] = key+"=" + value;
      break;
    }
  }
  return window.location.href.split("?")[0] + "?" + searchParams.join("&");
}

usuage:

window.location.href = addOrReplace('order_by', 'date_created');

if you would not want to reload the page you can use pushState Api

if (history.pushState) {
    var newurl =  addOrReplace('order_by', 'date_created');
    window.history.pushState({path:newurl},'',newurl);
}
john Smith
  • 17,409
  • 11
  • 76
  • 117
  • this does not work when you already have a param, like url?other-para=x. In that case no & is added. – rmpt Dec 17 '19 at 11:19
0

function myFunction() {
  var str = "https://www.citicards.com/cards/credit/application/flow.action?app=UNSOL&HKOP=828cca70910b4fe25e118bd0b59b89c3c7c560df877909495d8252d20026cf8d&cmp=afa|acquire|2003|comparecards&ranMID=44660&ranEAID=2759285&ProspectID=516511657A844EF3A6F0C2B1E85FEFB0&ID=3000";
  var res = str.split("&");
  var myKey;
  if (!str.includes("ranSiteID")) {

    console.log("key not found ");
    res.push('ranSiteID=samplearsdyfguh.090-nuvbknlmc0.gvyhbjknl')
    console.log(res.join("&"));

  } else {

    res.map(function(key) {
      console.log("my keys", key);

      if (key.includes("ranSiteID")) {
        console.log("my required-->key", key);
        mykey = key.split("=");
        console.log(mykey);

      }
    })
  }

  document.getElementById("demo").innerHTML = res;
}
<!DOCTYPE html>
<html>

<body>
  <p>Click the button to display the array values after the split.</p>
  <button onclick="myFunction()">Try it</button>
  <p id="demo"></p>
</body>

</html>
Vivek Jain
  • 2,730
  • 6
  • 12
  • 27