/**
* The Url Utility.
*
* @module aui-url
*/
var QS = A.QueryString,
_SCHEME_SEPARATOR = '://',
URL_SOURCE = 0,
URL_PROTOCOL = 1,
URL_AUTHORITY = 2,
URL_USER_INFO = 3,
URL_USER = 4,
URL_PASSWORD = 5,
URL_HOST = 6,
URL_PORT = 7,
URL_RELATIVE = 8,
URL_PATH = 9,
URL_DIRECTORY = 10,
URL_FILE = 11,
URL_QUERY = 12,
URL_ANCHOR = 13;
function Url(url) {
var instance = this;
if (!url) {
throw 'An URL should be specified.';
}
instance._indexParts(url);
instance._indexParameters();
}
// Loose implementation of http://tools.ietf.org/html/rfc3986
// See http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
Url.URI_REGEX_RFC3986 = new RegExp('^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)' +
'?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)' +
'(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*)' +
')(?:\\?([^#]*))?(?:#(.*))?)');
/**
* A base class for `A.Url`.
*
* In order to understand what each attribute/method does,
* you need to see the anatomy of a URL:
*
* ```
* foo://example.com:8042/over/there?name=ferret#nose
* \_/ \______________/\_________/ \_________/ \__/
* Scheme Authority Path Query Anchor
* ```
*
* @class A.Url
* @param {Object} config Object literal specifying widget configuration
* properties.
* @constructor
*/
A.mix(Url.prototype, {
_source: undefined,
_protocol: undefined,
_authority: undefined,
_user_info: undefined,
_user: undefined,
_password: undefined,
_host: undefined,
_port: undefined,
_relative: undefined,
_path: undefined,
_directory: undefined,
_file: undefined,
_query: undefined,
_anchor: undefined,
_parameters: undefined,
/**
* Adds a single parameter in the URL.
*
* @method addParameter
* @param key
* @param values
*/
addParameter: function(key, values) {
var instance = this;
instance.setParameter(key, !instance.hasParameter(key) ?
values :
A.Array(instance.getParameter(key)).concat(values));
},
/**
* Adds a list of parameters in the URL.
*
* @method addParameters
* @param parameters
*/
addParameters: function(parameters) {
var instance = this;
A.each(parameters, function(val, key) {
instance.addParameter(key, val);
});
},
/**
* Checks if the URL has a parameter.
*
* @method hasParameter
* @param key
* @return {Boolean}
*/
hasParameter: function(key) {
var instance = this;
return instance._parameters.hasOwnProperty(key);
},
/**
* Gets a single parameter.
*
* @method getParameter
* @param key
* @return {String}
*/
getParameter: function(key) {
var instance = this;
return instance._parameters[key];
},
/**
* Gets a list of parameters.
*
* @method getParameters
* @return {Array}
*/
getParameters: function() {
var instance = this;
return instance._parameters;
},
/**
* Gets the anchor.
*
* @method getAnchor
* @return {String}
*/
getAnchor: function() {
var instance = this;
return instance._anchor;
},
/**
* Gets the authority.
*
* @method getAuthority
* @return {String}
*/
getAuthority: function() {
var instance = this;
return instance._authority;
},
/**
* Gets the directory.
*
* @method getDirectory
* @return {String}
*/
getDirectory: function() {
var instance = this;
return instance._directory;
},
/**
* Gets the file.
*
* @method getFile
* @return {String}
*/
getFile: function() {
var instance = this;
return instance._file;
},
/**
* Gets the host.
*
* @method getHost
* @return {String}
*/
getHost: function() {
var instance = this;
return instance._host;
},
/**
* Gets the password.
*
* @method getPassword
* @return {String}
*/
getPassword: function() {
var instance = this;
return instance._password;
},
/**
* Gets the path.
*
* @method getPath
* @return {String}
*/
getPath: function() {
var instance = this;
return instance._path;
},
/**
* Gets the port.
*
* @method getPort
* @return {String}
*/
getPort: function() {
var instance = this;
return instance._port;
},
/**
* Gets the protocol.
*
* @method getProtocol
* @return {String}
*/
getProtocol: function() {
var instance = this;
return instance._protocol;
},
/**
* Gets the query.
*
* @method getQuery
* @return {String}
*/
getQuery: function() {
var instance = this;
return instance._query;
},
/**
* Gets the relative.
*
* @method getRelative
* @return {String}
*/
getRelative: function() {
var instance = this;
return instance._relative;
},
/**
* Gets the source.
*
* @method getSource
* @return {String}
*/
getSource: function() {
var instance = this;
return instance._source;
},
/**
* Gets the user.
*
* @method getUser
* @return {String}
*/
getUser: function() {
var instance = this;
return instance._user;
},
/**
* Gets the user info.
*
* @method getUserInfo
* @return {String}
*/
getUserInfo: function() {
var instance = this;
return instance._user_info;
},
/**
* Removes a single parameter from the parameters list.
*
* @method removeParameter
* @param key
*/
removeParameter: function(key) {
var instance = this;
delete instance._parameters[key];
instance._indexParameters();
},
/**
* Removes a list of parameters from the parameters list.
*
* @method removeParameters
* @param parameters
*/
removeParameters: function(parameters) {
var instance = this;
A.each(parameters, function(val, key) {
instance.removeParameter(key);
});
},
/**
* Sets a single parameter.
*
* @method setParameter
* @param key
* @param opt_values
*/
setParameter: function(key, opt_values) {
var instance = this;
instance._parameters[key] = opt_values;
instance._indexParameters();
},
/**
* Sets a list of parameters.
*
* @method setParameters
* @param parameters
*/
setParameters: function(parameters) {
var instance = this;
A.each(parameters, function(val, key) {
instance.setParameter(key, val);
});
},
/**
* Sets the anchor.
*
* @method setAnchor
* @param val
*/
setAnchor: function(val) {
var instance = this;
instance._anchor = val;
},
/**
* Sets the authority.
*
* @method setAuthority
* @param val
*/
setAuthority: function(val) {
var instance = this;
instance._authority = val;
},
/**
* Sets the directory.
*
* @method setDirectory
* @param val
*/
setDirectory: function(val) {
var instance = this;
instance._directory = val;
},
/**
* Sets the file.
*
* @method setFile
* @param val
*/
setFile: function(val) {
var instance = this;
instance._file = val;
},
/**
* Sets the host.
*
* @method setHost
* @param val
*/
setHost: function(val) {
var instance = this;
instance._host = val;
},
/**
* Sets the password.
*
* @method setPassword
* @param val
*/
setPassword: function(val) {
var instance = this;
instance._password = val;
},
/**
* Sets the path.
*
* @method setPath
* @param val
*/
setPath: function(val) {
var instance = this;
instance._path = val;
},
/**
* Sets the port.
*
* @method setPort
* @param val
*/
setPort: function(val) {
var instance = this;
instance._port = val;
},
/**
* Sets the protocol.
*
* @method setProtocol
* @param val
*/
setProtocol: function(val) {
var instance = this;
instance._protocol = val;
},
/**
* Sets the relative.
*
* @method setRelative
* @param val
*/
setRelative: function(val) {
var instance = this;
instance._relative = val;
},
/**
* Sets the source.
*
* @method setSource
* @param val
*/
setSource: function(val) {
var instance = this;
instance._source = val;
},
/**
* Sets the user.
*
* @method setUser
* @param val
*/
setUser: function(val) {
var instance = this;
instance._user = val;
},
/**
* Sets the user info.
*
* @method setUserInfo
* @param val
*/
setUserInfo: function(val) {
var instance = this;
instance._user_info = val;
},
/**
* Generates the entire URL based on each attribute.
*
* @method toString
* @return {String}
*/
toString: function() {
var instance = this,
url = [];
// foo://example.com:8042/over/there?name=ferret#nose
// \_/ \______________/\_________/ \_________/ \__/
// scheme authority path query anchor
if (instance._protocol) {
url.push(
instance._protocol,
_SCHEME_SEPARATOR
);
}
url.push(
instance._authority,
instance._path
);
if (instance._query) {
url.push(
'?',
instance._query
);
}
if (instance._anchor) {
url.push(
'#',
instance._anchor
);
}
return url.join('');
},
/**
* Indexes all parameters into the query.
*
* @method _indexParameters
* @protected
*/
_indexParameters: function() {
var instance = this;
if (!instance._parameters) {
instance._parameters = QS.parse(instance._query || '');
}
instance._query = QS.stringify(instance._parameters);
},
/**
* Indexes all URL parts to its private attributes.
*
* @method _indexParts
* @param url
* @protected
*/
_indexParts: function(url) {
var instance = this,
parts = Url.URI_REGEX_RFC3986.exec(url);
instance._source = parts[URL_SOURCE];
instance._protocol = parts[URL_PROTOCOL];
instance._authority = parts[URL_AUTHORITY];
instance._user_info = parts[URL_USER_INFO];
instance._user = parts[URL_USER];
instance._password = parts[URL_PASSWORD];
instance._host = parts[URL_HOST];
instance._port = parts[URL_PORT];
instance._relative = parts[URL_RELATIVE];
instance._path = parts[URL_PATH];
instance._directory = parts[URL_DIRECTORY];
instance._file = parts[URL_FILE];
instance._query = parts[URL_QUERY];
instance._anchor = parts[URL_ANCHOR];
}
}, true);
A.Url = Url;