src/scripts/utils/urlUtils.js
'use strict';
var utilities = require('./utilityFunctions');
/**
*
* IMPORTANT NOTE: This function comes from angularJs and was originally called urlResolve
* you can take a look at the original code here https://github.com/angular/angular.js/blob/master/src/ng/urlUtils.js
*
* Implementation Notes for non-IE browsers
* ----------------------------------------
* Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
* results both in the normalizing and parsing of the URL. Normalizing means that a relative
* URL will be resolved into an absolute URL in the context of the application document.
* Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
* properties are all populated to reflect the normalized URL. This approach has wide
* compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
* http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
*
* Implementation Notes for IE
* ---------------------------
* IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other
* browsers. However, the parsed components will not be set if the URL assigned did not specify
* them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
* work around that by performing the parsing in a 2nd step by taking a previously normalized
* URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
* properties such as protocol, hostname, port, etc.
*
* IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one
* uses the inner HTML approach to assign the URL as part of an HTML snippet -
* http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL.
* Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception.
* Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that
* method and IE < 8 is unsupported.
*
* References:
* http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
* http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
* http://url.spec.whatwg.org/#urlutils
* https://github.com/angular/angular.js/pull/2902
* http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
*
* @kind function
* @param {string} url The URL to be parsed.
* @description Normalizes and parses a URL.
* @returns {object} Returns the normalized URL as a dictionary.
*
* | member name | Description |
* |---------------|----------------|
* | href | A normalized version of the provided URL if it was not an absolute URL |
* | protocol | The protocol including the trailing colon |
* | host | The host and port (if the port is non-default) of the normalizedUrl |
* | search | The search params, minus the question mark |
* | hash | The hash string, minus the hash symbol
* | hostname | The hostname
* | port | The port, without ":"
* | pathname | The pathname, beginning with "/"
*
*/
var urlParsingNode = document.createElement("a");
/**
* documentMode is an IE-only property
* http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
*/
var msie = document.documentMode;
function urlParts(url) {
var href = url;
if (msie) {
// Normalize before parse. Refer Implementation Notes on why this is
// done in two steps on IE.
urlParsingNode.setAttribute("href", href);
href = urlParsingNode.href;
}
urlParsingNode.setAttribute('href', href);
// urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
return {
href: urlParsingNode.href,
protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
host: urlParsingNode.host,
search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
hostname: urlParsingNode.hostname,
port: utilities.isNotEmptyString(urlParsingNode.port)? urlParsingNode.port: 80,
pathname: (urlParsingNode.pathname.charAt(0) === '/')
? urlParsingNode.pathname
: '/' + urlParsingNode.pathname
};
}
/**
* This function accepts a query string (search part of a url) and returns a dictionary with
* the different key value pairs
* @param {string} qs queryString
*/
function queryStringToObj(qs, cond) {
var pairs, qsObj;
cond = utilities.isFunction(cond)? cond : function() {
return true;
};
qs = qs.trim().replace(/^\?/, '');
pairs = qs.split('&');
qsObj = {};
utilities.forEach(pairs, function (pair) {
var keyValue, key, value;
if (pair !== '') {
keyValue = pair.split('=');
key = keyValue[0];
value = keyValue[1];
if(cond(key, value)){
qsObj[key] = value;
}
}
});
return qsObj;
}
/**
* This function accepts an object and serializes it into a query string without the leading '?'
* @param obj
* @returns {string}
*/
function objToQueryString(obj) {
var pairs = [];
utilities.forEach(obj, function (value, key) {
pairs.push(key + '=' + value);
});
return pairs.join('&');
}
module.exports = {
urlParts: urlParts,
queryStringToObj: queryStringToObj,
objToQueryString: objToQueryString
};