views:

215

answers:

4

I need to rewrite a querysting using javascript. First I check to see if the variable is present, if it is I want to replace it with a new search term. If it is not present then I just add the new variable

I'm able to get it to work with simple terms like hat, ufc hat whitespaces are %20, so ufc hat is really ufc%20hat

I run into problem with terms like make-up, hat -baseball, coffee & tea, etc..

What is the proper regex for this?

Below is my code, which doesn't work.

var url = String(document.location).split('?');
querystring = url[1];
if(querystring.match(/gbn_keywords=/)!=null)
querystring=querystring.replace(/gbn_keywords=[a-zA-Z0-9%20.]+/,"gbn_keywords="+term);
else
querystring=querystring+"&gbn_keywords="+term;
A: 

No Regex needed. To get the query arguments, take everything after ?. Then, split the string by & to return each argument. Split again by = to get the arg name (right of =) and the value (left of =). Iterate through each argument, a rebuild the URL with each argument, excluding the one you don't want. You shouldn't run into problems here because ?, &, and - must be escaped if they are to be used in arguments. You also said you want to add the argument if it doesn't exist, so just set a variable to true, while you are iterating through each argument, if you find the argument. If you didn't append it to the end of the query string that you rebuilt.

SimpleCoder
Good idea... I think this will give me much more control over the querystring, thanks
Matt
A: 

Why don't you run a split on url[1] and than replace the value of the gbn_keywords in that new array?

And if you use a JavaScript Framework, there might be a handy function that does all that. In Prototype there is the funtion toQueryParams().

Kau-Boy
A: 

& character is used to seperate key and value pairs in the querystring. So that you can match all the characters except for & by re-writing your code as follows:

querystring=querystring.replace(/gbn_keywords=[^&]+/,"gbn_keywords="+term);

[^&]+ matches one or more characters up to & or end of string. But if there may situations where the querystring data may look like ...?gbn_keywords= (no value) then a slight modification is needed to the above line:

querystring=querystring.replace(/gbn_keywords=[^&]*/,"gbn_keywords="+term);

Just change + to * so that the regex will match 0 or more characters. I think this is better.

Zafer
+1  A: 

location objects already have perfectly good properties like pathname, hostname etc. that give you the separate parts of a URL. Use the .search property instead of trying to hack the URL as a string (? may not only appear in that one place).

It's then a case of splitting on the & character (and maybe ; too if you want to be nice, as per HTML4 B2.2) and checking each parameter against the one you're looking for. For the general case this requires proper URL-decoding, as g%62n_keywords=... is a valid way of spelling the same parameter. On the way out naturally you will need to encode again, to stop & going on to the next parameter (as well as to include other invalid characters).

Here's a couple of utility functions you can use to cope with query string manipulation more easily. They convert between the ?... string as seen in location.search or link.search and a lookup Object mapping parameter names to arrays of values (since form-url-encoded queries can have multiple instances of the same parameter).

function queryToLookup(query) {
    var lookup= {};
    var params= query.slice(1).split(/[&;]/);
    for (var i= 0; i<params.length; i++) {
        var ix= params[i].indexOf('=');
        if (ix!==-1) {
            var name= decodeURIComponent(params[i].slice(0, ix));
            var value= decodeURIComponent(params[i].slice(ix+1));
            if (!(name in lookup))
                lookup[name]= [];
            lookup[name].push(value);
        }
    }
    return lookup;
}

function lookupToQuery(lookup) {
    var params= [];
    for (var name in lookup)
        for (var i= 0; i<lookup[name].length; i++)
            params.push(encodeURIComponent(name)+'='+encodeURIComponent(lookup[name][i]));
    return params.length===0? '' : '?'+params.join('&');
}

This makes the usage as simple as:

var lookup= queryToLookup(location.search);
lookup['gbn_keywords']= ['coffee & tea'];
var query= lookupToQuery(lookup);
bobince