Web tricks - Manipulate URL through JS

Quite frequently, we need to retrieve some part of the current URL: host, port, parameters, and so on...
Here are some useful JavaScript functions that might help you.

Protocol

/**
 * Function to retrieve the protocol of the URL
 * 
 * @see http://www.w3schools.com/jsref/prop_loc_protocol.asp
 * 
 * @returns the protocol of the URL
 */
function getUrlProtocol() {
	return location.protocol;
}

Host

/**
 * Function to retrieve the host of the URL
 * 
 * @see http://www.w3schools.com/jsref/prop_loc_hostname.asp
 * 
 * @returns the host of the URL
 */
function getUrlHost() {
	return location.hostName;
}

Port

/**
 * Function to retrieve the port of the URL
 * 
 * @see http://www.w3schools.com/jsref/prop_loc_port.asp
 * 
 * @returns the port of the URL
 */
function getUrlPort() {
	return location.port;
}

Origin

The origin in the URL contains the protocol, the host and the port if any. As such, it can be a very useful information:

/**
 * Function to retrieve the origin from the current URL.
 * Uses the browser <code>location.origin</code> if it exists, 
 * or defines the origin manually otherwise.
 * 
 * @return the URL origin
 */
function getUrlOrigin() {
	if (typeof location.origin == 'undefined')
		return location.protocol + "//" + location.hostname + (location.port ? ':' + location.port: '');
	else
		return location.origin;
}

Path

The «default» format of the URL's path is not always interesting: the first and last / are usually unimportant once you have the origin (see above), and the same goes for the default file opened when indexing a directory (the important information is the directory itself).
In order to remove those information, we need a function to «clean» the path:

/**
 * Function to clean a path
 * 
 * The function will get rid of the first and last '/', 'index.*' or 
 * 'default.*', etc...
 * 
 * @param {String} string path to clean
 * @returns the path cleaned
 */
function filterPath(string)
{
    return string
        .replace('/^\//', '')
        .replace('/(index|default).[a-zA-Z]{3,4}$/', '')
        .replace('/\/$/', '');
}

With the previous function, we can get rid of all useless information in a URL path.

Now, we can retrieve the URL's path:

/**
 * Function to retrieve the path of the URL
 * 
 * @see http://www.w3schools.com/jsref/prop_loc_pathname.asp
 * 
 * @param clean whether or not the path should be cleaned with {filterPath}
 * 	(default behavior)
 * @returns the path
 */
function getUrlPath(clean) {
	var path = location.pathname;
	return (clean == null || clean) ? filterPath(path) : path;
}

Parameter(s)

A function to retrieve an array containing all URL's parameters:

/**
 * Function to retrieve the parameters of the URL
 * 
 * @see http://www.w3schools.com/jsref/prop_loc_search.asp
 * @see http://www.w3schools.com/jsref/jsref_split.asp
 * 
 * @param separator Optional. Specifies the character to use for splitting the 
 * string. If omitted, '&' will be used.
 * @returns array of parameters
 */
function getUrlParameters(separator) {
	var query = location.search.split('?');
	if (query.length <= 1)
		return [];

	var parameters = query[1].split(separator ? separator : '&');
	for (var i = 0, n = parameters.length ; i < n ; i++) {
		var index = parameters[i].indexOf("=");
		var name = (index > -1) ? parameters[i].substr(0, index) : parameters[i];
		name = name.replace(/^\s+|\s+$/g, "");
		value = (index > -1) ? decodeURIComponent(parameters[i].substr(index + 1)) : true;
		parameters[i] = Array(name, value);
	}
	return parameters;
}

A function to retrieve a specific parameter:

/**
 * Function to retrieve a parameter of the URL
 * 
 * @see http://www.w3schools.com/jsref/prop_loc_search.asp
 * 
 * @param pName name of the parameter to retrieve
 * @param separator Optional. Specifies the character to use for splitting the 
 * string. If omitted, '&' will be used.
 * @returns the value of the parameter, true if the parameter is only defined,
 * 	null if not found
 */
function getUrlParameter(pName, separator) {
	var query = location.search.split('?');
	if (query.length <= 1)
		return null;

	var parameters = query[1].split(separator ? separator : '&');
	for (var i = 0, n = parameters.length ; i < n ; i++) {
		var index = parameters[i].indexOf("=");
		var name = (index > -1) ? parameters[i].substr(0, index) : parameters[i];
		name = name.replace(/^\s+|\s+$/g, "");
		if (name == pName) {
			value = (index > -1) ? decodeURIComponent(parameters[i].substr(index + 1)) : true;
			return value;
		}
	}
	return null;
}

Anchor

/**
 * Function to retrieve the anchor of the URL
 * 
 * @see http://www.w3schools.com/jsref/prop_loc_hash.asp
 * 
 * @returns the anchor of the URL
 */
function getUrlAnchor() {
	return location.hash;
}

Setting the URL

Up until now, I have only presented functions to retrieve parts of the URL, but I never mentionned how to change it. The reason is that is so simple it does not require any functions. Just setting the proper parameter in the location is enough:

window.location = 'http://my.website.com';
// redirects to http://my.website.com

As mentionned, setting the location reload the browser with the new URL. This is actually quite troublesome when working with AJAX websites that require to update the URL and the content of the page without reloading the whole page!

In this case, the solution is to manipulate the browser's history. Instead of changing the URL, which would reload the page, we will push a new state in the browser's history to store the URL for the new content of the page. Here is a simple function to do it:

function setUrl(newUrl, refresh, stateObject, stateTitle, popStateFct) {
	if (typeof refresh == 'undefined' || refresh) {
		window.location.href = newUrl;
	}
	else {
		window.history.pushState(stateObject,stateTitle,newUrl);
		window.onpopstate = popStateFct;
	}
}

In some case, AJAX website need to update the whole ULR, but in some other cases, we might just need to update the parameters. To do so, first we need to add or update the parameter:

/**
 * Function to change a parameter of the URL
 * 
 * If the parameter already exists, its value is changed with the new one.
 * 
 * @see W3Schools: Location search Property
 * 
 * @param pName name of the parameter to set
 * @param newValue Optional. New value of the parameter to set
 * @param separator Optional. Specifies the character to use for splitting the 
 * string. If omitted, '&' will be used.
 * 
 * @return the string containing all parameters
 */
function changeUrlParameter(pName, newValue, separator) {
	var strParam = window.location.search.substring(window.location.search.indexOf('?')+1);

	var newUrlSearch = '?',
		found = false, i = 0, 
		paramSeparator = (separator ? separator : '&'),
		parameters = strParam.length == 0 ? '' : strParam.split(paramSeparator);
	for (var n = parameters.length ; i < n ; i++) {
		var index = parameters[i].indexOf('=');
		var name = (index > -1) ? parameters[i].substr(0, index) : parameters[i];
		name = name.replace(/^\s+|\s+$/g, "");
		if (i > 0) {
			newUrlSearch += paramSeparator;
		}
		if (name == pName) {
			newUrlSearch += name + (newValue ? '=' + newValue : '');
			found = true;
		} else {
			value = (index > -1) ? decodeURIComponent(parameters[i].substr(index + 1)) : true;
			newUrlSearch += name + (value != true ? '=' + value : '');
		}
	}
	if (!found) {
		if (i > 0) {
			newUrlSearch += paramSeparator;
		}
		newUrlSearch += pName + (newValue ? '=' + newValue : '');
	}

	return newUrlSearch;
}

Using these functions, we can now easily set a parameter in the URL:

function setUrlParameter(pName, newValue, separator, refresh, stateObject, stateTitle, popStateFct) {
	var strParam = changeUrlParameter(pName, newValue, separator);

	var newUrl = getUrlOrigin() + getUrlPath() + strParam;
	setUrl(newUrl,refresh,stateObject,stateTitle,popStateFct);

	return newUrl;
}
Back to top