Skip to content

Instantly share code, notes, and snippets.

@kuruma-gs
Created August 2, 2011 03:36
Show Gist options
  • Save kuruma-gs/1119555 to your computer and use it in GitHub Desktop.
Save kuruma-gs/1119555 to your computer and use it in GitHub Desktop.
jquery.url.js
// JQuery URL Parser plugin - https://github.com/allmarkedup/jQuery-URL-Parser
// Written by Mark Perkins, mark@allmarkedup.com
// License: http://unlicense.org/ (i.e. do what you want with it!)
;(function($, undefined) {
var tag2attr = {
a : 'href',
img : 'src',
form : 'action',
base : 'href',
script : 'src',
iframe : 'src',
link : 'href'
},
key = ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","fragment"], // keys available to query
aliases = { "anchor" : "fragment" }, // aliases for backwards compatability
parser = {
strict : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs
loose : /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
},
querystring_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g, // supports both ampersand and semicolon-delimted query string key/value pairs
fragment_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g; // supports both ampersand and semicolon-delimted fragment key/value pairs
function parseUri( url, strictMode )
{
var str = decodeURI( url ),
res = parser[ strictMode || false ? "strict" : "loose" ].exec( str ),
uri = { attr : {}, param : {}, seg : {} },
i = 14;
while ( i-- )
{
uri.attr[ key[i] ] = res[i] || "";
}
// build query and fragment parameters
uri.param['query'] = {};
uri.param['fragment'] = {};
uri.attr['query'].replace( querystring_parser, function ( $0, $1, $2 ){
if ($1)
{
uri.param['query'][$1] = $2;
}
});
uri.attr['fragment'].replace( fragment_parser, function ( $0, $1, $2 ){
if ($1)
{
uri.param['fragment'][$1] = $2;
}
});
// split path and fragement into segments
uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/');
uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/');
// compile a 'base' domain attribute
uri.attr['base'] = uri.attr.host ? uri.attr.protocol+"://"+uri.attr.host + (uri.attr.port ? ":"+uri.attr.port : '') : '';
return uri;
};
function getAttrName( elm )
{
var tn = elm.tagName;
if ( tn !== undefined ) return tag2attr[tn.toLowerCase()];
return tn;
}
$.fn.url = function( strictMode )
{
var url = '';
if ( this.length )
{
url = $(this).attr( getAttrName(this[0]) ) || '';
}
return $.url( url, strictMode );
};
$.url = function( url, strictMode )
{
if ( arguments.length === 1 && url === true )
{
strictMode = true;
url = undefined;
}
strictMode = strictMode || false;
url = url || window.location.toString();
return {
data : parseUri(url, strictMode),
// get various attributes from the URI
attr : function( attr )
{
attr = aliases[attr] || attr;
return attr !== undefined ? this.data.attr[attr] : this.data.attr;
},
// return query string parameters
param : function( param )
{
return param !== undefined ? this.data.param.query[param] : this.data.param.query;
},
// return fragment parameters
fparam : function( param )
{
return param !== undefined ? this.data.param.fragment[param] : this.data.param.fragment;
},
// return path segments
segment : function( seg )
{
if ( seg === undefined )
{
return this.data.seg.path;
}
else
{
seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end
if(this.data.seg.path[seg]===undefined){
return 'heart';
}else{
return this.data.seg.path[seg];
}
}
},
// return fragment segments
fsegment : function( seg )
{
if ( seg === undefined )
{
return this.data.seg.fragment;
}
else
{
seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end
return this.data.seg.fragment[seg];
}
},
merge : function( obj )
{
var str=[];
if ( obj === undefined )
{
$.each(this.data.param.query,function(k,v){str.push(k+'='+v)});
}
else
{
$.each($.extend(this.data.param.query,obj),function(k,v){str.push(k+'='+v)});
}
if(str.length==0)
{
return '/'+this.data.seg.path.join('/');
}
else
{
return '/'+this.data.seg.path.join('/') + '?' + str.join('&');
}
},
addMerge : function( obj )
{
var str=[];
if ( obj === undefined )
{
$.each(this.data.param.query,function(k,v){str.push(k+'='+v)});
}
else
{
var newObj = {};
var op = this.data.param.query;
$.each(obj,function(k,v){
if(op[k]===undefined){
newObj[k] = v;
}else{
var ar = op[k].split(/%2C|,/);
ar.push(v);
newObj[k] = $.unique(ar.sort()).join(",");
}
});
$.each($.extend(this.data.param.query,newObj),function(k,v){str.push(k+'='+v)});
}
if(str.length==0)
{
return '/'+this.data.seg.path.join('/');
}
else
{
return '/'+this.data.seg.path.join('/') + '?' + str.join('&');
}
}
};
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment