mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
256 lines
9.6 KiB
JavaScript
256 lines
9.6 KiB
JavaScript
import $ from 'jQuery';
|
|
|
|
// 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 parts, i, tmp, params = {};
|
|
search = search.replace( /^\?/, '' );
|
|
parts = search ? search.split( '&' ) : [];
|
|
for(i=0; i < parts.length; i++) {
|
|
tmp = parts[i].split( '=' );
|
|
params[decodeURIComponent(tmp[0])] = decodeURIComponent(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;
|