Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Side by Side Diff: chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js

Issue 2444443002: cros: Allow pin keyboard to keep focus without popping up the pin keyboard. (Closed)
Patch Set: Fixed patch set 1 errors. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview 6 * @fileoverview
7 * 'pin-keyboard' is a keyboard that can be used to enter PINs or more generally 7 * 'pin-keyboard' is a keyboard that can be used to enter PINs or more generally
8 * numeric values. 8 * numeric values.
9 * 9 *
10 * Properties: 10 * Properties:
11 * value: The value of the PIN keyboard. Writing to this property will adjust 11 * value: The value of the PIN keyboard. Writing to this property will adjust
12 * the PIN keyboard's value. 12 * the PIN keyboard's value.
13 * 13 *
14 * Events: 14 * Events:
15 * pin-change: Fired when the PIN value has changed. The pin is available at 15 * pin-change: Fired when the PIN value has changed. The PIN is available at
16 * event.detail.pin. 16 * event.detail.pin.
17 * submit: Fired when the PIN is submitted. The pin is available at 17 * pin-clear: Fired when the clear button is clicked. If the PIN keyboard
18 * has no input, this notifies the input which receives the PIN
19 * keyboard events that backspace has been pressed.
20 * pin-focus: Fired when the pin-input is focused. If the PIN keyboard has no
21 * input, this notifies the input which receives the PIN keyboard
22 * events to handle the input being focused.
23 * submit: Fired when the PIN is submitted. The PIN is available at
18 * event.detail.pin. 24 * event.detail.pin.
19 * 25 *
20 * Example: 26 * Example:
21 * <pin-keyboard on-pin-change="onPinChange" on-submit="onPinSubmit" 27 * <pin-keyboard on-pin-change="onPinChange" on-submit="onPinSubmit"
22 * value="{{pinValue}}"> 28 * value="{{pinValue}}">
23 * </pin-keyboard> 29 * </pin-keyboard>
24 */ 30 */
25 31
26 (function() { 32 (function() {
27 33
28 /** 34 /**
29 * Once auto backspace starts, the time between individual backspaces. 35 * Once auto backspace starts, the time between individual backspaces.
30 * @type {number} 36 * @type {number}
31 * @const 37 * @const
32 */ 38 */
33 var REPEAT_BACKSPACE_DELAY_MS = 150; 39 var REPEAT_BACKSPACE_DELAY_MS = 150;
34 40
35 /** 41 /**
36 * How long the backspace button must be held down before auto backspace 42 * How long the backspace button must be held down before auto backspace
37 * starts. 43 * starts.
38 * @type {number} 44 * @type {number}
39 * @const 45 * @const
40 */ 46 */
41 var INITIAL_BACKSPACE_DELAY_MS = 500; 47 var INITIAL_BACKSPACE_DELAY_MS = 500;
42 48
49 /**
50 * The key codes of the keys allowed to be used on the pin input, in addition to
51 * number keys. Currently we allow backspace(8), tab(9), left(37) and right(39).
52 * @type {Array<number>}
53 * @const
54 */
55 var PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES = [8, 9, 37, 39];
56
43 Polymer({ 57 Polymer({
44 is: 'pin-keyboard', 58 is: 'pin-keyboard',
45 59
46 behaviors: [ 60 behaviors: [
47 I18nBehavior, 61 I18nBehavior,
48 ], 62 ],
49 63
50 properties: { 64 properties: {
51 /** 65 /**
52 * Whether or not the keyboard's input element should be numerical 66 * Whether or not the keyboard's input element should be numerical
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 * The timeoutID used for the auto backspace. 100 * The timeoutID used for the auto backspace.
87 * @private 101 * @private
88 */ 102 */
89 startAutoBackspaceId_: { 103 startAutoBackspaceId_: {
90 type: Number, 104 type: Number,
91 value: 0 105 value: 0
92 } 106 }
93 }, 107 },
94 108
95 /** 109 /**
96 * @override
97 */
98 attached: function() {
99 // Remove the space/enter key binds from the polymer
100 // iron-a11y-keys-behavior.
101 var digitButtons = Polymer.dom(this.root).querySelectorAll('.digit-button');
102 for (var i = 0; i < digitButtons.length; ++i)
103 digitButtons[i].keyEventTarget = null;
104 },
105
106 /**
107 * Gets the container holding the password field. 110 * Gets the container holding the password field.
108 * @type {!HTMLInputElement} 111 * @type {!HTMLInputElement}
109 */ 112 */
110 get inputElement() { 113 get inputElement() {
111 return this.$$('#pin-input'); 114 return this.$$('#pin-input');
112 }, 115 },
113 116
114 /** Transfers focus to the input element. */ 117 /** Transfers focus to the input element. */
115 focus: function() { 118 focus: function() {
116 this.$$('#pin-input').focus(); 119 if (!this.hideInput)
120 this.$$('#pin-input').focus();
121 this.fire('pin-focus');
117 }, 122 },
118 123
119 /** 124 /**
120 * Called when a keypad number has been tapped. 125 * Called when a keypad number has been tapped.
121 * @param {!{target: !PaperButtonElement}} event 126 * @param {Event} event The event object.
122 * @private 127 * @private
123 */ 128 */
124 onNumberTap_: function(event, detail) { 129 onNumberTap_: function(event) {
125 var numberValue = event.target.getAttribute('value'); 130 var numberValue = event.target.getAttribute('value');
126 this.value += numberValue; 131 this.value += numberValue;
132
133 // If a number button is clicked, we do not want to switch focus to the
134 // button, therefore we transfer focus back to the input, but if a number
135 // button is tabbed into, it should keep focus, so users can use tab and
136 // spacebar/return to enter their PIN.
137 if (!event.target.receivedFocusFromKeyboard)
138 this.focus();
139 event.preventDefault();
127 }, 140 },
128 141
129 /** Fires a submit event with the current PIN value. */ 142 /** Fires a submit event with the current PIN value. */
130 firePinSubmitEvent_: function() { 143 firePinSubmitEvent_: function() {
131 this.fire('submit', { pin: this.value }); 144 this.fire('submit', { pin: this.value });
132 }, 145 },
133 146
134 /** 147 /**
135 * Fires an update event with the current PIN value. The event will only be 148 * Fires an update event with the current PIN value. The event will only be
136 * fired if the PIN value has actually changed. 149 * fired if the PIN value has actually changed.
137 * @param {string} value 150 * @param {string} value
138 * @param {string} previous 151 * @param {string} previous
139 */ 152 */
140 onPinValueChange_: function(value, previous) { 153 onPinValueChange_: function(value, previous) {
141 if (value != previous) 154 if (value != previous)
142 this.fire('pin-change', { pin: value }); 155 this.fire('pin-change', { pin: value });
143 }, 156 },
144 157
145 /** 158 /**
146 * Called when the user wants to erase the last character of the entered 159 * Called when the user wants to erase the last character of the entered
147 * PIN value. 160 * PIN value.
148 * @private 161 * @private
149 */ 162 */
150 onPinClear_: function() { 163 onPinClear_: function() {
151 this.value = this.value.substring(0, this.value.length - 1); 164 if (!this.hideInput) {
165 // If the input is shown check the location of the caret or the selected
166 // area to delete the correct character(s).
167 var selectionStart = this.$$('#pin-input').selectionStart;
168 var selectionEnd = this.$$('#pin-input').selectionEnd;
169 if (selectionStart == selectionEnd)
170 selectionStart--;
171 this.value = this.value.substring(0, selectionStart) +
172 this.value.substring(selectionEnd, this.value.length);
jdufault 2016/10/27 19:54:13 Needs indent
jdufault 2016/10/27 19:54:13 I believe you can change this.value.substring(sele
sammiequon 2016/10/27 22:00:20 Done.
sammiequon 2016/10/27 22:00:20 Done.
173 }
174 this.fire('pin-clear');
152 }, 175 },
153 176
154 /** 177 /**
155 * Called when the user presses or touches the backspace button. Starts a 178 * Called when the user presses or touches the backspace button. Starts a
156 * timer which starts an interval to repeatedly backspace the pin value until 179 * timer which starts an interval to repeatedly backspace the pin value until
157 * the interval is cleared. 180 * the interval is cleared.
158 * @param {Event} event The event object. 181 * @param {Event} event The event object.
159 * @private 182 * @private
160 */ 183 */
161 onBackspacePointerDown_: function(event) { 184 onBackspacePointerDown_: function(event) {
(...skipping 15 matching lines...) Expand all
177 }, 200 },
178 201
179 /** 202 /**
180 * Called when the user exits the backspace button. Stops the interval 203 * Called when the user exits the backspace button. Stops the interval
181 * callback. 204 * callback.
182 * @param {Event} event The event object. 205 * @param {Event} event The event object.
183 * @private 206 * @private
184 */ 207 */
185 onBackspacePointerOut_: function(event) { 208 onBackspacePointerOut_: function(event) {
186 this.clearAndReset_(); 209 this.clearAndReset_();
210
211 if (!event.target.receivedFocusFromKeyboard)
212 this.focus();
213 event.preventDefault();
187 }, 214 },
188 215
189 /** 216 /**
190 * Called when the user unpresses or untouches the backspace button. Stops the 217 * Called when the user unpresses or untouches the backspace button. Stops the
191 * interval callback and fires a backspace event if there is no interval 218 * interval callback and fires a backspace event if there is no interval
192 * running. 219 * running.
193 * @param {Event} event The event object. 220 * @param {Event} event The event object.
194 * @private 221 * @private
195 */ 222 */
196 onBackspacePointerUp_: function(event) { 223 onBackspacePointerUp_: function(event) {
197 // If an interval has started, do not fire event on pointer up. 224 // If an interval has started, do not fire event on pointer up.
198 if (!this.repeatBackspaceIntervalId_) 225 if (!this.repeatBackspaceIntervalId_)
199 this.onPinClear_(); 226 this.onPinClear_();
200 this.clearAndReset_(); 227 this.clearAndReset_();
228
229 if (!event.target.receivedFocusFromKeyboard)
230 this.focus();
231 event.preventDefault();
201 }, 232 },
202 233
203 /** Called when a key event is pressed while the input element has focus. */ 234 /** Called when a key event is pressed while the input element has focus. */
204 onInputKeyDown_: function(event) { 235 onInputKeyDown_: function(event) {
205 // Up/down pressed, swallow the event to prevent the input value from 236 // Up/down pressed, swallow the event to prevent the input value from
206 // being incremented or decremented. 237 // being incremented or decremented.
207 if (event.keyCode == 38 || event.keyCode == 40) { 238 if (event.keyCode == 38 || event.keyCode == 40) {
208 event.preventDefault(); 239 event.preventDefault();
209 return; 240 return;
210 } 241 }
211 242
212 // Enter pressed. 243 // Enter pressed.
213 if (event.keyCode == 13) { 244 if (event.keyCode == 13) {
214 this.firePinSubmitEvent_(); 245 this.firePinSubmitEvent_();
215 event.preventDefault(); 246 event.preventDefault();
216 return; 247 return;
217 } 248 }
249
250 // Do not pass events that are not numbers or special keys we care about. We
251 // use this instead of input type number because there are several issues
252 // with input type number, such as no selectionStart/selectionEnd and
253 // entered non numbers causes the caret to jump to the left.
254 var isUsableKey = (event.keyCode >= 48 && event.keyCode <= 57) ||
255 PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES.indexOf(event.keyCode) > -1;
256
257 if (!isUsableKey) {
258 event.preventDefault();
259 return;
260 }
218 }, 261 },
219 262
220 /** 263 /**
221 * Keypress does not handle backspace but handles the char codes nicely, so we
222 * have a seperate event to process the backspaces.
223 * @param {Event} event Keydown Event object.
224 * @private
225 */
226 onKeyDown_: function(event) {
227 // Backspace pressed.
228 if (event.keyCode == 8) {
229 this.onPinClear_();
230 event.preventDefault();
231 return;
232 }
233 },
234
235 /**
236 * Called when a key press event is fired while the number button is focused.
237 * Ideally we would want to pass focus back to the input element, but the we
238 * cannot or the virtual keyboard will keep poping up.
239 * @param {Event} event Keypress Event object.
240 * @private
241 */
242 onKeyPress_: function(event) {
243 // If the active element is the input element, the input element itself will
244 // handle the keypresses, so we do not handle them here.
245 if (this.shadowRoot.activeElement == this.inputElement)
246 return;
247
248 var code = event.keyCode;
249
250 // Enter pressed.
251 if (code == 13) {
252 this.firePinSubmitEvent_();
253 event.preventDefault();
254 return;
255 }
256
257 // Space pressed. We want the old polymer function of space activating the
258 // button with focus.
259 if (code == 32) {
260 // Check if target was a number button.
261 if (event.target.hasAttribute('value')) {
262 this.value += event.target.getAttribute('value');
263 return;
264 }
265 // Check if target was backspace button.
266 if (event.target.classList.contains('backspace-button')) {
267 this.onPinClear_();
268 return;
269 }
270 }
271
272 this.value += String.fromCharCode(code);
273 },
274
275 /**
276 * Disables the submit and backspace button if nothing is entered. 264 * Disables the submit and backspace button if nothing is entered.
277 * @param {string} value 265 * @param {string} value
278 * @private 266 * @private
279 */ 267 */
280 hasInput_: function(value) { 268 hasInput_: function(value) {
281 return value.length > 0; 269 return value.length > 0;
282 }, 270 },
283 271
284 /** 272 /**
285 * Computes whether the input type for the pin input should be password or
286 * numerical.
287 * @param {boolean} enablePassword
288 * @private
289 */
290 getInputType_: function(enablePassword) {
291 return enablePassword ? 'password' : 'number';
292 },
293
294 /**
295 * Computes the value of the pin input placeholder. 273 * Computes the value of the pin input placeholder.
296 * @param {boolean} enablePassword 274 * @param {boolean} enablePassword
297 * @private 275 * @private
298 */ 276 */
299 getInputPlaceholder_: function(enablePassword) { 277 getInputPlaceholder_: function(enablePassword) {
300 return enablePassword ? this.i18n('pinKeyboardPlaceholderPinPassword') : 278 return enablePassword ? this.i18n('pinKeyboardPlaceholderPinPassword') :
301 this.i18n('pinKeyboardPlaceholderPin'); 279 this.i18n('pinKeyboardPlaceholderPin');
302 }, 280 },
303 281
304 /** 282 /**
305 * Computes the direction of the pin input. 283 * Computes the direction of the pin input.
306 * @param {string} password 284 * @param {string} password
307 * @private 285 * @private
308 */ 286 */
309 isInputRtl_: function(password) { 287 isInputRtl_: function(password) {
310 // +password will convert a string to a number or to NaN if that's not 288 // +password will convert a string to a number or to NaN if that's not
311 // possible. Number.isInteger will verify the value is not a NaN and that it 289 // possible. Number.isInteger will verify the value is not a NaN and that it
312 // does not contain decimals. 290 // does not contain decimals.
313 // This heuristic will fail for inputs like '1.0'. 291 // This heuristic will fail for inputs like '1.0'.
314 // 292 //
315 // Since we still support users entering their passwords through the PIN 293 // Since we still support users entering their passwords through the PIN
316 // keyboard, we swap the input box to rtl when we think it is a password 294 // keyboard, we swap the input box to rtl when we think it is a password
317 // (just numbers), if the document direction is rtl. 295 // (just numbers), if the document direction is rtl.
318 return (document.dir == 'rtl') && !Number.isInteger(+password); 296 return (document.dir == 'rtl') && !Number.isInteger(+password);
319 }, 297 },
320 }); 298 });
321 })(); 299 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698