mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 23:40:23 +00:00
parent
0f44964e5e
commit
6593a3e082
3 changed files with 125 additions and 33 deletions
|
|
@ -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;
|
||||
rewrittenUrl = $location.$$rewriteAppUrl(absHref);
|
||||
|
||||
if (!absHref ||
|
||||
elm.attr('target') ||
|
||||
absHref.indexOf(absUrlPrefix) !== 0) { // link to different domain or base path
|
||||
return;
|
||||
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;
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
2
src/ngMock/angular-mocks.js
vendored
2
src/ngMock/angular-mocks.js
vendored
|
|
@ -39,7 +39,7 @@ angular.mock.$Browser = function() {
|
|||
var self = this;
|
||||
|
||||
this.isMock = true;
|
||||
self.$$url = "http://server";
|
||||
self.$$url = "http://server/";
|
||||
self.$$lastUrl = self.$$url; // used by url polling fn
|
||||
self.pollFns = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,64 @@ describe('$location', function() {
|
|||
expect($browser.url()).toEqual(base + '#!/view2');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should not intercept link clicks outside the app base url space', function() {
|
||||
var base, clickHandler;
|
||||
module(function($provide) {
|
||||
$provide.value('$rootElement', {
|
||||
bind: function(event, handler) {
|
||||
expect(event).toEqual('click');
|
||||
clickHandler = handler;
|
||||
}
|
||||
});
|
||||
return function($browser) {
|
||||
$browser.url(base = 'http://server/');
|
||||
}
|
||||
});
|
||||
inject(function($rootScope, $compile, $browser, $rootElement, $document, $location) {
|
||||
// make IE happy
|
||||
jqLite(window.document.body).html('<a href="http://server/test.html">link</a>');
|
||||
|
||||
var event = {
|
||||
target: jqLite(window.document.body).find('a')[0],
|
||||
preventDefault: jasmine.createSpy('preventDefault')
|
||||
};
|
||||
|
||||
|
||||
clickHandler(event);
|
||||
expect(event.preventDefault).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should not intercept hash link clicks outside the app base url space', function() {
|
||||
var base, clickHandler;
|
||||
module(function($provide) {
|
||||
$provide.value('$rootElement', {
|
||||
bind: function(event, handler) {
|
||||
expect(event).toEqual('click');
|
||||
clickHandler = handler;
|
||||
}
|
||||
});
|
||||
return function($browser) {
|
||||
$browser.url(base = 'http://server/');
|
||||
}
|
||||
});
|
||||
inject(function($rootScope, $compile, $browser, $rootElement, $document, $location) {
|
||||
// make IE happy
|
||||
jqLite(window.document.body).html('<a href="http://server/index.html#test">link</a>');
|
||||
|
||||
var event = {
|
||||
target: jqLite(window.document.body).find('a')[0],
|
||||
preventDefault: jasmine.createSpy('preventDefault')
|
||||
};
|
||||
|
||||
|
||||
clickHandler(event);
|
||||
expect(event.preventDefault).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -1111,7 +1169,7 @@ describe('$location', function() {
|
|||
);
|
||||
|
||||
|
||||
it('should listen on click events on href and prevent browser default in hasbang mode', function() {
|
||||
it('should listen on click events on href and prevent browser default in hashbang mode', function() {
|
||||
module(function() {
|
||||
return function($rootElement, $compile, $rootScope) {
|
||||
$rootElement.html('<a href="http://server/#/somePath">link</a>');
|
||||
|
|
@ -1162,7 +1220,7 @@ describe('$location', function() {
|
|||
log += '$locationChangeStart';
|
||||
});
|
||||
$rootScope.$on('$locationChangeSuccess', function() {
|
||||
throw new Error('after cancalation in html5 mode');
|
||||
throw new Error('after cancelation in html5 mode');
|
||||
});
|
||||
|
||||
browserTrigger(link, 'click');
|
||||
|
|
|
|||
Loading…
Reference in a new issue