Skip to content

Commit

Permalink
fix(a): don't preventDefault on click when SVGAElement has an xlink:h…
Browse files Browse the repository at this point in the history
…ref 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 angular#5896
Closes angular#5897
  • Loading branch information
caitp committed Jan 22, 2014
1 parent b07afa0 commit e020916
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 2 deletions.
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) {
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();
});
});
}
});

0 comments on commit e020916

Please sign in to comment.