// JQuery URL Toolbox
// Written by Mark Perkins, mark@allmarkedup.com
// License: http://unlicense.org/ (i.e. do what you want with it!)
// https://github.com/allmarkedup/jQuery-URL-Toolbox
/*
Use var myUrl = $(element).url() to grab an element's URL and return a special 'URL' object. (a, form, img, base, link and iframe elements are supported, and using 'document' (no quotes) as the selector will return a URL object based on the current page's URL)

Then use myUrl.attr('theAttr') to return any part of the URL, where 'theAttr' can be any one of: source, protocol, host, port, query, file, hash or path.

If you include a second argument to the attr() method – i.e. something like myUrl.attr('path', '/myNewPath/'), then it will set the value of that part of the URL to the value of the second argument. Whatever the URL of element the initial url() function was called on will be updated accordingly. If the document URL was used (via $(document).url()) then the location will be changed accordingly, normally resulting in a page refresh.

Doing a .toString() on the URL object at any time will return the current string representation of the URL.

The .segment(i) method (where 'i' is the segment number, starting from zero) will return the corresponding segment from the URL. Including a second parameter will set that segment.

The .param('key') method (where 'key' is the query string key) will return the corresponding value of the suppied key in the URL query (GET) string, if there is one. Including a second parameter will set that parameter.

If you have a hash fragment that consists of segments, like #/part1/part2/ then you can get/set those segments using the hashSegment() method, which works exactly like the segment() one.

Similarly if you have a hash fragment that looks like a query string, the parts can be get/set using the hashParam() method.
*/
;(function($){var isStr=function(item){return typeof item==='string';};var isObj=function(item){return typeof item==='object';};var isfunc=function(item){return typeof item==='function';};var isGetter=function(args){return(args.length==1&&!isObj(args[0]));}
var isSetter=function(args){return(args.length>=2||(args.length==1&&isObj(args[0])));}
var stripQ=function(str){return str.replace(/\?.*$/,'');}
var stripH=function(str){return str.replace(/^#/,'');}
var loc=document.location,tag2attr={a:'href',img:'src',form:'action',base:'href',script:'src',iframe:'src',link:'href'};function splitQuery(string)
{var ret={},seg=string.replace(/^\?/,'').split('&'),len=seg.length,i=0,s;for(;i<len;i++)
{if(!seg[i]){continue;}
s=seg[i].split('=');ret[s[0]]=s[1];}
return ret;}
var combineQuery=function(params,prefixQM)
{var queryString=(prefixQM===true)?'?':'';for(i in params)queryString+=i+'='+params[i]+'&';return queryString.slice(0,-1);};var combinePath=function(segments)
{return segments.join('/');};function splitHashSegments(hash)
{if(hash.indexOf('=')===-1)
{if(hash.charAt(hash.length-1)=='/')hash=hash.slice(0,-1);return hash.replace(/^\//,'').split('/');}
return null;}
function splitHashParams(hash)
{if(hash.indexOf('=')!==-1)return splitQuery(hash);return null;}
var getTagName=function(elm)
{var tg=$(elm).get(0).tagName;if(tg!==undefined)return tg.toLowerCase();return tg;}
var throwParserError=function(msg)
{if(msg===undefined)msg='url parser error';};var getHost=function(hostname,port)
{var portRegex=new RegExp(':'+port);return hostname.replace(portRegex,'');}
$.extend($.expr[':'],{external:function(elm,i,m)
{var tagName=elm.tagName;if(tagName!==undefined)
{var tg=tagName.toLowerCase();var attr=tag2attr[tg];if(elm[attr])
{if(tg!=='a')
{var a=document.createElement('a');a.href=elm[attr];}
else var a=elm;return a.hostname&&getHost(a.hostname,a.port)!==getHost(loc.hostname,loc.port);}}
return false;},internal:function(elm,i,m)
{var tagName=elm.tagName;if(tagName!==undefined)
{var tg=tagName.toLowerCase();var attr=tag2attr[tg];if(elm[attr])
{if(tg!=='a')
{var a=document.createElement('a');a.href=elm[attr];}
else var a=elm;return a.hostname&&getHost(a.hostname,a.port)===getHost(loc.hostname,loc.port);}}
return false;}});$.url=function(urlString)
{return new activeUrl(urlString);};$.fn.url=function()
{if(this.size()>1)
{var activeUrls={};this.each(function(i){activeUrls[i]=new activeUrl($(this));});return activeUrls;}
else
{return new activeUrl(this);}};function parseUrl(url)
{var a=document.createElement('a');a.href=url;if(a.protocol==":")a.protocol='http:';return{source:url,protocol:a.protocol.replace(':',''),host:getHost(a.hostname,a.port),base:(function(){if(a.port!=0&&a.port!==null&&a.port!=="")return a.protocol+"//"+getHost(a.hostname,a.port)+":"+a.port;return a.protocol+"//"+a.host;})(),port:a.port,query:a.search,params:splitQuery(a.search),file:(a.pathname.match(/\/([^\/?#]+)$/i)||[,''])[1],hash:stripH(a.hash),path:(function(){var pn=a.pathname.replace(/^([^\/])/,'/$1');if(pn=='/')pn='';return pn;})(),segments:a.pathname.replace(/^\//,'').split('/'),hashSegments:splitHashSegments(stripH(a.hash)),hashParams:splitHashParams(stripH(a.hash))};};var activeUrl=function(source)
{var sourceType=null,ref=null,parsed={};var makeHash=function(prefixHash)
{var hash='';if(parsed.hashParams!=null)
{hash=makeQueryString(parsed.hashParams);}
else if(parsed.hashSegments!=null)
{hash=makePathString(parsed.hashSegments);}
if(hash!=='')
{if(parsed.hash.charAt(0)=='/')hash='/'+hash;if(prefixHash===true)return'#'+hash;return hash;}
return'';};var updateElement=function()
{if(sourceType=='elm')
{ref.attr(tag2attr[getTagName(ref)],parsed.source);}
else if(sourceType=='doc')
{loc.href=parsed.source;}};var updateSource=function()
{parsed.source=parsed.base+parsed.path+parsed.query;if(parsed.hash&&parsed.hash!='')parsed.source+='#'+parsed.hash;}
var updateParsedAttrs=function(key,val)
{switch(key)
{case'source':parsed=parseUrl(val);break;case'base':if(val.charAt(val.length-1)=='/')val=val.slice(0,-1);var a=document.createElement('a');a.href=parsed.base=val;parsed.protocol=a.protocol.replace(':','');parsed.host=getHost(a.hostname,a.port);parsed.port=a.port;break;case'protocol':case'host':case'port':parsed[key]=val;if(a.port!=0&&a.port!==null&&a.port!=="")parsed.base=a.protocol+"//"+getHost(a.hostname,a.port)+":"+a.port;else parsed.base=a.protocol+"//"+a.host;break;case'query':parsed.query='?'+val.replace(/\?/,'');parsed.params=splitQuery(val);break;case'file':parsed.path=parsed.path.replace(new RegExp(parsed.file+'$'),val);parsed.file=val;break;case'hash':parsed.hash=val;parsed.hashSegments=splitHashSegments(val);parsed.hashParams=splitHashParams(val);break;case'path':if(val.charAt(0)!='/')val='/'+val;parsed.path=val;parsed.file=(val.match(/\/([^\/?#]+)$/i)||[,''])[1];parsed.segments=val.replace(/^\//,'').split('/');break;default:throwParserError('you can\'t update this property directly');break;}
updateSource();};var updateParsedParams=function(key,val)
{parsed.params[key]=val;parsed.query=combineQuery(parsed.params,true);updateSource();};var updateParsedSegments=function(key,val)
{parsed.segments[key]=val;parsed.path='/'+combinePath(parsed.segments);parsed.file=(parsed.path.match(/\/([^\/?#]+)$/i)||[,''])[1];updateSource();};var updateHashParams=function(key,val)
{parsed.hashParams[key]=val;parsed.hash=combineQuery(parsed.hashParams,true);updateSource();};var updateHashSegments=function(key,val)
{var slash=(parsed.hash.charAt(0)=='/')?'/':'';parsed.hashSegments[key]=val;parsed.hash=slash+combinePath(parsed.hashSegments);updateSource();};var action=function(gettObj,sett,args)
{if(isGetter(args))
{var key=args[0];return(gettObj===undefined||gettObj[key]===undefined||gettObj[key]==="")?null:gettObj[key];}
else if(isSetter(args))
{if(isObj(args[0]))
{for(var key in args[0])sett(key,args[0][key]);if(args[1]!==false)updateElement();}
else
{sett(args[0],args[1]);if(args[2]!==false)updateElement();}
return this;}};var init=function()
{if(isObj(source)&&source.size())
{urlAttr=undefined;var tagName=getTagName(source);if(tagName!==undefined)urlAttr=tag2attr[tagName];if(tagName!==undefined&&urlAttr!==undefined)
{sourceType='elm';ref=source;var url=source.attr(urlAttr);}
else if(tagName!==undefined&&urlAttr===undefined)
{throwParserError('no valid URL on object');return;}
else
{sourceType='doc';var url=loc.href;$(window).bind('hashchange',function(hash){updateParsedAttrs('hash',stripH(loc.hash));});}}
else if(!isObj(source))
{sourceType='str';var url=source;}
else
{throwParserError('no valid item');return;}
parsed=parseUrl(url);}();return{attr:function(){return action(parsed,updateParsedAttrs,arguments)},param:function(){return action(parsed.params,updateParsedParams,arguments)},segment:function(){return action(parsed.segments,updateParsedSegments,arguments)},hashParam:function(){return action(parsed.hashParams,updateHashParams,arguments)},hashSegment:function(){return action(parsed.hashSegments,updateHashSegments,arguments)},is:function(test)
{if(test==='internal'||test===':internal')
{return parsed.host&&parsed.host===getHost(loc.hostname);}
else if(test==='external'||test===':external')
{return parsed.host&&parsed.host!==getHost(loc.hostname);}},toString:function(){return parsed.source;}};};})(jQuery);
