/* * JQuery URL Parser plugin, v2.2.1 * Developed and maintanined by Mark Perkins, mark@allmarkedup.com * Source repository: https://github.com/allmarkedup/jQuery-URL-Parser * Licensed under an MIT-style license. See https://github.com/allmarkedup/jQuery-URL-Parser/blob/master/LICENSE for details. */ ;(function(factory) { if (typeof define === 'function' && define.amd) { // AMD available; use anonymous module if ( typeof jQuery !== 'undefined' ) { define(['jquery'], factory); } else { define([], factory); } } else { // No AMD available; mutate global vars if ( typeof jQuery !== 'undefined' ) { factory(jQuery); } else { factory(); } } })(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 }, toString = Object.prototype.toString, isint = /^[0-9]+$/; 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'] = parseString(uri.attr['query']); uri.param['fragment'] = parseString(uri.attr['fragment']); // 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.protocol+'://'+uri.attr.host : uri.attr.host) + (uri.attr.port ? ':'+uri.attr.port : '') : ''; return uri; }; function getAttrName( elm ) { var tn = elm.tagName; if ( typeof tn !== 'undefined' ) return tag2attr[tn.toLowerCase()]; return tn; } function promote(parent, key) { if (parent[key].length == 0) return parent[key] = {}; var t = {}; for (var i in parent[key]) t[i] = parent[key][i]; parent[key] = t; return t; } function parse(parts, parent, key, val) { var part = parts.shift(); if (!part) { if (isArray(parent[key])) { parent[key].push(val); } else if ('object' == typeof parent[key]) { parent[key] = val; } else if ('undefined' == typeof parent[key]) { parent[key] = val; } else { parent[key] = [parent[key], val]; } } else { var obj = parent[key] = parent[key] || []; if (']' == part) { if (isArray(obj)) { if ('' != val) obj.push(val); } else if ('object' == typeof obj) { obj[keys(obj).length] = val; } else { obj = parent[key] = [parent[key], val]; } } else if (~part.indexOf(']')) { part = part.substr(0, part.length - 1); if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); parse(parts, obj, part, val); // key } else { if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); parse(parts, obj, part, val); } } } function merge(parent, key, val) { if (~key.indexOf(']')) { var parts = key.split('['), len = parts.length, last = len - 1; parse(parts, parent, 'base', val); } else { if (!isint.test(key) && isArray(parent.base)) { var t = {}; for (var k in parent.base) t[k] = parent.base[k]; parent.base = t; } set(parent.base, key, val); } return parent; } function parseString(str) { return reduce(String(str).split(/&|;/), function(ret, pair) { try { pair = decodeURIComponent(pair.replace(/\+/g, ' ')); } catch(e) { // ignore } var eql = pair.indexOf('='), brace = lastBraceInKey(pair), key = pair.substr(0, brace || eql), val = pair.substr(brace || eql, pair.length), val = val.substr(val.indexOf('=') + 1, val.length); if ('' == key) key = pair, val = ''; return merge(ret, key, val); }, { base: {} }).base; } function set(obj, key, val) { var v = obj[key]; if (undefined === v) { obj[key] = val; } else if (isArray(v)) { v.push(val); } else { obj[key] = [v, val]; } } function lastBraceInKey(str) { var len = str.length, brace, c; for (var i = 0; i < len; ++i) { c = str[i]; if (']' == c) brace = false; if ('[' == c) brace = true; if ('=' == c && !brace) return i; } } function reduce(obj, accumulator){ var i = 0, l = obj.length >> 0, curr = arguments[2]; while (i < l) { if (i in obj) curr = accumulator.call(undefined, curr, obj[i], i, obj); ++i; } return curr; } function isArray(vArg) { return Object.prototype.toString.call(vArg) === "[object Array]"; } function keys(obj) { var keys = []; for ( prop in obj ) { if ( obj.hasOwnProperty(prop) ) keys.push(prop); } return keys; } function purl( 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 typeof attr !== 'undefined' ? this.data.attr[attr] : this.data.attr; }, // return query string parameters param : function( param ) { return typeof param !== 'undefined' ? this.data.param.query[param] : this.data.param.query; }, // return fragment parameters fparam : function( param ) { return typeof param !== 'undefined' ? this.data.param.fragment[param] : this.data.param.fragment; }, // return path segments segment : function( seg ) { if ( typeof 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 return this.data.seg.path[seg]; } }, // return fragment segments fsegment : function( seg ) { if ( typeof 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]; } } }; }; if ( typeof $ !== 'undefined' ) { $.fn.url = function( strictMode ) { var url = ''; if ( this.length ) { url = $(this).attr( getAttrName(this[0]) ) || ''; } return purl( url, strictMode ); }; $.url = purl; } else { window.purl = purl; } });