Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 24f7999

Browse files
committed
fix($location): fix and test html5Mode url-parsing algorithm for legacy browsers
This CL fixes problems and adds test cases for changes from #6421. Changes include fixing the algorithm for preprocessing href attribute values, as well as supporting xlink:href attributes. Credit for the original URL parsing algorithm still goes to @richardcrichardc. Good work, champ!
1 parent e020366 commit 24f7999

File tree

2 files changed

+68
-15
lines changed

2 files changed

+68
-15
lines changed

src/ng/location.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -653,33 +653,34 @@ function $LocationProvider(){
653653
}
654654

655655
// Make relative links work in HTML5 mode for legacy browsers (or at least IE8 & 9)
656-
// The href should be a regular url e.g. /link/somewhere or link/somewhere or ../somewhere or somewhere#anchor or http://example.com/somewhere
656+
// The href should be a regular url e.g. /link/somewhere or link/somewhere or ../somewhere or
657+
// somewhere#anchor or http://example.com/somewhere
657658
if (LocationMode === LocationHashbangInHtml5Url) {
658-
// get the actual href attribute - see http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
659-
// TODO check browser is in standards mode
660-
var href = elm[0].getAttribute('href');
659+
// get the actual href attribute - see
660+
// http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
661+
var href = elm.attr('href') || elm.attr('xlink:href');
661662

662-
if (href.indexOf('://' == -1)) { // Ignore absolute URLs
663+
if (href.indexOf('://') < 0) { // Ignore absolute URLs
664+
var prefix = '#' + hashPrefix;
663665
if (href[0] == '/') {
664666
// absolute path - replace old path
665-
absHref = serverBase(absHref) + href;
667+
absHref = appBase + prefix + href;
666668
} else if (href[0] == '#') {
667669
// local anchor
668-
absHref = serverBase(absHref) + $location.path() + href;
670+
absHref = appBase + prefix + ($location.path() || '/') + href;
669671
} else {
670672
// relative path - join with current path
671673
var stack = $location.path().split("/"),
672674
parts = href.split("/");
673-
stack.pop(); // remove top file
674675
for (var i=0; i<parts.length; i++) {
675676
if (parts[i] == ".")
676677
continue;
677678
else if (parts[i] == "..")
678679
stack.pop();
679-
else
680+
else if (parts[i].length)
680681
stack.push(parts[i]);
681682
}
682-
absHref = serverBase(absHref) + stack.join("/");
683+
absHref = appBase + prefix + stack.join('/');
683684
}
684685
}
685686
}

test/ng/locationSpec.js

+57-5
Original file line numberDiff line numberDiff line change
@@ -779,15 +779,22 @@ describe('$location', function() {
779779

780780
var root, link, originalBrowser, lastEventPreventDefault;
781781

782-
function configureService(linkHref, html5Mode, supportHist, attrs, content) {
782+
function configureService(linkHref, html5Mode, supportHist, relLink, attrs, content) {
783+
if (typeof relLink !== "boolean") {
784+
content = attrs;
785+
attrs = relLink;
786+
relLink = false;
787+
}
783788
module(function($provide, $locationProvider) {
784789
attrs = attrs ? ' ' + attrs + ' ' : '';
785790

786791
// fake the base behavior
787-
if (linkHref[0] == '/') {
788-
linkHref = 'http://host.com' + linkHref;
789-
} else if(!linkHref.match(/:\/\//)) {
790-
linkHref = 'http://host.com/base/' + linkHref;
792+
if (!relLink) {
793+
if (linkHref[0] == '/') {
794+
linkHref = 'http://host.com' + linkHref;
795+
} else if(!linkHref.match(/:\/\//)) {
796+
linkHref = 'http://host.com/base/' + linkHref;
797+
}
791798
}
792799

793800
link = jqLite('<a href="' + linkHref + '"' + attrs + '>' + content + '</a>')[0];
@@ -1067,6 +1074,51 @@ describe('$location', function() {
10671074
});
10681075

10691076

1077+
it('should rewrite relative links relative to current path when history disabled', function() {
1078+
configureService('link', true, false, true);
1079+
inject(
1080+
initBrowser(),
1081+
initLocation(),
1082+
function($browser, $location) {
1083+
$location.path('/some');
1084+
browserTrigger(link, 'click');
1085+
expectRewriteTo($browser, 'http://host.com/base/index.html#!/some/link');
1086+
}
1087+
);
1088+
});
1089+
1090+
1091+
it('should replace current path when link begins with "/" and history disabled', function() {
1092+
configureService('/link', true, false, true);
1093+
inject(
1094+
initBrowser(),
1095+
initLocation(),
1096+
function($browser, $location) {
1097+
$location.path('/some');
1098+
browserTrigger(link, 'click');
1099+
expectRewriteTo($browser, 'http://host.com/base/index.html#!/link');
1100+
}
1101+
);
1102+
});
1103+
1104+
1105+
it('should replace current hash fragment when link begins with "#" history disabled', function() {
1106+
configureService('#link', true, false, true);
1107+
inject(
1108+
initBrowser(),
1109+
initLocation(),
1110+
function($browser, $location) {
1111+
// Initialize browser URL
1112+
$location.path('/some');
1113+
$location.hash('foo');
1114+
browserTrigger(link, 'click');
1115+
expect($location.hash()).toBe('link');
1116+
expectRewriteTo($browser, 'http://host.com/base/index.html#!/some#link');
1117+
}
1118+
);
1119+
});
1120+
1121+
10701122
// don't run next tests on IE<9, as browserTrigger does not simulate pressed keys
10711123
if (!(msie < 9)) {
10721124

0 commit comments

Comments
 (0)