Skip to content

Instantly share code, notes, and snippets.

@sujeetkv
Last active February 19, 2019 07:29
Show Gist options
  • Save sujeetkv/290dd2f417fe08d19e7dd634f972d22b to your computer and use it in GitHub Desktop.
Save sujeetkv/290dd2f417fe08d19e7dd634f972d22b to your computer and use it in GitHub Desktop.
URL State manipulation utility
/**
* URL State manipulation utility
*
* Usage Example:
* //urlState.strictMode = (function() { return !this; })();
* var queryString = urlState.search();
* queryString.name = 'sujeet';
* urlState.pathname('/result-page').search(queryString).update();
*/
(function (win) {
'use strict';
var toType = function (val) {
var type = Object.prototype.toString.call(val);
return type.replace(/\[(\w+)\s(\w+)\]/, '$2').toLowerCase();
};
var parseQstr = function (queryString, coerce) {
queryString = ('' + queryString).replace(/^\?/, '');
var re = /([^&=]+)=?([^&]*)/g,
m,
params = {},
coerceTypes = {'true': !0, 'false': !1, 'null': null},
decode = function (str) {
return decodeURIComponent(str.replace(/\+/g, '%20'));
};
if (queryString) {
while (m = re.exec(queryString)) {
var k = decode(m[1]),
v = decode(m[2]),
curr = params;
if (coerce) {
v = !isNaN(v) ? +v : (v === 'undefined' ? undefined : (coerceTypes[v] ? coerceTypes[v] : v));
}
var keys = k.split('][');
var keysLast = keys.length - 1;
if (/\[/.test(keys[0]) && /\]$/.test(keys[keysLast])) {
keys[keysLast] = keys[keysLast].replace(/\]$/, '');
keys = keys.shift().split('[').concat(keys);
keysLast = keys.length - 1;
}
if (keysLast) {
for (var i = 0; i <= keysLast; i++) {
k = (keys[i] === '') ? curr.length : keys[i];
curr = curr[k] = (i < keysLast) ? curr[k] || (keys[i+1] && isNaN(keys[i+1]) ? {} : []) : v;
}
} else if (params[k]) {
if (toType(params[k]) === 'array') {
params[k].push(v);
} else {
params[k] = [params[k], v];
}
} else {
params[k] = v;
}
}
}
return params;
};
var createQstr = function (obj) {
var key, s = [];
var add = function (k, v) {
v = typeof v === 'function' ? v() : v;
v = (v === null || v === undefined) ? '' : v === undefined ? '' : v;
s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
};
var buildParams = function (prefix, obj) {
var i, len, key, objectType = toType(obj);
if (objectType === 'array') {
for (i = 0, len = obj.length; i < len; i++) {
buildParams(prefix + '[' + (typeof obj[i] === 'object' && obj[i] ? i : '') + ']', obj[i]);
}
} else if (objectType === 'object') {
for (key in obj) {
buildParams(prefix + '[' + key + ']', obj[key]);
}
} else {
add(prefix, obj);
}
};
for (key in obj) {
buildParams(key, obj[key]);
}
return s.join('&');
};
win.urlState = (function () {
var init_state = win.history.state,
init_title = win.document.title,
init_loc = win.document.createElement('a'),
wloc = win.document.createElement('a');
init_loc.href = win.location.href;
wloc.href = win.location.href;
return {
strictMode: true,
get protocol() { return wloc.protocol; },
set protocol(value) {
if (this.strictMode) {
throw new TypeError('"protocol" is read-only');
}
},
get host() { return wloc.host; },
set host(value) {
if (this.strictMode) {
throw new TypeError('"host" is read-only');
}
},
get hostname() { return wloc.hostname; },
set hostname(value) {
if (this.strictMode) {
throw new TypeError('"hostname" is read-only');
}
},
get port() { return wloc.port; },
set port(value) {
if (this.strictMode) {
throw new TypeError('"port" is read-only');
}
},
pathname: function (pathname) {
if (pathname === undefined) {
return wloc.pathname;
} else {
wloc.pathname = pathname;
return this;
}
},
search: function (search) {
if (search === undefined) {
return parseQstr(wloc.search);
} else {
wloc.search = createQstr(search);
return this;
}
},
hash: function (hash) {
if (hash === undefined) {
return wloc.hash;
} else {
wloc.hash = hash;
return this;
}
},
update: function (title, replace) {
win.history[replace?'replaceState':'pushState'](init_state, '', this.toString());
win.document.title = title || init_title;
return this;
},
reset: function () {
wloc = init_loc;
win.history.replaceState(init_state, '', this.toString());
win.document.title = init_title;
return this;
},
toString: function () {
return wloc.toString();
},
};
})();
})(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment