mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-09 23:34:42 +00:00
parent
59bfe8e5a9
commit
58ef32308f
4 changed files with 188 additions and 208 deletions
|
|
@ -52,7 +52,7 @@ function isSameDomain(requestUrl, locationUrl) {
|
||||||
relativeProtocol: match[2] === undefined || match[2] === ''
|
relativeProtocol: match[2] === undefined || match[2] === ''
|
||||||
};
|
};
|
||||||
|
|
||||||
match = URL_MATCH.exec(locationUrl);
|
match = SERVER_MATCH.exec(locationUrl);
|
||||||
var domain2 = {
|
var domain2 = {
|
||||||
protocol: match[1],
|
protocol: match[1],
|
||||||
host: match[3],
|
host: match[3],
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
|
||||||
|
|
||||||
function completeRequest(callback, status, response, headersString) {
|
function completeRequest(callback, status, response, headersString) {
|
||||||
// URL_MATCH is defined in src/service/location.js
|
// URL_MATCH is defined in src/service/location.js
|
||||||
var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];
|
var protocol = (url.match(SERVER_MATCH) || ['', locationProtocol])[1];
|
||||||
|
|
||||||
// fix status code for file protocol (it's always 0)
|
// fix status code for file protocol (it's always 0)
|
||||||
status = (protocol == 'file') ? (response ? 200 : 404) : status;
|
status = (protocol == 'file') ? (response ? 200 : 404) : status;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var URL_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?(\{?[\w\.-]*\}?)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
|
var SERVER_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?(\{?[\w\.-]*\}?)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
|
||||||
PATH_MATCH = /^([^\?#]*)?(\?([^#]*))?(#(.*))?$/,
|
PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
|
||||||
HASH_MATCH = PATH_MATCH,
|
|
||||||
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
|
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -23,30 +22,23 @@ function encodePath(path) {
|
||||||
return segments.join('/');
|
return segments.join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripHash(url) {
|
function matchUrl(url, obj) {
|
||||||
return url.split('#')[0];
|
var match = SERVER_MATCH.exec(url);
|
||||||
|
|
||||||
|
obj.$$protocol = match[1];
|
||||||
|
obj.$$host = match[3];
|
||||||
|
obj.$$port = int(match[5]) || DEFAULT_PORTS[match[1]] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function matchAppUrl(url, obj) {
|
||||||
|
var match = PATH_MATCH.exec(url);
|
||||||
|
|
||||||
function matchUrl(url, obj) {
|
obj.$$path = decodeURIComponent(match[1]);
|
||||||
var match = URL_MATCH.exec(url);
|
obj.$$search = parseKeyValue(match[3]);
|
||||||
|
obj.$$hash = decodeURIComponent(match[5] || '');
|
||||||
|
|
||||||
match = {
|
// make sure path starts with '/';
|
||||||
protocol: match[1],
|
if (obj.$$path && obj.$$path.charAt(0) != '/') obj.$$path = '/' + obj.$$path;
|
||||||
host: match[3],
|
|
||||||
port: int(match[5]) || DEFAULT_PORTS[match[1]] || null,
|
|
||||||
path: match[6] || '/',
|
|
||||||
search: match[8],
|
|
||||||
hash: match[10]
|
|
||||||
};
|
|
||||||
|
|
||||||
if (obj) {
|
|
||||||
obj.$$protocol = match.protocol;
|
|
||||||
obj.$$host = match.host;
|
|
||||||
obj.$$port = match.port;
|
|
||||||
}
|
|
||||||
|
|
||||||
return match;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -54,77 +46,62 @@ function composeProtocolHostPort(protocol, host, port) {
|
||||||
return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);
|
return protocol + '://' + host + (port == DEFAULT_PORTS[protocol] ? '' : ':' + port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
function pathPrefixFromBase(basePath) {
|
*
|
||||||
return basePath.substr(0, basePath.lastIndexOf('/'));
|
* @param {string} begin
|
||||||
|
* @param {string} whole
|
||||||
|
* @param {string} otherwise
|
||||||
|
* @returns {string} returns text from whole after begin or otherwise if it does not begin with expected string.
|
||||||
|
*/
|
||||||
|
function beginsWith(begin, whole, otherwise) {
|
||||||
|
return whole.indexOf(begin) == 0 ? whole.substr(begin.length) : otherwise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function convertToHtml5Url(url, basePath, hashPrefix) {
|
function stripHash(url) {
|
||||||
var match = matchUrl(url);
|
var index = url.indexOf('#');
|
||||||
|
return index == -1 ? url : url.substr(0, index);
|
||||||
// already html5 url
|
|
||||||
if (decodeURIComponent(match.path) != basePath || isUndefined(match.hash) ||
|
|
||||||
match.hash.indexOf(hashPrefix) !== 0) {
|
|
||||||
return url;
|
|
||||||
// convert hashbang url -> html5 url
|
|
||||||
} else {
|
|
||||||
return composeProtocolHostPort(match.protocol, match.host, match.port) +
|
|
||||||
pathPrefixFromBase(basePath) + match.hash.substr(hashPrefix.length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function convertToHashbangUrl(url, basePath, hashPrefix) {
|
function stripFile(url) {
|
||||||
var match = matchUrl(url);
|
return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
// already hashbang url
|
/* return the server only */
|
||||||
if (decodeURIComponent(match.path) == basePath && !isUndefined(match.hash) &&
|
function serverBase(url) {
|
||||||
match.hash.indexOf(hashPrefix) === 0) {
|
return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
|
||||||
return url;
|
|
||||||
// convert html5 url -> hashbang url
|
|
||||||
} else {
|
|
||||||
var search = match.search && '?' + match.search || '',
|
|
||||||
hash = match.hash && '#' + match.hash || '',
|
|
||||||
pathPrefix = pathPrefixFromBase(basePath),
|
|
||||||
path = match.path.substr(pathPrefix.length);
|
|
||||||
|
|
||||||
if (match.path.indexOf(pathPrefix) !== 0) {
|
|
||||||
throw Error('Invalid url "' + url + '", missing path prefix "' + pathPrefix + '" !');
|
|
||||||
}
|
|
||||||
|
|
||||||
return composeProtocolHostPort(match.protocol, match.host, match.port) + basePath +
|
|
||||||
'#' + hashPrefix + path + search + hash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LocationUrl represents an url
|
* LocationHtml5Url represents an url
|
||||||
* This object is exposed as $location service when HTML5 mode is enabled and supported
|
* This object is exposed as $location service when HTML5 mode is enabled and supported
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {string} url HTML5 url
|
* @param {string} appBase application base URL
|
||||||
* @param {string} pathPrefix
|
* @param {string} basePrefix url path prefix
|
||||||
*/
|
*/
|
||||||
function LocationUrl(url, pathPrefix, appBaseUrl) {
|
function LocationHtml5Url(appBase, basePrefix) {
|
||||||
pathPrefix = pathPrefix || '';
|
basePrefix = basePrefix || '';
|
||||||
|
var appBaseNoFile = stripFile(appBase);
|
||||||
/**
|
/**
|
||||||
* Parse given html5 (regular) url string into properties
|
* Parse given html5 (regular) url string into properties
|
||||||
* @param {string} newAbsoluteUrl HTML5 url
|
* @param {string} newAbsoluteUrl HTML5 url
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.$$parse = function(newAbsoluteUrl) {
|
this.$$parse = function(url) {
|
||||||
var match = matchUrl(newAbsoluteUrl, this);
|
var parsed = {}
|
||||||
|
matchUrl(url, parsed);
|
||||||
if (match.path.indexOf(pathPrefix) !== 0) {
|
var pathUrl = beginsWith(appBaseNoFile, url);
|
||||||
throw Error('Invalid url "' + newAbsoluteUrl + '", missing path prefix "' + pathPrefix + '" !');
|
if (!isString(pathUrl)) {
|
||||||
|
throw Error('Invalid url "' + url + '", missing path prefix "' + appBaseNoFile + '".');
|
||||||
|
}
|
||||||
|
matchAppUrl(pathUrl, parsed);
|
||||||
|
extend(this, parsed);
|
||||||
|
if (!this.$$path) {
|
||||||
|
this.$$path = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length));
|
|
||||||
this.$$search = parseKeyValue(match.search);
|
|
||||||
this.$$hash = match.hash && decodeURIComponent(match.hash) || '';
|
|
||||||
|
|
||||||
this.$$compose();
|
this.$$compose();
|
||||||
};
|
};
|
||||||
|
|
@ -138,19 +115,24 @@ function LocationUrl(url, pathPrefix, appBaseUrl) {
|
||||||
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
|
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
|
||||||
|
|
||||||
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
|
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
|
||||||
this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +
|
this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
|
||||||
pathPrefix + this.$$url;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.$$rewrite = function(url) {
|
||||||
|
var appUrl;
|
||||||
|
|
||||||
this.$$rewriteAppUrl = function(absoluteLinkUrl) {
|
if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
|
||||||
if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
|
if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
|
||||||
return absoluteLinkUrl;
|
return appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
|
||||||
|
} else {
|
||||||
|
return appBase;
|
||||||
|
}
|
||||||
|
} else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
|
||||||
|
return appBaseNoFile + appUrl;
|
||||||
|
} else if (appBaseNoFile == url + '/') {
|
||||||
|
return appBaseNoFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.$$parse(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -159,11 +141,11 @@ function LocationUrl(url, pathPrefix, appBaseUrl) {
|
||||||
* This object is exposed as $location service when html5 history api is disabled or not supported
|
* This object is exposed as $location service when html5 history api is disabled or not supported
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {string} url Legacy url
|
* @param {string} appBase application base URL
|
||||||
* @param {string} hashPrefix Prefix for hash part (containing path and search)
|
* @param {string} hashPrefix hashbang prefix
|
||||||
*/
|
*/
|
||||||
function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
|
function LocationHashbangUrl(appBase, hashPrefix) {
|
||||||
var basePath;
|
var appBaseNoFile = stripFile(appBase);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse given hashbang url into properties
|
* Parse given hashbang url into properties
|
||||||
|
|
@ -171,24 +153,16 @@ function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.$$parse = function(url) {
|
this.$$parse = function(url) {
|
||||||
var match = matchUrl(url, this);
|
matchUrl(url, this);
|
||||||
|
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
|
||||||
|
if (!isString(withoutBaseUrl)) {
|
||||||
if (match.hash && match.hash.indexOf(hashPrefix) !== 0) {
|
throw new Error('Invalid url "' + url + '", does not start with "' + appBase + '".');
|
||||||
throw Error('Invalid url "' + url + '", missing hash prefix "' + hashPrefix + '" !');
|
|
||||||
}
|
}
|
||||||
|
var withoutHashUrl = withoutBaseUrl.charAt(0) == '#' ? beginsWith(hashPrefix, withoutBaseUrl) : withoutBaseUrl;
|
||||||
basePath = match.path + (match.search ? '?' + match.search : '');
|
if (!isString(withoutHashUrl)) {
|
||||||
match = HASH_MATCH.exec((match.hash || '').substr(hashPrefix.length));
|
throw new Error('Invalid url "' + url + '", missing hash prefix "' + hashPrefix + '".');
|
||||||
if (match[1]) {
|
|
||||||
this.$$path = (match[1].charAt(0) == '/' ? '' : '/') + decodeURIComponent(match[1]);
|
|
||||||
} else {
|
|
||||||
this.$$path = '';
|
|
||||||
}
|
}
|
||||||
|
matchAppUrl(withoutHashUrl, this);
|
||||||
this.$$search = parseKeyValue(match[3]);
|
|
||||||
this.$$hash = match[5] && decodeURIComponent(match[5]) || '';
|
|
||||||
|
|
||||||
this.$$compose();
|
this.$$compose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -201,22 +175,48 @@ function LocationHashbangUrl(url, hashPrefix, appBaseUrl) {
|
||||||
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
|
hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
|
||||||
|
|
||||||
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
|
this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
|
||||||
this.$$absUrl = composeProtocolHostPort(this.$$protocol, this.$$host, this.$$port) +
|
this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
|
||||||
basePath + (this.$$url ? '#' + hashPrefix + this.$$url : '');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$$rewriteAppUrl = function(absoluteLinkUrl) {
|
this.$$rewrite = function(url) {
|
||||||
if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
|
if(stripHash(appBase) == stripHash(url)) {
|
||||||
return absoluteLinkUrl;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.$$parse(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LocationUrl.prototype = {
|
/**
|
||||||
|
* LocationHashbangUrl represents url
|
||||||
|
* This object is exposed as $location service when html5 history api is enabled but the browser
|
||||||
|
* does not support it.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {string} appBase application base URL
|
||||||
|
* @param {string} hashPrefix hashbang prefix
|
||||||
|
*/
|
||||||
|
function LocationHashbangInHtml5Url(appBase, hashPrefix) {
|
||||||
|
LocationHashbangUrl.apply(this, arguments);
|
||||||
|
|
||||||
|
var appBaseNoFile = stripFile(appBase);
|
||||||
|
|
||||||
|
this.$$rewrite = function(url) {
|
||||||
|
var appUrl;
|
||||||
|
|
||||||
|
if ( appBase == stripHash(url) ) {
|
||||||
|
return url;
|
||||||
|
} else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
|
||||||
|
return appBase + hashPrefix + appUrl;
|
||||||
|
} else if ( appBaseNoFile === url + '/') {
|
||||||
|
return appBaseNoFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LocationHashbangInHtml5Url.prototype =
|
||||||
|
LocationHashbangUrl.prototype =
|
||||||
|
LocationHtml5Url.prototype = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has any change been replacing ?
|
* Has any change been replacing ?
|
||||||
|
|
@ -398,21 +398,6 @@ LocationUrl.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
LocationHashbangUrl.prototype = inherit(LocationUrl.prototype);
|
|
||||||
|
|
||||||
function LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {
|
|
||||||
LocationHashbangUrl.apply(this, arguments);
|
|
||||||
|
|
||||||
|
|
||||||
this.$$rewriteAppUrl = function(absoluteLinkUrl) {
|
|
||||||
if (absoluteLinkUrl.indexOf(appBaseUrl) == 0) {
|
|
||||||
return appBaseUrl + baseExtra + '#' + hashPrefix + absoluteLinkUrl.substr(appBaseUrl.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LocationHashbangInHtml5Url.prototype = inherit(LocationHashbangUrl.prototype);
|
|
||||||
|
|
||||||
function locationGetter(property) {
|
function locationGetter(property) {
|
||||||
return function() {
|
return function() {
|
||||||
return this[property];
|
return this[property];
|
||||||
|
|
@ -509,37 +494,20 @@ function $LocationProvider(){
|
||||||
this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
|
this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
|
||||||
function( $rootScope, $browser, $sniffer, $rootElement) {
|
function( $rootScope, $browser, $sniffer, $rootElement) {
|
||||||
var $location,
|
var $location,
|
||||||
basePath,
|
LocationMode,
|
||||||
pathPrefix,
|
baseHref = $browser.baseHref(),
|
||||||
initUrl = $browser.url(),
|
initialUrl = $browser.url(),
|
||||||
initUrlParts = matchUrl(initUrl),
|
appBase;
|
||||||
appBaseUrl;
|
|
||||||
|
|
||||||
if (html5Mode) {
|
if (html5Mode) {
|
||||||
basePath = $browser.baseHref() || '/';
|
appBase = baseHref ? serverBase(initialUrl) + baseHref : initialUrl;
|
||||||
pathPrefix = pathPrefixFromBase(basePath);
|
LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
|
||||||
appBaseUrl =
|
|
||||||
composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +
|
|
||||||
pathPrefix + '/';
|
|
||||||
|
|
||||||
if ($sniffer.history) {
|
|
||||||
$location = new LocationUrl(
|
|
||||||
convertToHtml5Url(initUrl, basePath, hashPrefix),
|
|
||||||
pathPrefix, appBaseUrl);
|
|
||||||
} else {
|
|
||||||
$location = new LocationHashbangInHtml5Url(
|
|
||||||
convertToHashbangUrl(initUrl, basePath, hashPrefix),
|
|
||||||
hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
appBaseUrl =
|
appBase = stripHash(initialUrl);
|
||||||
composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) +
|
LocationMode = LocationHashbangUrl;
|
||||||
(initUrlParts.path || '') +
|
|
||||||
(initUrlParts.search ? ('?' + initUrlParts.search) : '') +
|
|
||||||
'#' + hashPrefix + '/';
|
|
||||||
|
|
||||||
$location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl);
|
|
||||||
}
|
}
|
||||||
|
$location = new LocationMode(appBase, '#' + hashPrefix);
|
||||||
|
$location.$$parse($location.$$rewrite(initialUrl));
|
||||||
|
|
||||||
$rootElement.bind('click', function(event) {
|
$rootElement.bind('click', function(event) {
|
||||||
// TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
|
// TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
|
||||||
|
|
@ -556,7 +524,7 @@ function $LocationProvider(){
|
||||||
}
|
}
|
||||||
|
|
||||||
var absHref = elm.prop('href'),
|
var absHref = elm.prop('href'),
|
||||||
rewrittenUrl = $location.$$rewriteAppUrl(absHref);
|
rewrittenUrl = $location.$$rewrite(absHref);
|
||||||
|
|
||||||
if (absHref && !elm.attr('target') && rewrittenUrl) {
|
if (absHref && !elm.attr('target') && rewrittenUrl) {
|
||||||
// update location manually
|
// update location manually
|
||||||
|
|
@ -570,7 +538,7 @@ function $LocationProvider(){
|
||||||
|
|
||||||
|
|
||||||
// rewrite hashbang url <> html5 url
|
// rewrite hashbang url <> html5 url
|
||||||
if ($location.absUrl() != initUrl) {
|
if ($location.absUrl() != initialUrl) {
|
||||||
$browser.url($location.absUrl(), true);
|
$browser.url($location.absUrl(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
describe('NewUrl', function() {
|
describe('NewUrl', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
url = new LocationUrl('http://www.domain.com:9877/path/b?search=a&b=c&d#hash');
|
url = new LocationHtml5Url('http://www.domain.com:9877/');
|
||||||
|
url.$$parse('http://www.domain.com:9877/path/b?search=a&b=c&d#hash');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -132,16 +133,18 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should parse new url', function() {
|
it('should parse new url', function() {
|
||||||
url = new LocationUrl('http://host.com/base');
|
url = new LocationHtml5Url('http://host.com/');
|
||||||
|
url.$$parse('http://host.com/base');
|
||||||
expect(url.path()).toBe('/base');
|
expect(url.path()).toBe('/base');
|
||||||
|
|
||||||
url = new LocationUrl('http://host.com/base#');
|
url = new LocationHtml5Url('http://host.com/');
|
||||||
|
url.$$parse('http://host.com/base#');
|
||||||
expect(url.path()).toBe('/base');
|
expect(url.path()).toBe('/base');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should prefix path with forward-slash', function() {
|
it('should prefix path with forward-slash', function() {
|
||||||
url = new LocationUrl('http://server/a');
|
url = new LocationHtml5Url('http://server/');
|
||||||
url.path('b');
|
url.path('b');
|
||||||
|
|
||||||
expect(url.path()).toBe('/b');
|
expect(url.path()).toBe('/b');
|
||||||
|
|
@ -150,7 +153,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should set path to forward-slash when empty', function() {
|
it('should set path to forward-slash when empty', function() {
|
||||||
url = new LocationUrl('http://server');
|
url = new LocationHtml5Url('http://server/');
|
||||||
|
url.$$parse('http://server/')
|
||||||
expect(url.path()).toBe('/');
|
expect(url.path()).toBe('/');
|
||||||
expect(url.absUrl()).toBe('http://server/');
|
expect(url.absUrl()).toBe('http://server/');
|
||||||
});
|
});
|
||||||
|
|
@ -175,7 +179,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should prepend path with basePath', function() {
|
it('should prepend path with basePath', function() {
|
||||||
url = new LocationUrl('http://server/base/abc?a', '/base');
|
url = new LocationHtml5Url('http://server/base/');
|
||||||
|
url.$$parse('http://server/base/abc?a');
|
||||||
expect(url.path()).toBe('/abc');
|
expect(url.path()).toBe('/abc');
|
||||||
expect(url.search()).toEqual({a: true});
|
expect(url.search()).toEqual({a: true});
|
||||||
|
|
||||||
|
|
@ -184,12 +189,21 @@ describe('$location', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should throw error when invalid url given', function() {
|
it('should throw error when invalid server url given', function() {
|
||||||
url = new LocationUrl('http://server.org/base/abc', '/base');
|
url = new LocationHtml5Url('http://server.org/base/abc', '/base');
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
url.$$parse('http://other.server.org/path#/path');
|
||||||
|
}).toThrow('Invalid url "http://other.server.org/path#/path", missing path prefix "http://server.org/base/".');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should throw error when invalid base url given', function() {
|
||||||
|
url = new LocationHtml5Url('http://server.org/base/abc', '/base');
|
||||||
|
|
||||||
expect(function() {
|
expect(function() {
|
||||||
url.$$parse('http://server.org/path#/path');
|
url.$$parse('http://server.org/path#/path');
|
||||||
}).toThrow('Invalid url "http://server.org/path#/path", missing path prefix "/base" !');
|
}).toThrow('Invalid url "http://server.org/path#/path", missing path prefix "http://server.org/base/".');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -217,7 +231,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should decode special characters', function() {
|
it('should decode special characters', function() {
|
||||||
url = new LocationUrl('http://host.com/a%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23');
|
url = new LocationHtml5Url('http://host.com/');
|
||||||
|
url.$$parse('http://host.com/a%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23');
|
||||||
expect(url.path()).toBe('/a <>#');
|
expect(url.path()).toBe('/a <>#');
|
||||||
expect(url.search()).toEqual({'i j': '<>#'});
|
expect(url.search()).toEqual({'i j': '<>#'});
|
||||||
expect(url.hash()).toBe('x <>#');
|
expect(url.hash()).toBe('x <>#');
|
||||||
|
|
@ -229,7 +244,8 @@ describe('$location', function() {
|
||||||
describe('HashbangUrl', function() {
|
describe('HashbangUrl', function() {
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
url = new LocationHashbangUrl('http://www.server.org:1234/base#!/path?a=b&c#hash', '!');
|
url = new LocationHashbangUrl('http://www.server.org:1234/base', '#!');
|
||||||
|
url.$$parse('http://www.server.org:1234/base#!/path?a=b&c#hash');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -254,7 +270,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should preserve query params in base', function() {
|
it('should preserve query params in base', function() {
|
||||||
url = new LocationHashbangUrl('http://www.server.org:1234/base?base=param#/path?a=b&c#hash', '');
|
url = new LocationHashbangUrl('http://www.server.org:1234/base?base=param', '#');
|
||||||
|
url.$$parse('http://www.server.org:1234/base?base=param#/path?a=b&c#hash');
|
||||||
expect(url.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?a=b&c#hash');
|
expect(url.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?a=b&c#hash');
|
||||||
|
|
||||||
url.path('/new/path');
|
url.path('/new/path');
|
||||||
|
|
@ -265,7 +282,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should prefix path with forward-slash', function() {
|
it('should prefix path with forward-slash', function() {
|
||||||
url = new LocationHashbangUrl('http://host.com/base#path', '');
|
url = new LocationHashbangUrl('http://host.com/base', '#');
|
||||||
|
url.$$parse('http://host.com/base#path');
|
||||||
expect(url.path()).toBe('/path');
|
expect(url.path()).toBe('/path');
|
||||||
expect(url.absUrl()).toBe('http://host.com/base#/path');
|
expect(url.absUrl()).toBe('http://host.com/base#/path');
|
||||||
|
|
||||||
|
|
@ -276,7 +294,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should set path to forward-slash when empty', function() {
|
it('should set path to forward-slash when empty', function() {
|
||||||
url = new LocationHashbangUrl('http://server/base#!', '!');
|
url = new LocationHashbangUrl('http://server/base', '#!');
|
||||||
|
url.$$parse('http://server/base');
|
||||||
url.path('aaa');
|
url.path('aaa');
|
||||||
|
|
||||||
expect(url.path()).toBe('/aaa');
|
expect(url.path()).toBe('/aaa');
|
||||||
|
|
@ -294,10 +313,17 @@ describe('$location', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should throw error when invalid url given', function() {
|
it('should throw error when invalid server url given', function() {
|
||||||
expect(function() {
|
expect(function() {
|
||||||
url.$$parse('http://server.org/path#/path');
|
url.$$parse('http://server.org/path#/path');
|
||||||
}).toThrow('Invalid url "http://server.org/path#/path", missing hash prefix "!" !');
|
}).toThrow('Invalid url "http://server.org/path#/path", does not start with "http://www.server.org:1234/base".');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should throw error when invalid hashbang prefix given', function() {
|
||||||
|
expect(function() {
|
||||||
|
url.$$parse('http://www.server.org:1234/base#/path');
|
||||||
|
}).toThrow('Invalid url "http://www.server.org:1234/base#/path", missing hash prefix "#!".');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -325,7 +351,8 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should decode special characters', function() {
|
it('should decode special characters', function() {
|
||||||
url = new LocationHashbangUrl('http://host.com/a#/%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23', '');
|
url = new LocationHashbangUrl('http://host.com/a', '#');
|
||||||
|
url.$$parse('http://host.com/a#/%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23');
|
||||||
expect(url.path()).toBe('/ <>#');
|
expect(url.path()).toBe('/ <>#');
|
||||||
expect(url.search()).toEqual({'i j': '<>#'});
|
expect(url.search()).toEqual({'i j': '<>#'});
|
||||||
expect(url.hash()).toBe('x <>#');
|
expect(url.hash()).toBe('x <>#');
|
||||||
|
|
@ -333,13 +360,15 @@ describe('$location', function() {
|
||||||
|
|
||||||
|
|
||||||
it('should return decoded characters for search specified in URL', function() {
|
it('should return decoded characters for search specified in URL', function() {
|
||||||
var locationUrl = new LocationUrl('http://host.com/?q=1%2F2%203');
|
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||||
|
locationUrl.$$parse('http://host.com/?q=1%2F2%203');
|
||||||
expect(locationUrl.search()).toEqual({'q': '1/2 3'});
|
expect(locationUrl.search()).toEqual({'q': '1/2 3'});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should return decoded characters for search specified with setter', function() {
|
it('should return decoded characters for search specified with setter', function() {
|
||||||
var locationUrl = new LocationUrl('http://host.com/');
|
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||||
|
locationUrl.$$parse('http://host.com/')
|
||||||
locationUrl.search('q', '1/2 3');
|
locationUrl.search('q', '1/2 3');
|
||||||
expect(locationUrl.search()).toEqual({'q': '1/2 3'});
|
expect(locationUrl.search()).toEqual({'q': '1/2 3'});
|
||||||
});
|
});
|
||||||
|
|
@ -364,7 +393,7 @@ describe('$location', function() {
|
||||||
describe('wiring', function() {
|
describe('wiring', function() {
|
||||||
|
|
||||||
beforeEach(initService(false, '!', true));
|
beforeEach(initService(false, '!', true));
|
||||||
beforeEach(inject(initBrowser('http://new.com/a/b#!', '/a/b')));
|
beforeEach(inject(initBrowser('http://new.com/a/b#!', 'http://new.com/a/b')));
|
||||||
|
|
||||||
|
|
||||||
it('should update $location when browser url changes', inject(function($browser, $location) {
|
it('should update $location when browser url changes', inject(function($browser, $location) {
|
||||||
|
|
@ -381,7 +410,7 @@ describe('$location', function() {
|
||||||
it('should not $apply when browser url changed inside $apply', inject(
|
it('should not $apply when browser url changed inside $apply', inject(
|
||||||
function($rootScope, $browser, $location) {
|
function($rootScope, $browser, $location) {
|
||||||
var OLD_URL = $browser.url(),
|
var OLD_URL = $browser.url(),
|
||||||
NEW_URL = 'http://updated.com/url';
|
NEW_URL = 'http://new.com/a/b#!/new';
|
||||||
|
|
||||||
|
|
||||||
$rootScope.$apply(function() {
|
$rootScope.$apply(function() {
|
||||||
|
|
@ -397,7 +426,7 @@ describe('$location', function() {
|
||||||
it('should not $apply when browser url changed inside $digest', inject(
|
it('should not $apply when browser url changed inside $digest', inject(
|
||||||
function($rootScope, $browser, $location) {
|
function($rootScope, $browser, $location) {
|
||||||
var OLD_URL = $browser.url(),
|
var OLD_URL = $browser.url(),
|
||||||
NEW_URL = 'http://updated.com/url',
|
NEW_URL = 'http://new.com/a/b#!/new',
|
||||||
notRunYet = true;
|
notRunYet = true;
|
||||||
|
|
||||||
$rootScope.$watch(function() {
|
$rootScope.$watch(function() {
|
||||||
|
|
@ -613,72 +642,55 @@ describe('$location', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('URL_MATCH', function() {
|
describe('SERVER_MATCH', function() {
|
||||||
|
|
||||||
it('should parse basic url', function() {
|
it('should parse basic url', function() {
|
||||||
var match = URL_MATCH.exec('http://www.angularjs.org/path?search#hash?x=x');
|
var match = SERVER_MATCH.exec('http://www.angularjs.org/path?search#hash?x=x');
|
||||||
|
|
||||||
expect(match[1]).toBe('http');
|
expect(match[1]).toBe('http');
|
||||||
expect(match[3]).toBe('www.angularjs.org');
|
expect(match[3]).toBe('www.angularjs.org');
|
||||||
expect(match[6]).toBe('/path');
|
|
||||||
expect(match[8]).toBe('search');
|
|
||||||
expect(match[10]).toBe('hash?x=x');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should parse file://', function() {
|
it('should parse file://', function() {
|
||||||
var match = URL_MATCH.exec('file:///Users/Shared/misko/work/angular.js/scenario/widgets.html');
|
var match = SERVER_MATCH.exec('file:///Users/Shared/misko/work/angular.js/scenario/widgets.html');
|
||||||
|
|
||||||
expect(match[1]).toBe('file');
|
expect(match[1]).toBe('file');
|
||||||
expect(match[3]).toBe('');
|
expect(match[3]).toBe('');
|
||||||
expect(match[5]).toBeFalsy();
|
expect(match[5]).toBeFalsy();
|
||||||
expect(match[6]).toBe('/Users/Shared/misko/work/angular.js/scenario/widgets.html');
|
|
||||||
expect(match[8]).toBeFalsy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should parse url with "-" in host', function() {
|
it('should parse url with "-" in host', function() {
|
||||||
var match = URL_MATCH.exec('http://a-b1.c-d.09/path');
|
var match = SERVER_MATCH.exec('http://a-b1.c-d.09/path');
|
||||||
|
|
||||||
expect(match[1]).toBe('http');
|
expect(match[1]).toBe('http');
|
||||||
expect(match[3]).toBe('a-b1.c-d.09');
|
expect(match[3]).toBe('a-b1.c-d.09');
|
||||||
expect(match[5]).toBeFalsy();
|
expect(match[5]).toBeFalsy();
|
||||||
expect(match[6]).toBe('/path');
|
|
||||||
expect(match[8]).toBeFalsy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should parse host without "/" at the end', function() {
|
it('should parse host without "/" at the end', function() {
|
||||||
var match = URL_MATCH.exec('http://host.org');
|
var match = SERVER_MATCH.exec('http://host.org');
|
||||||
expect(match[3]).toBe('host.org');
|
expect(match[3]).toBe('host.org');
|
||||||
|
|
||||||
match = URL_MATCH.exec('http://host.org#');
|
match = SERVER_MATCH.exec('http://host.org#');
|
||||||
expect(match[3]).toBe('host.org');
|
expect(match[3]).toBe('host.org');
|
||||||
|
|
||||||
match = URL_MATCH.exec('http://host.org?');
|
match = SERVER_MATCH.exec('http://host.org?');
|
||||||
expect(match[3]).toBe('host.org');
|
expect(match[3]).toBe('host.org');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should match with just "/" path', function() {
|
|
||||||
var match = URL_MATCH.exec('http://server/#?book=moby');
|
|
||||||
|
|
||||||
expect(match[10]).toBe('?book=moby');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should parse chrome extension urls', function() {
|
it('should parse chrome extension urls', function() {
|
||||||
var match = URL_MATCH.exec('chrome-extension://jjcldkdmokihdaomalanmlohibnoplog/index.html?foo#bar');
|
var match = SERVER_MATCH.exec('chrome-extension://jjcldkdmokihdaomalanmlohibnoplog/index.html?foo#bar');
|
||||||
|
|
||||||
expect(match[1]).toBe('chrome-extension');
|
expect(match[1]).toBe('chrome-extension');
|
||||||
expect(match[3]).toBe('jjcldkdmokihdaomalanmlohibnoplog');
|
expect(match[3]).toBe('jjcldkdmokihdaomalanmlohibnoplog');
|
||||||
expect(match[6]).toBe('/index.html');
|
|
||||||
expect(match[8]).toBe('foo');
|
|
||||||
expect(match[10]).toBe('bar');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse FFOS app:// urls', function() {
|
it('should parse FFOS app:// urls', function() {
|
||||||
var match = URL_MATCH.exec('app://{d0419af1-8b42-41c5-96f4-ef4179e52315}/path');
|
var match = SERVER_MATCH.exec('app://{d0419af1-8b42-41c5-96f4-ef4179e52315}/path');
|
||||||
|
|
||||||
expect(match[1]).toBe('app');
|
expect(match[1]).toBe('app');
|
||||||
expect(match[3]).toBe('{d0419af1-8b42-41c5-96f4-ef4179e52315}');
|
expect(match[3]).toBe('{d0419af1-8b42-41c5-96f4-ef4179e52315}');
|
||||||
|
|
@ -686,7 +698,7 @@ describe('$location', function() {
|
||||||
expect(match[6]).toBe('/path');
|
expect(match[6]).toBe('/path');
|
||||||
expect(match[8]).toBeFalsy();
|
expect(match[8]).toBeFalsy();
|
||||||
|
|
||||||
match = URL_MATCH.exec('app://}foo{')
|
match = SERVER_MATCH.exec('app://}foo{')
|
||||||
expect(match).toBe(null);
|
expect(match).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -1077,7 +1089,7 @@ describe('$location', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should not intercept link clicks outside the app base url space', function() {
|
it('should not intercept clicks outside the current hash prefix', function() {
|
||||||
var base, clickHandler;
|
var base, clickHandler;
|
||||||
module(function($provide) {
|
module(function($provide) {
|
||||||
$provide.value('$rootElement', {
|
$provide.value('$rootElement', {
|
||||||
|
|
@ -1085,13 +1097,13 @@ describe('$location', function() {
|
||||||
expect(event).toEqual('click');
|
expect(event).toEqual('click');
|
||||||
clickHandler = handler;
|
clickHandler = handler;
|
||||||
},
|
},
|
||||||
unbind: angular.noop
|
unbind: noop
|
||||||
});
|
});
|
||||||
return function($browser) {
|
return function($browser) {
|
||||||
$browser.url(base = 'http://server/');
|
$browser.url(base = 'http://server/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
inject(function($rootScope, $compile, $browser, $rootElement, $document, $location) {
|
inject(function($location) {
|
||||||
// make IE happy
|
// make IE happy
|
||||||
jqLite(window.document.body).html('<a href="http://server/test.html">link</a>');
|
jqLite(window.document.body).html('<a href="http://server/test.html">link</a>');
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue