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

fix(a): don't preventDefault on click when SVGAElement has an xlink:href attribute #5897

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/ng/directive/a.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ var htmlAnchorDirective = valueFn({
element.append(document.createComment('IE fix'));
}

if (!attr.href && !attr.name) {
if (!attr.href && !attr.xlinkHref && !attr.name) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why exactly do we care about the 'name' attribute? I don't really get that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it has name then it's just an anchor e.g. <a name="someId"></a> and in that case we don't need to listen for clicks on this element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see, thanks

return function(scope, element) {
// SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
'xlink:href' : 'href';
element.on('click', function(event){
// if we have no href url, then don't navigate anywhere.
if (!element.attr('href')) {
if (!element.attr(href)) {
event.preventDefault();
}
});
Expand Down
67 changes: 67 additions & 0 deletions test/ng/directive/aSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,71 @@ describe('a', function() {

expect(jq.prototype.on).not.toHaveBeenCalled();
});


if (isDefined(window.SVGElement)) {
describe('SVGAElement', function() {
it('should prevent default action to be executed when href is empty', function() {
var orgLocation = document.location.href,
preventDefaultCalled = false,
event,
child;

element = $compile('<svg><a xlink:href="">empty link</a></svg>')($rootScope);
child = element.children('a');

if (msie < 9) {

event = document.createEventObject();
expect(event.returnValue).not.toBeDefined();
child[0].fireEvent('onclick', event);
expect(event.returnValue).toEqual(false);

} else {

event = document.createEvent('MouseEvent');
event.initMouseEvent(
'click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);

event.preventDefaultOrg = event.preventDefault;
event.preventDefault = function() {
preventDefaultCalled = true;
if (this.preventDefaultOrg) this.preventDefaultOrg();
};

child[0].dispatchEvent(event);

expect(preventDefaultCalled).toEqual(true);
}

expect(document.location.href).toEqual(orgLocation);
});


it('should not link and hookup an event if xlink:href is present at compile', function() {
var jq = jQuery || jqLite;
element = jq('<svg><a xlink:href="bobby">hello@you</a></svg>');
var linker = $compile(element);

spyOn(jq.prototype, 'on');

linker($rootScope);

expect(jq.prototype.on).not.toHaveBeenCalled();
});


it('should not link and hookup an event if name is present at compile', function() {
var jq = jQuery || jqLite;
element = jq('<svg><a name="bobby">hello@you</a></svg>');
var linker = $compile(element);

spyOn(jq.prototype, 'on');

linker($rootScope);

expect(jq.prototype.on).not.toHaveBeenCalled();
});
});
}
});