19

My current URL is: http://something.com/mobiles.php?brand=samsung

Now when a user clicks on a minimum price filter (say 300), I want my URL to become

http://something.com/mobiles.php?brand=samsung&priceMin=300

In other words, I am looking for a javascript function which will add a specified parameter in the current URL and then re-direct the webpage to the new URL.

Note: If no parameters are set then the function should add ? instead of &

i.e. if the current URL is http://something.com/mobiles.php then page should be re-directed to http://something.com/mobiles.php?priceMin=300 instead of http://something.com/mobiles.php&priceMin=300

Community
  • 1
  • 1
sumit
  • 10,935
  • 24
  • 65
  • 83
  • 1
    Any reason you can't generate the link server-side or use a webform? – zzzzBov Aug 01 '11 at 13:30
  • I agree with @zzzzBov, then you can turn your minimum price filter into a dynamic link. – iLLin Aug 01 '11 at 13:33
  • 1
    There are too many filters on my website like brand name, price range, sort by popularity, sort by price and many others. To generate the URL on server side needs a lot of `if-else` statements and will generate un-necessary load on the server. I am specifically looking for the URL change at client side. Thanks! – sumit Aug 01 '11 at 13:35
  • @iSumitG, if you're using PHP and you're using "a lot of `if-else` statements", then you're doing it very wrong. – zzzzBov Aug 01 '11 at 13:37
  • @zzzzBov: Yes, that's why I asked the question. I want to do it on client side. I know that using lot of `if-else` is not good but can you tell me why it is not good? – sumit Aug 01 '11 at 13:38
  • 2
    You shouldn't need if-else... PHP has functions designed for this. Check out http://www.php.net/manual/en/function.http-build-query.php – iLLin Aug 01 '11 at 13:40
  • 2
    @iSumitG, because you could be using your `$_GET` array to populate a webform with the necessary values as hidden fields, or you could build a new querystring with `http_build_query` with a copy of `$_GET` where you've set any necessary new parameters. This new query could be dumped into a link. – zzzzBov Aug 01 '11 at 13:44
  • http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#dom-location ; http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#dom-location-search – hakre Aug 01 '11 at 14:00

10 Answers10

20

try something like this, it should consider also cases when you already have that param in url:

function addOrUpdateUrlParam(name, value)
{
  var href = window.location.href;
  var regex = new RegExp("[&\\?]" + name + "=");
  if(regex.test(href))
  {
    regex = new RegExp("([&\\?])" + name + "=\\d+");
    window.location.href = href.replace(regex, "$1" + name + "=" + value);
  }
  else
  {
    if(href.indexOf("?") > -1)
      window.location.href = href + "&" + name + "=" + value;
    else
      window.location.href = href + "?" + name + "=" + value;
  }
}

then you invoke it like in your case:

addOrUpdateUrlParam('priceMin', 300);
petho
  • 677
  • 4
  • 10
  • If a parameter called `mypriceMin` is already part of the location.href, it might get changed as well, so take care the code is actually working for it's purpose. Additionally, the regex should run on the search part only, not the complete href. – hakre Aug 01 '11 at 14:21
  • @hakre fixed "mypriceMin" problem :) as for search part only - yes it would be more efficient on shorter string, of course this is not optimal solution, anyone can tweak it to his liking – petho Aug 01 '11 at 14:43
  • Added a function below that will actually compare the normalized parameter names, set's parameters that already exists and have no value and removes duplicate parameters. And it works on search only, no need to deal with the rest of the URI. – hakre Aug 01 '11 at 15:30
  • 1
    I found another reason to use `search` instead of `href`: try with `test.html?a=b#filter` - adding to location.href does add parameters even to the wrong part of the location. – hakre Aug 01 '11 at 16:30
  • @harke, true, location.hash can cause stuff, although i guess not in the case that we have here, where we clearly didn't plan to use it. On the other hand .. if you would ajaxify your app and you put your parameters in hash and you want it to do callback when hash changes, you could even want it to be changed by this kind of method call in some cases. Depends on how you design application and its url handling – petho Aug 02 '11 at 07:07
  • For me, this solution added extraneous 1s instead of ?s/&s and had other issues. I ended up using @hakre's solution and it worked well. – davecom Nov 21 '13 at 21:53
  • This sadly did not work when the previous value was a string and it was to be replaced by a number. I also ended up using @hakre's solution. – F_V Apr 06 '17 at 09:21
  • Had some issues here as well, not sure the reason but it wouldn't replace an old value. Had to use the @hakre as well which worked immediately. – Brettins Sep 30 '18 at 01:04
  • After a change in the replacement of the regexp it works like a charm. use \w+ instead of \d+ (words instead of digits) – David Canós Mar 30 '22 at 11:37
18

Actually this is totally trivial, because the javascript location object already deals with this. Just encapsulate this one-liner into a function to re-use it with links etc:

<script>
    function addParam(v) {
        window.location.search += '&' + v;
    }
</script>

<a href="javascript:addParam('priceMin=300');">add priceMin=300</a>

There is no need to check for ? as this is already the search part and you only need to add the param.

If you don't want to even make use of a function you can write as so:

<a href="javascript:location.search+='&priceMin=300';">add priceMin=300</a>

Keep in mind that this does exactly what you've asked for: To add that specific parameter. It can already be part of the search part because you can have the same parameter more than once in an URI. You might want to normalize that within your application, but that's another field. I would centralize URL-normalization into a function of it's own.

