(function($) { // Copyright (c) 2011 John Resig, http://jquery.com/ // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //define vars for interal use var $window = $( window ), $html = $( 'html' ), $head = $( 'head' ), //url path helpers for use in relative url management path = { // This scary looking regular expression parses an absolute URL or its relative // variants (protocol, site, document, query, and hash), into the various // components (protocol, host, path, query, fragment, etc that make up the // URL as well as some other commonly used sub-parts. When used with RegExp.exec() // or String.match, it parses the URL into a results array that looks like this: // // [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content // [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread // [2]: http://jblas:password@mycompany.com:8080/mail/inbox // [3]: http://jblas:password@mycompany.com:8080 // [4]: http: // [5]: // // [6]: jblas:password@mycompany.com:8080 // [7]: jblas:password // [8]: jblas // [9]: password // [10]: mycompany.com:8080 // [11]: mycompany.com // [12]: 8080 // [13]: /mail/inbox // [14]: /mail/ // [15]: inbox // [16]: ?msg=1234&type=unread // [17]: #msg-content // urlParseRE: /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/, //Parse a URL into a structure that allows easy access to //all of the URL components by name. parseUrl: function( url ) { // If we're passed an object, we'll assume that it is // a parsed url object and just return it back to the caller. if ( $.type( url ) === "object" ) { return url; } var matches = path.urlParseRE.exec( url || "" ) || []; // Create an object that allows the caller to access the sub-matches // by name. Note that IE returns an empty string instead of undefined, // like all other browsers do, so we normalize everything so its consistent // no matter what browser we're running on. return { href: matches[ 0 ] || "", hrefNoHash: matches[ 1 ] || "", hrefNoSearch: matches[ 2 ] || "", domain: matches[ 3 ] || "", protocol: matches[ 4 ] || "", doubleSlash: matches[ 5 ] || "", authority: matches[ 6 ] || "", username: matches[ 8 ] || "", password: matches[ 9 ] || "", host: matches[ 10 ] || "", hostname: matches[ 11 ] || "", port: matches[ 12 ] || "", pathname: matches[ 13 ] || "", directory: matches[ 14 ] || "", filename: matches[ 15 ] || "", search: matches[ 16 ] || "", hash: matches[ 17 ] || "" }; }, //Turn relPath into an asbolute path. absPath is //an optional absolute path which describes what //relPath is relative to. makePathAbsolute: function( relPath, absPath ) { if ( relPath && relPath.charAt( 0 ) === "/" ) { return relPath; } relPath = relPath || ""; absPath = absPath ? absPath.replace( /^\/|(\/[^\/]*|[^\/]+)$/g, "" ) : ""; var absStack = absPath ? absPath.split( "/" ) : [], relStack = relPath.split( "/" ); for ( var i = 0; i < relStack.length; i++ ) { var d = relStack[ i ]; switch ( d ) { case ".": break; case "..": if ( absStack.length ) { absStack.pop(); } break; default: absStack.push( d ); break; } } return "/" + absStack.join( "/" ); }, //Returns true if both urls have the same domain. isSameDomain: function( absUrl1, absUrl2 ) { return path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain; }, //Returns true for any relative variant. isRelativeUrl: function( url ) { // All relative Url variants have one thing in common, no protocol. return path.parseUrl( url ).protocol === ""; }, //Returns true for an absolute url. isAbsoluteUrl: function( url ) { return path.parseUrl( url ).protocol !== ""; }, //Turn the specified realtive URL into an absolute one. This function //can handle all relative variants (protocol, site, document, query, fragment). makeUrlAbsolute: function( relUrl, absUrl ) { if ( !path.isRelativeUrl( relUrl ) ) { return relUrl; } var relObj = path.parseUrl( relUrl ), absObj = path.parseUrl( absUrl ), protocol = relObj.protocol || absObj.protocol, doubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash ), authority = relObj.authority || absObj.authority, hasPath = relObj.pathname !== "", pathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ), search = relObj.search || ( !hasPath && absObj.search ) || "", hash = relObj.hash; return protocol + doubleSlash + authority + pathname + search + hash; }, //Add search (aka query) params to the specified url. // 2013-12-06 ischommer: Customized to merge with existing keys addSearchParams: function( url, params ) { var u = path.parseUrl( url ), params = ( typeof params === "string" ) ? path.convertSearchToArray( params ) : params, newParams = $.extend( path.convertSearchToArray( u.search ), params ); return u.hrefNoSearch + '?' + $.param( newParams ) + ( u.hash || "" ); }, // 2013-12-06 ischommer: Added to allow merge with existing keys getSearchParams: function(url) { var u = path.parseUrl( url ); return path.convertSearchToArray( u.search ); }, // Converts query strings (foo=bar&baz=bla) to a hash. // TODO Handle repeating elements (e.g. arr[]=one&arr[]=two) // 2013-12-06 ischommer: Added to allow merge with existing keys convertSearchToArray: function(search) { var params = {}, search = search.replace( /^\?/, '' ), parts = search ? search.split( '&' ) : [], i, tmp; for(i=0; i < parts.length; i++) { tmp = parts[i].split( '=' ); params[tmp[0]] = tmp[1]; } return params; }, convertUrlToDataUrl: function( absUrl ) { var u = path.parseUrl( absUrl ); if ( path.isEmbeddedPage( u ) ) { // For embedded pages, remove the dialog hash key as in getFilePath(), // otherwise the Data Url won't match the id of the embedded Page. return u.hash.split( dialogHashKey )[0].replace( /^#/, "" ); } else if ( path.isSameDomain( u, document ) ) { return u.hrefNoHash.replace( document.domain, "" ); } return absUrl; }, //get path from current hash, or from a file path get: function( newPath ) { if( newPath === undefined ) { newPath = location.hash; } return path.stripHash( newPath ).replace( /[^\/]*\.[^\/*]+$/, '' ); }, //return the substring of a filepath before the sub-page key, for making a server request getFilePath: function( path ) { var splitkey = '&' + $.mobile.subPageUrlKey; return path && path.split( splitkey )[0].split( dialogHashKey )[0]; }, //set location hash to path set: function( path ) { location.hash = path; }, //test if a given url (string) is a path //NOTE might be exceptionally naive isPath: function( url ) { return ( /\// ).test( url ); }, //return a url path with the window's location protocol/hostname/pathname removed clean: function( url ) { return url.replace( document.domain, "" ); }, //just return the url without an initial # stripHash: function( url ) { return url.replace( /^#/, "" ); }, //remove the preceding hash, any query params, and dialog notations cleanHash: function( hash ) { return path.stripHash( hash.replace( /\?.*$/, "" ).replace( dialogHashKey, "" ) ); }, //check whether a url is referencing the same domain, or an external domain or different protocol //could be mailto, etc isExternal: function( url ) { var u = path.parseUrl( url ); return u.protocol && u.domain !== document.domain ? true : false; }, hasProtocol: function( url ) { return ( /^(:?\w+:)/ ).test( url ); } }; $.path = path; }(jQuery));