| OLD | NEW |
| 1 part of angular.directive; | 1 part of angular.directive; |
| 2 | 2 |
| 3 // NOTE(deboer): onXX functions are now typed as 'var' instead of 'Getter' | 3 // NOTE(deboer): onXX functions are now typed as 'var' instead of 'Getter' |
| 4 // to work-around https://code.google.com/p/dart/issues/detail?id=13519 | 4 // to work-around https://code.google.com/p/dart/issues/detail?id=13519 |
| 5 | 5 |
| 6 /** | 6 /** |
| 7 * Allows you to specify custom behavior for DOM UI events such as mouse, | 7 * Allows you to specify custom behavior for DOM UI events such as mouse, |
| 8 * keyboard and touch events. | 8 * keyboard and touch events. |
| 9 * | 9 * |
| 10 * The custom behavior is specified via an Angular binding expression specified | 10 * The custom behavior is specified via an Angular binding expression specified |
| 11 * on the `ng-`*event* directive (e.g. `ng-click`). This expression is evaluate
d | 11 * on the `ng-`*event* directive (e.g. `ng-click`). This expression is evaluate
d |
| 12 * on the correct `scope` every time the event occurs. The event is available | 12 * on the correct `scope` every time the event occurs. The event is available |
| 13 * to the expression as `$event`. | 13 * to the expression as `$event`. |
| 14 * | 14 * |
| 15 * This is more secure than inline DOM handlers in HTML that execute arbitrary | 15 * This is more secure than inline DOM handlers in HTML that execute arbitrary |
| 16 * JavaScript code and have access to globals instead of the scope without the | 16 * JavaScript code and have access to globals instead of the scope without the |
| 17 * safety constraints of the Angular expression language. | 17 * safety constraints of the Angular expression language. |
| 18 * | 18 * |
| 19 * Example: | 19 * Example: |
| 20 * | 20 * |
| 21 * <button ng-click="lastEvent='Click'" | 21 * <button ng-click="lastEvent='Click'" |
| 22 * ng-doubleclick="lastEvent='DblClick'"> | 22 * ng-doubleclick="lastEvent='DblClick'"> |
| 23 * Button | 23 * Button |
| 24 * </button> | 24 * </button> |
| 25 * | 25 * |
| 26 * The full list of supported handlers are: | 26 * The full list of supported handlers are: |
| 27 * | 27 * |
| 28 * - [ng-blur] |
| 28 * - [ng-abort] | 29 * - [ng-abort] |
| 29 * - [ng-beforecopy] | 30 * - [ng-beforecopy] |
| 30 * - [ng-beforecut] | 31 * - [ng-beforecut] |
| 31 * - [ng-beforepaste] | 32 * - [ng-beforepaste] |
| 32 * - [ng-blur] | 33 * - [ng-blur] |
| 33 * - [ng-change] | 34 * - [ng-change] |
| 34 * - [ng-click] | 35 * - [ng-click] |
| 35 * - [ng-contextmenu] | 36 * - [ng-contextmenu] |
| 36 * - [ng-copy] | 37 * - [ng-copy] |
| 37 * - [ng-cut] | 38 * - [ng-cut] |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 @NgDirective(selector: '[ng-submit]', map: const {'ng-submit':
'&onSubmit'}) | 124 @NgDirective(selector: '[ng-submit]', map: const {'ng-submit':
'&onSubmit'}) |
| 124 @NgDirective(selector: '[ng-toucheancel]', map: const {'ng-touchcancel':
'&onTouchCancel'}) | 125 @NgDirective(selector: '[ng-toucheancel]', map: const {'ng-touchcancel':
'&onTouchCancel'}) |
| 125 @NgDirective(selector: '[ng-touchend]', map: const {'ng-touchend':
'&onTouchEnd'}) | 126 @NgDirective(selector: '[ng-touchend]', map: const {'ng-touchend':
'&onTouchEnd'}) |
| 126 @NgDirective(selector: '[ng-touchenter]', map: const {'ng-touchenter':
'&onTouchEnter'}) | 127 @NgDirective(selector: '[ng-touchenter]', map: const {'ng-touchenter':
'&onTouchEnter'}) |
| 127 @NgDirective(selector: '[ng-touchleave]', map: const {'ng-touchleave':
'&onTouchLeave'}) | 128 @NgDirective(selector: '[ng-touchleave]', map: const {'ng-touchleave':
'&onTouchLeave'}) |
| 128 @NgDirective(selector: '[ng-touchmove]', map: const {'ng-touchmove':
'&onTouchMove'}) | 129 @NgDirective(selector: '[ng-touchmove]', map: const {'ng-touchmove':
'&onTouchMove'}) |
| 129 @NgDirective(selector: '[ng-touchstart]', map: const {'ng-touchstart':
'&onTouchStart'}) | 130 @NgDirective(selector: '[ng-touchstart]', map: const {'ng-touchstart':
'&onTouchStart'}) |
| 130 @NgDirective(selector: '[ng-transitionend]', map: const {'ng-transitionend':
'&onTransitionEnd'}) | 131 @NgDirective(selector: '[ng-transitionend]', map: const {'ng-transitionend':
'&onTransitionEnd'}) |
| 131 | 132 |
| 132 class NgEventDirective { | 133 class NgEventDirective { |
| 133 // Is it better to use a map of listeners or have 29 properties on this | |
| 134 // object? One would pretty much only assign to one or two of those | |
| 135 // properties. I'm opting for the map since it's less boilerplate code. | |
| 136 var listeners = {}; | |
| 137 final dom.Element element; | |
| 138 final Scope scope; | |
| 139 | |
| 140 NgEventDirective(this.element, this.scope); | |
| 141 | 134 |
| 142 // NOTE: Do not use the element.on['some_event'].listen(...) syntax. Doing so | 135 // NOTE: Do not use the element.on['some_event'].listen(...) syntax. Doing so |
| 143 // has two downsides: | 136 // has two downsides: |
| 144 // - it loses the event typing | 137 // - it loses the event typing |
| 145 // - some DOM events may have multiple platform-dependent event names | 138 // - some DOM events may have multiple platform-dependent event names |
| 146 // under the covers. The standard Stream getters you will get the | 139 // under the covers. The standard Stream getters you will get the |
| 147 // platform specific event name automatically but you're on your own if | 140 // platform specific event name automatically but you're on your own if |
| 148 // you use the on[] syntax. This also applies to $dom_addEventListener. | 141 // you use the on[] syntax. This also applies to $dom_addEventListener. |
| 149 // Ref: http://api.dartlang.org/docs/releases/latest/dart_html/Events.html | 142 // Ref: http://api.dartlang.org/docs/releases/latest/dart_html/Events.html |
| 150 initListener(var stream, var handler) { | 143 initListener(var stream, var handler) { |
| 151 int key = stream.hashCode; | 144 int key = stream.hashCode; |
| 152 if (!listeners.containsKey(key)) { | 145 if (!listeners.containsKey(key)) { |
| 153 listeners[key] = handler; | 146 listeners[key] = handler; |
| 154 stream.listen((event) => handler({r"$event": event})); | 147 stream.listen((event) => scope.$apply(() { |
| 148 handler({r"$event": event}); |
| 149 })); |
| 155 } | 150 } |
| 156 } | 151 } |
| 157 | 152 |
| 158 set onAbort(value) => initListener(element.onAbort, val
ue); | 153 set onAbort(value) => initListener(element.onAbort, val
ue); |
| 159 set onBeforeCopy(value) => initListener(element.onBeforeCopy, val
ue); | 154 set onBeforeCopy(value) => initListener(element.onBeforeCopy, val
ue); |
| 160 set onBeforeCut(value) => initListener(element.onBeforeCut, val
ue); | 155 set onBeforeCut(value) => initListener(element.onBeforeCut, val
ue); |
| 161 set onBeforePaste(value) => initListener(element.onBeforePaste, val
ue); | 156 set onBeforePaste(value) => initListener(element.onBeforePaste, val
ue); |
| 162 set onBlur(value) => initListener(element.onBlur, val
ue); | 157 set onBlur(value) => initListener(element.onBlur, val
ue); |
| 163 set onChange(value) => initListener(element.onChange, val
ue); | 158 set onChange(value) => initListener(element.onChange, val
ue); |
| 164 set onClick(value) => initListener(element.onClick, val
ue); | 159 set onClick(value) => initListener(element.onClick, val
ue); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 set onSelectStart(value) => initListener(element.onSelectStart, val
ue); | 194 set onSelectStart(value) => initListener(element.onSelectStart, val
ue); |
| 200 // set onSpeechChange(value) => initListener(element.onSpeechChange, v
alue); | 195 // set onSpeechChange(value) => initListener(element.onSpeechChange, v
alue); |
| 201 set onSubmit(value) => initListener(element.onSubmit, val
ue); | 196 set onSubmit(value) => initListener(element.onSubmit, val
ue); |
| 202 set onTouchCancel(value) => initListener(element.onTouchCancel, val
ue); | 197 set onTouchCancel(value) => initListener(element.onTouchCancel, val
ue); |
| 203 set onTouchEnd(value) => initListener(element.onTouchEnd, val
ue); | 198 set onTouchEnd(value) => initListener(element.onTouchEnd, val
ue); |
| 204 set onTouchEnter(value) => initListener(element.onTouchEnter, val
ue); | 199 set onTouchEnter(value) => initListener(element.onTouchEnter, val
ue); |
| 205 set onTouchLeave(value) => initListener(element.onTouchLeave, val
ue); | 200 set onTouchLeave(value) => initListener(element.onTouchLeave, val
ue); |
| 206 set onTouchMove(value) => initListener(element.onTouchMove, val
ue); | 201 set onTouchMove(value) => initListener(element.onTouchMove, val
ue); |
| 207 set onTouchStart(value) => initListener(element.onTouchStart, val
ue); | 202 set onTouchStart(value) => initListener(element.onTouchStart, val
ue); |
| 208 set onTransitionEnd(value) => initListener(element.onTransitionEnd, val
ue); | 203 set onTransitionEnd(value) => initListener(element.onTransitionEnd, val
ue); |
| 204 |
| 205 // Is it better to use a map of listeners or have 29 properties on this |
| 206 // object? One would pretty much only assign to one or two of those |
| 207 // properties. I'm opting for the map since it's less boilerplate code. |
| 208 var listeners = {}; |
| 209 dom.Element element; |
| 210 Scope scope; |
| 211 |
| 212 NgEventDirective(this.element, this.scope); |
| 209 } | 213 } |
| OLD | NEW |