Edit:

In discussion about the accepted answer above it became clear, that the following conditions should be met to get a working function:

  • if the parameter already exists, it should be changed.
  • if the parameter already exists multiple times, only the changed copy should survive.
  • if the parameter already exists, but have no value, the value should be set.

As search already provides the search string, the only thing left to achieve is to parse that query-info part into the name and value pairs, change or add the missing name and value and then add it back to search:

<script>
    function setParam(name, value) {
        var l = window.location;

        /* build params */
        var params = {};        
        var x = /(?:\??)([^=&?]+)=?([^&?]*)/g;        
        var s = l.search;
        for(var r = x.exec(s); r; r = x.exec(s))
        {
            r[1] = decodeURIComponent(r[1]);
            if (!r[2]) r[2] = '%%';
            params[r[1]] = r[2];
        }

        /* set param */
        params[name] = encodeURIComponent(value);

        /* build search */
        var search = [];
        for(var i in params)
        {
            var p = encodeURIComponent(i);
            var v = params[i];
            if (v != '%%') p += '=' + v;
            search.push(p);
        }
        search = search.join('&');

        /* execute search */
        l.search = search;
    }
</script>

<a href="javascript:setParam('priceMin', 300);">add priceMin=300</a>

This at least is a bit more robust as it can deal with URLs like these:

test.html?a?b&c&test=foo&priceMin=300

Or even:

test.html?a?b&c&test=foo&pri%63eMin=300

Additionally, the added name and value are always properly encoded. Where this might fail is if a parameter name results in an illegal property js label.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • Thanks, this setParam function is really useful. Is there a way I can call it more than once to set multiple parameters? – Alex Jan 16 '14 at 13:03
8
if(location.search === "") {
    location.href = location.href + "?priceMin=300";
} else {
    location.href = location.href + "&priceMin=300";
}

In case location.search === "", then there is no ? part.

So add ?newpart so that it becomes .php?newpart.

Otherwise there is a ? part already.

So add &newpart so that it becomes .php?existingpart&newpart.


Thanks to hakre, you can also simply set it like:

location.search += "&newpart";

It will automatically add ? if necessary (if not apparent, it will make it ?&newpart this way, but that should not matter).

pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • No need for the `if` in your example, the exact same thing can be done by `location.search += "&priceMin=300";` only. – hakre Aug 01 '11 at 15:29
  • @hakre: I'm sorry but the `if` is there to actually distinguish between `?` and `&`. – pimvdb Aug 01 '11 at 16:26
  • 1
    Which is superfluous as you can make use of `search` which does not require to set the `?` if it's not already part of it. With your code, you would even add it behind the hash-part at the end now as I see it, try with `test.html?a=b#filter`. – hakre Aug 01 '11 at 16:27
  • @hakre: I wasn't aware `location.search` could be set. Thanks. – pimvdb Aug 01 '11 at 18:45
3

There is an more elegant solution available, no need to write your own function.

This will add/update and take care of any ? or & you might need.

var params = new URLSearchParams(window.location.search);
params.set("name", "value");
window.location.search = params.toString();
JamesP
  • 95
  • 1
  • 9
2

I rewrite the correct answer in PHP:

function addOrUpdateUrlParam($name, $value){
$href = $_SERVER['REQUEST_URI'];
$regex = '/[&\\?]' . $name . "=/";
if(preg_match($regex, $href)){
    $regex = '([&\\?])'.$name.'=\\d+';
    $link = preg_replace($regex, "$1" . $name . "=" . $value, $href);
}else{
    if(strpos($href, '?')!=false){
        $link = $href . "&" . $name . "=" . $value;
    }else{
        $link = $href . "?" . $name . "=" . $value;
    }
}
return $link;
}

I hope that help's someone...

Leon Bauer
  • 21
  • 1
1
var applyMinPrice = function(minPrice) {
    var existingParams = (location.href.indexOf('?') !== -1),
        separator = existingParams ? '&' : '?',
        newParams = separator + 'priceMin=' + minPrice;

    location.href += newParams;
}
Martin
  • 1,289
  • 3
  • 13
  • 22
0
<html>
<body>
..
..
..

<?php
$priceMinValue= addslashes ( $_GET['priceMin']);
if (!empty($priceMin)) {
        $link = "currentpage.php?priceMin=". $priceMinValue;
        die("<script>location.href = '".$link. "'</script>");    
}
?>
</body>
</html>
Suresh
  • 1
  • 2
0

If you're having the user fill out a textfield with a minimum price, why not let the form submit as a GET-request with a blank action? IIRC, that should do just what you want, without any javascript.

bjelleklang
  • 476
  • 3
  • 8
  • 25
0

use var urlString = window.location to get the url

check if the url already contains a '?' with urlString.indexOf('?'), -1 means it doesnt exist.

set window.location to redirect

this is like 101 of javascript. try some search engines!

Alberto Zaccagni
  • 30,779
  • 11
  • 72
  • 106
zeal
  • 740
  • 1
  • 4
  • 31
0
<FORM action="" method="get">
<P>
<LABEL for="brand">Brand: </LABEL>
          <INPUT type="text" id="brand"><BR>
<LABEL for="priceMin">Minimum Price: </LABEL>
          <INPUT type="text" id="priceMin"><BR>
</P>

Sherif elKhatib
  • 45,786
  • 16
  • 89
  • 106