diff options
Diffstat (limited to 'src/ng/location.js')
| -rw-r--r-- | src/ng/location.js | 96 |
1 files changed, 65 insertions, 31 deletions
diff --git a/src/ng/location.js b/src/ng/location.js index b5f10293..727a0c2b 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -23,6 +23,10 @@ function encodePath(path) { return segments.join('/'); } +function stripHash(url) { + return url.split('#')[0]; +} + function matchUrl(url, obj) { var match = URL_MATCH.exec(url); @@ -102,19 +106,19 @@ function convertToHashbangUrl(url, basePath, hashPrefix) { * @param {string} url HTML5 url * @param {string} pathPrefix */ -function LocationUrl(url, pathPrefix) { +function LocationUrl(url, pathPrefix, appBaseUrl) { pathPrefix = pathPrefix || ''; /** * Parse given html5 (regular) url string into properties - * @param {string} url HTML5 url + * @param {string} newAbsoluteUrl HTML5 url * @private */ - this.$$parse = function(url) { - var match = matchUrl(url, this); + this.$$parse = function(newAbsoluteUrl) { + var match = matchUrl(newAbsoluteUrl, this); if (match.path.indexOf(pathPrefix) !== 0) { - throw Error('Invalid url "' + url + '", missing path prefix "' + pathPrefix + '" !'); + throw Error('Invalid url "' + newAbsoluteUrl + '", missing path prefix "' + pathPrefix + '" !'); } this.$$path = decodeURIComponent(match.path.substr(pathPrefix.length)); @@ -137,6 +141,14 @@ function LocationUrl(url, pathPrefix) { pathPrefix + this.$$url; }; + + this.$$rewriteAppUrl = function(absoluteLinkUrl) { + if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) { + return absoluteLinkUrl; + } + } + + this.$$parse(url); } @@ -149,7 +161,7 @@ function LocationUrl(url, pathPrefix) { * @param {string} url Legacy url * @param {string} hashPrefix Prefix for hash part (containing path and search) */ -function LocationHashbangUrl(url, hashPrefix) { +function LocationHashbangUrl(url, hashPrefix, appBaseUrl) { var basePath; /** @@ -192,6 +204,13 @@ function LocationHashbangUrl(url, hashPrefix) { basePath + (this.$$url ? '#' + hashPrefix + this.$$url : ''); }; + this.$$rewriteAppUrl = function(absoluteLinkUrl) { + if(absoluteLinkUrl.indexOf(appBaseUrl) == 0) { + return absoluteLinkUrl; + } + } + + this.$$parse(url); } @@ -380,6 +399,19 @@ 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) { return function() { return this[property]; @@ -479,26 +511,33 @@ function $LocationProvider(){ basePath, pathPrefix, initUrl = $browser.url(), - absUrlPrefix; + initUrlParts = matchUrl(initUrl), + appBaseUrl; if (html5Mode) { basePath = $browser.baseHref() || '/'; pathPrefix = pathPrefixFromBase(basePath); + appBaseUrl = + composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) + + pathPrefix + '/'; + if ($sniffer.history) { $location = new LocationUrl( convertToHtml5Url(initUrl, basePath, hashPrefix), - pathPrefix); + pathPrefix, appBaseUrl); } else { - $location = new LocationHashbangUrl( + $location = new LocationHashbangInHtml5Url( convertToHashbangUrl(initUrl, basePath, hashPrefix), - hashPrefix); + hashPrefix, appBaseUrl, basePath.substr(pathPrefix.length + 1)); } - // link rewriting - absUrlPrefix = composeProtocolHostPort( - $location.protocol(), $location.host(), $location.port()) + pathPrefix; } else { - $location = new LocationHashbangUrl(initUrl, hashPrefix); - absUrlPrefix = $location.absUrl().split('#')[0]; + appBaseUrl = + composeProtocolHostPort(initUrlParts.protocol, initUrlParts.host, initUrlParts.port) + + (initUrlParts.path || '') + + (initUrlParts.search ? ('?' + initUrlParts.search) : '') + + '#' + hashPrefix + '/'; + + $location = new LocationHashbangUrl(initUrl, hashPrefix, appBaseUrl); } $rootElement.bind('click', function(event) { @@ -510,27 +549,22 @@ function $LocationProvider(){ var elm = jqLite(event.target); // traverse the DOM up to find first A tag - while (elm.length && lowercase(elm[0].nodeName) !== 'a') { + while (lowercase(elm[0].nodeName) !== 'a') { + if (elm[0] === $rootElement[0]) return; elm = elm.parent(); } var absHref = elm.prop('href'), - href; - - if (!absHref || - elm.attr('target') || - absHref.indexOf(absUrlPrefix) !== 0) { // link to different domain or base path - return; + rewrittenUrl = $location.$$rewriteAppUrl(absHref); + + if (absHref && !elm.attr('target') && rewrittenUrl) { + // update location manually + $location.$$parse(rewrittenUrl); + $rootScope.$apply(); + event.preventDefault(); + // hack to work around FF6 bug 684208 when scenario runner clicks on links + window.angular['ff-684208-preventDefault'] = true; } - - // update location with href without the prefix - href = absHref.substr(absUrlPrefix.length); - if (href.indexOf('#' + hashPrefix) == 0) href = href.substr(hashPrefix.length + 1); - $location.url(href); - $rootScope.$apply(); - event.preventDefault(); - // hack to work around FF6 bug 684208 when scenario runner clicks on links - window.angular['ff-684208-preventDefault'] = true; }); |
