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

Commit e020916

Browse files
committed
fix(a): don't preventDefault on click when SVGAElement has an xlink:href attribute
Before this change, an SVGAElement with an xlink:href attribute and no href or name attribute which was compiled by the angular HTML compiler would never be clickable, due to the htmlAnchorDirective calling event.preventDefault() due to the missing href attribute. This change corrects this behaviour by also testing the xlink:href attribute if the element in question is determined to be an SVG anchor tag (with the href property having type SVGAnimatedString) Closes #5896 Closes #5897
1 parent b07afa0 commit e020916

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

src/ng/directive/a.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ var htmlAnchorDirective = valueFn({
3232
element.append(document.createComment('IE fix'));
3333
}
3434

35-
if (!attr.href && !attr.name) {
35+
if (!attr.href && !attr.xlinkHref && !attr.name) {
3636
return function(scope, element) {
37+
// SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
38+
var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
39+
'xlink:href' : 'href';
3740
element.on('click', function(event){
3841
// if we have no href url, then don't navigate anywhere.
39-
if (!element.attr('href')) {
42+
if (!element.attr(href)) {
4043
event.preventDefault();
4144
}
4245
});

test/ng/directive/aSpec.js

+67
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,71 @@ describe('a', function() {
8484

8585
expect(jq.prototype.on).not.toHaveBeenCalled();
8686
});
87+
88+
89+
if (isDefined(window.SVGElement)) {
90+
describe('SVGAElement', function() {
91+
it('should prevent default action to be executed when href is empty', function() {
92+
var orgLocation = document.location.href,
93+
preventDefaultCalled = false,
94+
event,
95+
child;
96+
97+
element = $compile('<svg><a xlink:href="">empty link</a></svg>')($rootScope);
98+
child = element.children('a');
99+
100+
if (msie < 9) {
101+
102+
event = document.createEventObject();
103+
expect(event.returnValue).not.toBeDefined();
104+
child[0].fireEvent('onclick', event);
105+
expect(event.returnValue).toEqual(false);
106+
107+
} else {
108+
109+
event = document.createEvent('MouseEvent');
110+
event.initMouseEvent(
111+
'click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
112+
113+
event.preventDefaultOrg = event.preventDefault;
114+
event.preventDefault = function() {
115+
preventDefaultCalled = true;
116+
if (this.preventDefaultOrg) this.preventDefaultOrg();
117+
};
118+
119+
child[0].dispatchEvent(event);
120+
121+
expect(preventDefaultCalled).toEqual(true);
122+
}
123+
124+
expect(document.location.href).toEqual(orgLocation);
125+
});
126+
127+
128+
it('should not link and hookup an event if xlink:href is present at compile', function() {
129+
var jq = jQuery || jqLite;
130+
element = jq('<svg><a xlink:href="bobby">hello@you</a></svg>');
131+
var linker = $compile(element);
132+
133+
spyOn(jq.prototype, 'on');
134+
135+
linker($rootScope);
136+
137+
expect(jq.prototype.on).not.toHaveBeenCalled();
138+
});
139+
140+
141+
it('should not link and hookup an event if name is present at compile', function() {
142+
var jq = jQuery || jqLite;
143+
element = jq('<svg><a name="bobby">hello@you</a></svg>');
144+
var linker = $compile(element);
145+
146+
spyOn(jq.prototype, 'on');
147+
148+
linker($rootScope);
149+
150+
expect(jq.prototype.on).not.toHaveBeenCalled();
151+
});
152+
});
153+
}
87154
});

0 commit comments

Comments
 (0)