Skip to content

Instantly share code, notes, and snippets.

@termi
Last active December 16, 2015 13:39
Show Gist options
  • Save termi/5443716 to your computer and use it in GitHub Desktop.
Save termi/5443716 to your computer and use it in GitHub Desktop.
JavaScript + DOM implementation of http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html
void function() {
"use strict";
var global = this;
//Mini alternative https://gist.github.com/2428561
//Uses
//https://gist.github.com/1384398
//https://gist.github.com/1235332
function parseSearch(s, match, notMatch, valueOnly, nameOnly) {
var result = []
, parts = s.slice(1).split('&')
, i = 0
, part
, key
, value
;
for( ; i < parts.length; i++ ) {
part = parts[i];
key = part.split('=', 1)[0];
if( key && (match == void 0 || match == key) && (notMatch == void 0 || notMatch != key) ) {
value = part.slice(key.length + 1);
result.push(valueOnly ? value : nameOnly ? key : [key, value]);
}
}
return result;
}
function serializeParsed(array) {
var i = 0
, l = array.length
, result = []
, pair
;
for( ; i < l ; ++i ) {
pair = array[i];
result[i] = pair[1] !== '' ? pair.join('=') : pair[0];
}
return result.join('&');
}
function _URL(url, base) {
if( this === global || this === null ) {
throw new TypeError("DOM object constructor cannot be called as a function");
}
if( !url )
throw new TypeError('Invalid argument');
var thisObj = this
//https://gist.github.com/1235332
, m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/)
;
thisObj.href = m[0];
if( thisObj.href === '' ) {
throw new TypeError('Invalid URL');
}
thisObj.protocol = m[1] || "";
thisObj.authority = m[2] || "";
thisObj.host = m[3] || "";
thisObj.hostname = m[4] || "";
thisObj.port = m[5] || "";
thisObj.pathname = m[6] || "";
thisObj.search = m[7] || "";
thisObj.hash = m[8] || "";
var match;
if( (match = thisObj.pathname.match(/\/([^\/]+)$/)) ) {
thisObj.filename = match[1];
}
thisObj.filename = '';
thisObj.parameterNames = Object.create ? Object.create(null) : {};
var searchArray = parseSearch(thisObj.search, void 0, void 0, void 0, true)
, i = 0
, l = searchArray.length
, result = []
, name
;
for( ; i < l ; ++i ) {
name = searchArray[i];
if( !(name in thisObj.parameterNames) ) {
thisObj.parameterNames[name] = true;
result.push(name);
}
}
}
_URL.prototype = {
toString: function() {
return this.href;
},
// NOT IMPLEMENTED
// get username() {
// return this._anchorElement.username;
// },
// set username(value) {
// this._anchorElement.username = value;
// },
// get password() {
// return this._anchorElement.password;
// },
// set password(value) {
// this._anchorElement.password = value;
// },
// get origin() {
// return this._anchorElement.origin;
// },
getParameter: function(name) {
return this.getParameterAll(name).pop();
},
getParameterAll: function(name) {
return parseSearch(this.search, name + "", void 0, true);
},
appendParameter: function(name, values) {
this.parameterNames[name] = true;
if( !Array.isArray(values) ) {
values = [values];
}
var parsed = parseSearch(this.search);
for( var i = 0; i < values.length; i++ ) {
parsed.push([name, values[i]]);
}
parsed = serializeParsed(parsed);
this.search = parsed ? ("?" + parsed) : "";
_recalculateHref.call(this);
},
clearParameter: function(name) {
if( name in this.parameterNames ) {
delete this.parameterNames[name];
}
name = serializeParsed(
parseSearch(this.search, void 0, name)
);
this.search = name ? ("?" + name) : "";
_recalculateHref.call(this);
}
};
function _recalculateHref() {
this.href = this.protocol + "//" + this.host + this.pathname + this.search;
}
var oldURL;
if( oldURL = global.URL || global.webkitURL || global.mozURL ) {
if( oldURL.createObjectURL ) {
_URL.createObjectURL = function(blob) {
return this.createObjectURL.apply(this, arguments);
}.bind(oldURL);
}
if( oldURL.revokeObjectURL ) {
_URL.revokeObjectURL = function(url) {
return this.revokeObjectURL.apply(this, arguments);
}.bind(oldURL);
}
}
oldURL = null;
/*
// Methods should not be enumerable.
Object.defineProperty(_URL.prototype, 'toString', {enumerable: false});
Object.defineProperty(_URL.prototype, 'getParameter', {enumerable: false});
Object.defineProperty(_URL.prototype, 'getParameterAll', {enumerable: false});
Object.defineProperty(_URL.prototype, 'appendParameter', {enumerable: false});
Object.defineProperty(_URL.prototype, 'clearParameter', {enumerable: false});
Object.defineProperty(_URL, 'createObjectURL', {enumerable: false});
Object.defineProperty(_URL, 'revokeObjectURL', {enumerable: false});*/
//EXPORT
global["URL"] = _URL;
}.call(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment