Set URL parameters without causing page refresh

Don P picture Don P · Mar 7, 2014 · Viewed 10.8k times · Source

How can you set URL parameters using History.pushState() to avoid browser refreshes? If there is a not a simple JS solution, is there already a popular library or built in function for jQuery?

Here is a relevant SO question, where the accepted answer does not actually work according to comments & my test (it removes the query string instead of updating a value): history.pushState() change query values

Just to be clear, I am referring to the URL parameters in a query string: http://google.com/page?name=don so we could change don to tim without causing a reload.

Here is one possible solution I found. However I'm nervous about using a JS library that only has 2 followers :P

Answer

Don P picture Don P · Mar 8, 2014

You can just use queryString.push('my_param_key', 'some_new_value') from the small library below.

It will update your URL param using history.push, so the browser will not refresh.

It will only affect the param you wish to change, it will leave the path and other params unaffected.

/*!
    query-string
    Parse and stringify URL query strings
    https://github.com/sindresorhus/query-string
    by Sindre Sorhus
    MIT License
*/
(function () {
    'use strict';
    var queryString = {};

    queryString.parse = function (str) {
        if (typeof str !== 'string') {
            return {};
        }

        str = str.trim().replace(/^\?/, '');

        if (!str) {
            return {};
        }

        return str.trim().split('&').reduce(function (ret, param) {
            var parts = param.replace(/\+/g, ' ').split('=');
            var key = parts[0];
            var val = parts[1];

            key = decodeURIComponent(key);
            // missing `=` should be `null`:
            // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
            val = val === undefined ? null : decodeURIComponent(val);

            if (!ret.hasOwnProperty(key)) {
                ret[key] = val;
            } else if (Array.isArray(ret[key])) {
                ret[key].push(val);
            } else {
                ret[key] = [ret[key], val];
            }

            return ret;
        }, {});
    };

    queryString.stringify = function (obj) {
        return obj ? Object.keys(obj).map(function (key) {
            var val = obj[key];

            if (Array.isArray(val)) {
                return val.map(function (val2) {
                    return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
                }).join('&');
            }

            return encodeURIComponent(key) + '=' + encodeURIComponent(val);
        }).join('&') : '';
    };

    queryString.push = function (key, new_value) {
    var params = queryString.parse(location.search);
    params[key] = new_value;
    var new_params_string = queryString.stringify(params)
    history.pushState({}, "", window.location.pathname + '?' + new_params_string);
  }

    if (typeof module !== 'undefined' && module.exports) {
        module.exports = queryString;
    } else {
        window.queryString = queryString;
    }
})();