diff options
| author | Igor Minar | 2010-09-30 23:07:36 +0800 |
|---|---|---|
| committer | Misko Hevery | 2010-10-01 07:44:46 +0800 |
| commit | 8248e77a7b910bcbc71ca25c06bef44dd6712990 (patch) | |
| tree | 333b5b91e914a96f27b214bac3ef61c8d04e5b4d | |
| parent | 0af763dcec8b9f6b17208ac58607cd1124382f63 (diff) | |
| download | angular.js-8248e77a7b910bcbc71ca25c06bef44dd6712990.tar.bz2 | |
'A' tag widget and ng:click propagation change
* added a widget for A (anchor) tag, that modifies the default behavior
and prevent default action (location change and page reload) for tags
with empty href attribute
* stopped event propagation for all ng:click handlers
| -rw-r--r-- | src/directives.js | 11 | ||||
| -rw-r--r-- | src/widgets.js | 22 | ||||
| -rw-r--r-- | test/directivesSpec.js | 13 | ||||
| -rw-r--r-- | test/widgetsSpec.js | 35 |
4 files changed, 80 insertions, 1 deletions
diff --git a/src/directives.js b/src/directives.js index 69648e31..4443cc9d 100644 --- a/src/directives.js +++ b/src/directives.js @@ -198,13 +198,22 @@ angularWidget("@ng:repeat", function(expression, element){ }; }); + +/* + * A directive that allows creation of custom onclick handlers that are defined as angular + * expressions and are compiled and executed within the current scope. + * + * Events that are handled via these handler are always configured not to propagate further. + * + * TODO: maybe we should consider allowing users to control even propagation in the future. + */ angularDirective("ng:click", function(expression, element){ return function(element){ var self = this; element.bind('click', function(event){ self.$tryEval(expression, element); self.$root.$eval(); - event.preventDefault(); + event.stopPropagation(); }); }; }); diff --git a/src/widgets.js b/src/widgets.js index fbca8436..24eba900 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -340,3 +340,25 @@ var ngSwitch = angularWidget('ng:switch', function (element){ }, route: switchRouteMatcher }); + + +/* + * Modifies the default behavior of html A tag, so that the default action is prevented when href + * attribute is empty. + * + * The reasoning for this change is to allow easy creation of action links with ng:click without + * changing the location or causing page reloads, e.g.: + * <a href="" ng:click="model.$save()">Save</a> + */ +angular.widget('a', function() { + this.descend(true); + this.directives(true); + + return function(element) { + if (element.attr('href') === '') { + element.bind('click', function(event){ + event.preventDefault(); + }); + } + }; +});
\ No newline at end of file diff --git a/test/directivesSpec.js b/test/directivesSpec.js index f0eb5c09..72f7b2f2 100644 --- a/test/directivesSpec.js +++ b/test/directivesSpec.js @@ -169,6 +169,19 @@ describe("directives", function(){ element.trigger('click'); expect(scope.$get('clicked')).toEqual(true); }); + + it('should stop event propagation', function() { + var scope = compile('<div ng:click="outer = true"><div ng:click="inner = true"></div></div>'); + scope.$eval(); + expect(scope.$get('outer')).not.toBeDefined(); + expect(scope.$get('inner')).not.toBeDefined(); + + var innerDiv = jqLite(element.children()[0]); + + innerDiv.trigger('click'); + expect(scope.$get('outer')).not.toBeDefined(); + expect(scope.$get('inner')).toEqual(true); + }) }); it('should ng:class', function(){ diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index d113e6ee..edaa5061 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -498,5 +498,40 @@ describe("widget", function(){ expect(element.text()).toEqual(''); }); }); + + describe('a', function() { + it('should prevent default action to be executed when href is empty', function() { + var orgLocation = document.location.href, + preventDefaultCalled = false, + event; + + compile('<a href="">empty link</a>'); + + if (msie) { + + event = document.createEventObject(); + expect(event.returnValue).not.toBeDefined(); + element[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(); + }; + + element[0].dispatchEvent(event); + + expect(preventDefaultCalled).toEqual(true); + } + + expect(document.location.href).toEqual(orgLocation); + }); + }) }); |
