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

Commit

Permalink
fix(htmlAnchorDirective): remove event listener if target is not element
Browse files Browse the repository at this point in the history
Previously, when an `a` tag element used a directive with a replacing template, and did not include an `href` or `name` attribute
before linkage, the anchor directive would always prevent default.

Now, the anchor directive will cancel its event listener if the linked element is not the same as the target element of the event.

Closes #4262
  • Loading branch information
caitp committed Jan 23, 2015
1 parent cea8e75 commit 1573e39
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
10 changes: 7 additions & 3 deletions src/ng/directive/a.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ var htmlAnchorDirective = valueFn({
// 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)) {
element.on('click', function clickHandler(event) {
if (element[0] !== event.target) {
// if the clicked element is not the directive element, stop listening.
// (the element was probably replaced).
element.off('click', clickHandler);
} else if (!element.attr(href)) {
// if we have no href url, then don't navigate anywhere.
event.preventDefault();
}
});
Expand Down
53 changes: 53 additions & 0 deletions test/ng/directive/aSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@
describe('a', function() {
var element, $compile, $rootScope;

beforeEach(module(function($compileProvider) {
$compileProvider.
directive('linkTo', valueFn({
restrict: 'A',
template: '<div class="my-link"><a href="{{destination}}">{{destination}}</a></div>',
replace: true,
scope: {
destination: '@linkTo'
}
})).
directive('linkNot', valueFn({
restrict: 'A',
template: '<div class="my-link"><a href>{{destination}}</a></div>',
replace: true,
scope: {
destination: '@linkNot'
}
}));
}));

beforeEach(inject(function(_$compile_, _$rootScope_) {
$compile = _$compile_;
Expand Down Expand Up @@ -76,6 +95,40 @@ describe('a', function() {
});


it('should not preventDefault if anchor element is replaced with href-containing element', function() {
spyOn(jqLite.prototype, 'on').andCallThrough();
element = $compile('<a link-to="https://www.google.com">')($rootScope);
$rootScope.$digest();

var child = element.children('a');
var preventDefault = jasmine.createSpy('preventDefault');

child.triggerHandler({
type: 'click',
preventDefault: preventDefault
});

expect(preventDefault).not.toHaveBeenCalled();
});


it('should preventDefault if anchor element is replaced with element without href attribute', function() {
spyOn(jqLite.prototype, 'on').andCallThrough();
element = $compile('<a link-not="https://www.google.com">')($rootScope);
$rootScope.$digest();

var child = element.children('a');
var preventDefault = jasmine.createSpy('preventDefault');

child.triggerHandler({
type: 'click',
preventDefault: preventDefault
});

expect(preventDefault).toHaveBeenCalled();
});


if (isDefined(window.SVGElement)) {
describe('SVGAElement', function() {
it('should prevent default action to be executed when href is empty', function() {
Expand Down

0 comments on commit 1573e39

Please sign in to comment.