| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of html; | 5 part of html; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Works with KeyboardEvent and KeyEvent to determine how to expose information | 8 * Works with KeyboardEvent and KeyEvent to determine how to expose information |
| 9 * about Key(board)Events. This class functions like an EventListenerList, and | 9 * about Key(board)Events. This class functions like an EventListenerList, and |
| 10 * provides a consistent interface for the Dart | 10 * provides a consistent interface for the Dart |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */ | 31 /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */ |
| 32 String _type; | 32 String _type; |
| 33 | 33 |
| 34 /** The element we are watching for events to happen on. */ | 34 /** The element we are watching for events to happen on. */ |
| 35 EventTarget _target; | 35 EventTarget _target; |
| 36 | 36 |
| 37 // The distance to shift from upper case alphabet Roman letters to lower case. | 37 // The distance to shift from upper case alphabet Roman letters to lower case. |
| 38 final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0]; | 38 final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0]; |
| 39 | 39 |
| 40 // Instance members referring to the internal event handlers because closures | 40 StreamSubscription _keyUpSubscription, _keyDownSubscription, |
| 41 // are not hashable. | 41 _keyPressSubscription; |
| 42 var _keyUp, _keyDown, _keyPress; | |
| 43 | 42 |
| 44 /** | 43 /** |
| 45 * An enumeration of key identifiers currently part of the W3C draft for DOM3 | 44 * An enumeration of key identifiers currently part of the W3C draft for DOM3 |
| 46 * and their mappings to keyCodes. | 45 * and their mappings to keyCodes. |
| 47 * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set | 46 * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set |
| 48 */ | 47 */ |
| 49 static Map<String, int> _keyIdentifier = { | 48 static Map<String, int> _keyIdentifier = { |
| 50 'Up': KeyCode.UP, | 49 'Up': KeyCode.UP, |
| 51 'Down': KeyCode.DOWN, | 50 'Down': KeyCode.DOWN, |
| 52 'Left': KeyCode.LEFT, | 51 'Left': KeyCode.LEFT, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 } | 87 } |
| 89 | 88 |
| 90 /** | 89 /** |
| 91 * General constructor, performs basic initialization for our improved | 90 * General constructor, performs basic initialization for our improved |
| 92 * KeyboardEvent controller. | 91 * KeyboardEvent controller. |
| 93 */ | 92 */ |
| 94 _KeyboardEventController(EventTarget target, String type) { | 93 _KeyboardEventController(EventTarget target, String type) { |
| 95 _callbacks = []; | 94 _callbacks = []; |
| 96 _type = type; | 95 _type = type; |
| 97 _target = target; | 96 _target = target; |
| 98 _keyDown = processKeyDown; | |
| 99 _keyUp = processKeyUp; | |
| 100 _keyPress = processKeyPress; | |
| 101 } | 97 } |
| 102 | 98 |
| 103 /** | 99 /** |
| 104 * Hook up all event listeners under the covers so we can estimate keycodes | 100 * Hook up all event listeners under the covers so we can estimate keycodes |
| 105 * and charcodes when they are not provided. | 101 * and charcodes when they are not provided. |
| 106 */ | 102 */ |
| 107 void _initializeAllEventListeners() { | 103 void _initializeAllEventListeners() { |
| 108 _keyDownList = []; | 104 _keyDownList = []; |
| 109 _target.on.keyDown.add(_keyDown, true); | 105 if (_keyDownSubscription == null) { |
| 110 _target.on.keyPress.add(_keyPress, true); | 106 _keyDownSubscription = Element.keyDownEvent.forTarget( |
| 111 _target.on.keyUp.add(_keyUp, true); | 107 _target, useCapture: true).listen(processKeyDown); |
| 108 _keyPressSubscription = Element.keyPressEvent.forTarget( |
| 109 _target, useCapture: true).listen(processKeyUp); |
| 110 _keyUpSubscription = Element.keyUpEvent.forTarget( |
| 111 _target, useCapture: true).listen(processKeyPress); |
| 112 } |
| 112 } | 113 } |
| 113 | 114 |
| 114 /** Add a callback that wishes to be notified when a KeyEvent occurs. */ | 115 /** Add a callback that wishes to be notified when a KeyEvent occurs. */ |
| 115 void add(void callback(KeyEvent)) { | 116 void add(void callback(KeyEvent)) { |
| 116 if (_callbacks.length == 0) { | 117 if (_callbacks.length == 0) { |
| 117 _initializeAllEventListeners(); | 118 _initializeAllEventListeners(); |
| 118 } | 119 } |
| 119 _callbacks.add(callback); | 120 _callbacks.add(callback); |
| 120 } | 121 } |
| 121 | 122 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 135 } | 136 } |
| 136 | 137 |
| 137 /** Remove the given callback from the listeners list. */ | 138 /** Remove the given callback from the listeners list. */ |
| 138 void remove(void callback(KeyEvent)) { | 139 void remove(void callback(KeyEvent)) { |
| 139 var index = _callbacks.indexOf(callback); | 140 var index = _callbacks.indexOf(callback); |
| 140 if (index != -1) { | 141 if (index != -1) { |
| 141 _callbacks.removeAt(index); | 142 _callbacks.removeAt(index); |
| 142 } | 143 } |
| 143 if (_callbacks.length == 0) { | 144 if (_callbacks.length == 0) { |
| 144 // If we have no listeners, don't bother keeping track of keypresses. | 145 // If we have no listeners, don't bother keeping track of keypresses. |
| 145 _target.on.keyDown.remove(_keyDown); | 146 _keyDownSubscription.cancel(); |
| 146 _target.on.keyPress.remove(_keyPress); | 147 _keyDownSubscription = null; |
| 147 _target.on.keyUp.remove(_keyUp); | 148 _keyPressSubscription.cancel(); |
| 149 _keyPressSubscription = null; |
| 150 _keyUpSubscription.cancel(); |
| 151 _keyUpSubscription = null; |
| 148 } | 152 } |
| 149 } | 153 } |
| 150 | 154 |
| 151 /** Determine if caps lock is one of the currently depressed keys. */ | 155 /** Determine if caps lock is one of the currently depressed keys. */ |
| 152 bool get _capsLockOn => | 156 bool get _capsLockOn => |
| 153 _keyDownList.any((var element) => element.keyCode == KeyCode.CAPS_LOCK); | 157 _keyDownList.any((var element) => element.keyCode == KeyCode.CAPS_LOCK); |
| 154 | 158 |
| 155 /** | 159 /** |
| 156 * Given the previously recorded keydown key codes, see if we can determine | 160 * Given the previously recorded keydown key codes, see if we can determine |
| 157 * the keycode of this keypress [event]. (Generally browsers only provide | 161 * the keycode of this keypress [event]. (Generally browsers only provide |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 _keyDownList.where((element) => element != toRemove).toList(); | 401 _keyDownList.where((element) => element != toRemove).toList(); |
| 398 } else if (_keyDownList.length > 0) { | 402 } else if (_keyDownList.length > 0) { |
| 399 // This happens when we've reached some international keyboard case we | 403 // This happens when we've reached some international keyboard case we |
| 400 // haven't accounted for or we haven't correctly eliminated all browser | 404 // haven't accounted for or we haven't correctly eliminated all browser |
| 401 // inconsistencies. Filing bugs on when this is reached is welcome! | 405 // inconsistencies. Filing bugs on when this is reached is welcome! |
| 402 _keyDownList.removeLast(); | 406 _keyDownList.removeLast(); |
| 403 } | 407 } |
| 404 _dispatch(e); | 408 _dispatch(e); |
| 405 } | 409 } |
| 406 } | 410 } |
| OLD | NEW |