Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 * submit: Fired when the PIN is submitted. The PIN is available at |
| 18 * event.detail.pin. | 18 * event.detail.pin. |
| 19 * | 19 * |
| 20 * Example: | 20 * Example: |
| 21 * <pin-keyboard on-pin-change="onPinChange" on-submit="onPinSubmit" | 21 * <pin-keyboard on-pin-change="onPinChange" on-submit="onPinSubmit"> |
| 22 * value="{{pinValue}}"> | |
| 23 * </pin-keyboard> | 22 * </pin-keyboard> |
| 24 */ | 23 */ |
| 25 | 24 |
| 26 (function() { | 25 (function() { |
| 27 | 26 |
| 28 /** | 27 /** |
| 29 * Once auto backspace starts, the time between individual backspaces. | 28 * Once auto backspace starts, the time between individual backspaces. |
| 30 * @type {number} | 29 * @type {number} |
| 31 * @const | 30 * @const |
| 32 */ | 31 */ |
| 33 var REPEAT_BACKSPACE_DELAY_MS = 150; | 32 var REPEAT_BACKSPACE_DELAY_MS = 150; |
| 34 | 33 |
| 35 /** | 34 /** |
| 36 * How long the backspace button must be held down before auto backspace | 35 * How long the backspace button must be held down before auto backspace |
| 37 * starts. | 36 * starts. |
| 38 * @type {number} | 37 * @type {number} |
| 39 * @const | 38 * @const |
| 40 */ | 39 */ |
| 41 var INITIAL_BACKSPACE_DELAY_MS = 500; | 40 var INITIAL_BACKSPACE_DELAY_MS = 500; |
| 42 | 41 |
| 42 /** | |
| 43 * The key codes of the keys allowed to be used on the pin input, in addition to | |
| 44 * number keys. Currently we allow backspace(8), tab(9), left(37) and right(39). | |
| 45 * @type {Array<number>} | |
| 46 * @const | |
| 47 */ | |
| 48 var PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES = [8, 9, 37, 39]; | |
| 49 | |
| 43 Polymer({ | 50 Polymer({ |
| 44 is: 'pin-keyboard', | 51 is: 'pin-keyboard', |
| 45 | 52 |
| 46 behaviors: [ | 53 behaviors: [ |
| 47 I18nBehavior, | 54 I18nBehavior, |
| 48 ], | 55 ], |
| 49 | 56 |
| 50 properties: { | 57 properties: { |
| 51 /** | 58 /** |
| 52 * Whether or not the keyboard's input element should be numerical | 59 * Whether or not the keyboard's input element should be numerical |
| 53 * or password. | 60 * or password. |
| 61 * @private | |
| 54 */ | 62 */ |
| 55 enablePassword: { | 63 enablePassword: { |
| 56 type: Boolean, | 64 type: Boolean, |
| 57 value: false | 65 value: false |
| 58 }, | 66 }, |
| 59 | 67 |
| 60 /** | 68 /** |
| 61 * Whether or not the keyboard's input should be shown. | 69 * The value stored in the keyboard's input element. |
| 70 * @private | |
| 62 */ | 71 */ |
| 63 hideInput: { | 72 value: { |
| 64 type: Boolean, | 73 type: String, |
| 65 value: false | 74 value: '', |
| 75 observer: 'onPinValueChange_' | |
| 66 }, | 76 }, |
| 67 | 77 |
| 68 /** The value stored in the keyboard's input element. */ | 78 /** |
| 69 value: { | 79 * The password element the pin keyboard is associated with. If this is not |
| 70 type: String, | 80 * set, then a default input element is shown and used. |
| 71 notify: true, | 81 * @type {HTMLInputElement|undefined} |
| 72 value: '', | 82 * @private |
| 73 observer: 'onPinValueChange_' | 83 */ |
| 84 passwordElement: { | |
| 85 type: Object, | |
| 86 value: null, | |
| 87 observer: 'onPasswordElementAttached_' | |
| 74 }, | 88 }, |
| 75 | 89 |
| 76 /** | 90 /** |
| 77 * The intervalID used for the backspace button set/clear interval. | 91 * The intervalID used for the backspace button set/clear interval. |
| 78 * @private | 92 * @private |
| 79 */ | 93 */ |
| 80 repeatBackspaceIntervalId_: { | 94 repeatBackspaceIntervalId_: { |
| 81 type: Number, | 95 type: Number, |
| 82 value: 0 | 96 value: 0 |
| 83 }, | 97 }, |
| 84 | 98 |
| 85 /** | 99 /** |
| 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 | 110 * Called when a password element is attached to the pin keyboard. |
| 111 * @private | |
| 97 */ | 112 */ |
| 98 attached: function() { | 113 onPasswordElementAttached_: function() { |
| 99 // Remove the space/enter key binds from the polymer | 114 this.inputElement.addEventListener('input', |
| 100 // iron-a11y-keys-behavior. | 115 this.handleInputChanged_.bind(this)); |
| 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 }, | 116 }, |
| 105 | 117 |
| 106 /** | 118 /** |
| 119 * Called when the user uses the keyboard to enter a value into the input | |
| 120 * element. | |
| 121 * @param {Event} event The event object. | |
| 122 * @private | |
| 123 */ | |
| 124 handleInputChanged_: function(event) { | |
| 125 this.value = event.target.value; | |
| 126 }, | |
| 127 | |
| 128 /** | |
| 107 * Gets the container holding the password field. | 129 * Gets the container holding the password field. |
| 108 * @type {!HTMLInputElement} | 130 * @type {!HTMLInputElement} |
| 109 */ | 131 */ |
| 110 get inputElement() { | 132 get inputElement() { |
|
jdufault
2016/11/02 22:23:16
What about using passwordElement directly?
In att
sammiequon
2016/11/03 00:26:33
Done.
| |
| 111 return this.$$('#pin-input'); | 133 return this.passwordElement ? this.passwordElement : this.$$('#pin-input'); |
| 134 }, | |
| 135 | |
| 136 /** | |
| 137 * Gets the selection start of the input field. | |
| 138 * @type {number} | |
| 139 */ | |
| 140 get selectionStart() { | |
|
jdufault
2016/11/02 22:23:17
Should these four methods be private?
sammiequon
2016/11/03 00:26:33
Done.
| |
| 141 return this.inputElement.selectionStart; | |
| 142 }, | |
| 143 | |
| 144 /** | |
| 145 * Gets the selection end of the input field. | |
| 146 * @type {number} | |
| 147 */ | |
| 148 get selectionEnd() { | |
| 149 return this.inputElement.selectionEnd; | |
| 150 }, | |
| 151 | |
| 152 /** | |
| 153 * Sets the selection start of the input field. | |
| 154 * @param {number} start The new selection start of the input element. | |
| 155 */ | |
| 156 set selectionStart(start) { | |
| 157 this.inputElement.selectionStart = start; | |
| 158 }, | |
| 159 | |
| 160 /** | |
| 161 * Sets the selection end of the input field. | |
| 162 * @param {number} end The new selection end of the input element. | |
| 163 */ | |
| 164 set selectionEnd(end) { | |
| 165 this.inputElement.selectionEnd = end; | |
| 112 }, | 166 }, |
| 113 | 167 |
| 114 /** Transfers focus to the input element. */ | 168 /** Transfers focus to the input element. */ |
| 115 focus: function() { | 169 focus: function() { |
| 116 this.$$('#pin-input').focus(); | 170 this.inputElement.focus(); |
| 117 }, | 171 }, |
| 118 | 172 |
| 119 /** | 173 /** |
| 120 * Called when a keypad number has been tapped. | 174 * Called when a keypad number has been tapped. |
| 121 * @param {!{target: !PaperButtonElement}} event | 175 * @param {Event} event The event object. |
| 122 * @private | 176 * @private |
| 123 */ | 177 */ |
| 124 onNumberTap_: function(event, detail) { | 178 onNumberTap_: function(event) { |
| 125 var numberValue = event.target.getAttribute('value'); | 179 var numberValue = event.target.getAttribute('value'); |
| 126 this.value += numberValue; | 180 |
| 181 // Add the number where the caret is, then update the selection range of the | |
| 182 // input element. | |
| 183 var selectionStart = this.selectionStart; | |
| 184 var selectionEnd = this.selectionEnd; | |
| 185 this.value = this.value.substring(0, selectionStart) + numberValue + | |
| 186 this.value.substring(selectionEnd); | |
| 187 this.selectionStart = selectionStart + 1; | |
| 188 this.selectionEnd = selectionStart + 1; | |
| 189 | |
| 190 // If a number button is clicked, we do not want to switch focus to the | |
| 191 // button, therefore we transfer focus back to the input, but if a number | |
| 192 // button is tabbed into, it should keep focus, so users can use tab and | |
| 193 // spacebar/return to enter their PIN. | |
| 194 if (!event.target.receivedFocusFromKeyboard) | |
| 195 this.focus(); | |
| 196 event.preventDefault(); | |
| 127 }, | 197 }, |
| 128 | 198 |
| 129 /** Fires a submit event with the current PIN value. */ | 199 /** Fires a submit event with the current PIN value. */ |
| 130 firePinSubmitEvent_: function() { | 200 firePinSubmitEvent_: function() { |
| 131 this.fire('submit', { pin: this.value }); | 201 this.fire('submit', { pin: this.value }); |
| 132 }, | 202 }, |
| 133 | 203 |
| 134 /** | 204 /** |
| 135 * Fires an update event with the current PIN value. The event will only be | 205 * Fires an update event with the current PIN value. The event will only be |
| 136 * fired if the PIN value has actually changed. | 206 * fired if the PIN value has actually changed. |
| 137 * @param {string} value | 207 * @param {string} value |
| 138 * @param {string} previous | 208 * @param {string} previous |
| 139 */ | 209 */ |
| 140 onPinValueChange_: function(value, previous) { | 210 onPinValueChange_: function(value, previous) { |
| 141 if (value != previous) | 211 if (value != previous) { |
| 212 // The selection caret gets placed at the end after altering the | |
| 213 // password element, so we store the previous location(s) and reapply | |
| 214 // them after the the new value is set. | |
| 215 var selectionStart = this.selectionStart; | |
| 216 var selectionEnd = this.selectionEnd; | |
| 217 this.inputElement.value = this.value; | |
| 218 this.selectionStart = selectionStart; | |
| 219 this.selectionEnd = selectionEnd; | |
| 142 this.fire('pin-change', { pin: value }); | 220 this.fire('pin-change', { pin: value }); |
| 221 } | |
| 143 }, | 222 }, |
| 144 | 223 |
| 145 /** | 224 /** |
| 146 * Called when the user wants to erase the last character of the entered | 225 * Called when the user wants to erase the last character of the entered |
| 147 * PIN value. | 226 * PIN value. |
| 148 * @private | 227 * @private |
| 149 */ | 228 */ |
| 150 onPinClear_: function() { | 229 onPinClear_: function() { |
| 151 this.value = this.value.substring(0, this.value.length - 1); | 230 // If the input is shown, clear the text based on the caret location or |
| 231 // selected region of the input element. | |
| 232 var selectionStart = this.selectionStart; | |
| 233 var selectionEnd = this.selectionEnd; | |
| 234 | |
| 235 // If it is just a caret, remove the character in front of the caret. | |
| 236 if (selectionStart == selectionEnd) | |
| 237 selectionStart--; | |
| 238 this.value = this.value.substring(0, selectionStart) + | |
| 239 this.value.substring(selectionEnd); | |
| 240 | |
| 241 // Move the caret or selected region to the correct new place. | |
| 242 this.selectionStart = selectionStart; | |
| 243 this.selectionEnd = selectionStart; | |
| 152 }, | 244 }, |
| 153 | 245 |
| 154 /** | 246 /** |
| 155 * Called when the user presses or touches the backspace button. Starts a | 247 * 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 | 248 * timer which starts an interval to repeatedly backspace the pin value until |
| 157 * the interval is cleared. | 249 * the interval is cleared. |
| 158 * @param {Event} event The event object. | 250 * @param {Event} event The event object. |
| 159 * @private | 251 * @private |
| 160 */ | 252 */ |
| 161 onBackspacePointerDown_: function(event) { | 253 onBackspacePointerDown_: function(event) { |
| 162 this.startAutoBackspaceId_ = setTimeout(function() { | 254 this.startAutoBackspaceId_ = setTimeout(function() { |
| 163 this.repeatBackspaceIntervalId_ = setInterval( | 255 this.repeatBackspaceIntervalId_ = setInterval( |
| 164 this.onPinClear_.bind(this), REPEAT_BACKSPACE_DELAY_MS); | 256 this.onPinClear_.bind(this), REPEAT_BACKSPACE_DELAY_MS); |
| 165 }.bind(this), INITIAL_BACKSPACE_DELAY_MS); | 257 }.bind(this), INITIAL_BACKSPACE_DELAY_MS); |
| 258 | |
| 259 if (!event.target.receivedFocusFromKeyboard) | |
| 260 this.focus(); | |
| 261 event.preventDefault(); | |
| 166 }, | 262 }, |
| 167 | 263 |
| 168 /** | 264 /** |
| 169 * Helper function which clears the timer / interval ids and resets them. | 265 * Helper function which clears the timer / interval ids and resets them. |
| 170 * @private | 266 * @private |
| 171 */ | 267 */ |
| 172 clearAndReset_: function() { | 268 clearAndReset_: function() { |
| 173 clearInterval(this.repeatBackspaceIntervalId_); | 269 clearInterval(this.repeatBackspaceIntervalId_); |
| 174 this.repeatBackspaceIntervalId_ = 0; | 270 this.repeatBackspaceIntervalId_ = 0; |
| 175 clearTimeout(this.startAutoBackspaceId_); | 271 clearTimeout(this.startAutoBackspaceId_); |
| 176 this.startAutoBackspaceId_ = 0; | 272 this.startAutoBackspaceId_ = 0; |
| 177 }, | 273 }, |
| 178 | 274 |
| 179 /** | 275 /** |
| 180 * Called when the user exits the backspace button. Stops the interval | 276 * Called when the user exits the backspace button. Stops the interval |
| 181 * callback. | 277 * callback. |
| 182 * @param {Event} event The event object. | 278 * @param {Event} event The event object. |
| 183 * @private | 279 * @private |
| 184 */ | 280 */ |
| 185 onBackspacePointerOut_: function(event) { | 281 onBackspacePointerOut_: function(event) { |
| 186 this.clearAndReset_(); | 282 this.clearAndReset_(); |
| 283 | |
| 284 if (!event.target.receivedFocusFromKeyboard) | |
| 285 this.focus(); | |
| 286 event.preventDefault(); | |
| 187 }, | 287 }, |
| 188 | 288 |
| 189 /** | 289 /** |
| 190 * Called when the user unpresses or untouches the backspace button. Stops the | 290 * 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 | 291 * interval callback and fires a backspace event if there is no interval |
| 192 * running. | 292 * running. |
| 193 * @param {Event} event The event object. | 293 * @param {Event} event The event object. |
| 194 * @private | 294 * @private |
| 195 */ | 295 */ |
| 196 onBackspacePointerUp_: function(event) { | 296 onBackspacePointerUp_: function(event) { |
| 197 // If an interval has started, do not fire event on pointer up. | 297 // If an interval has started, do not fire event on pointer up. |
| 198 if (!this.repeatBackspaceIntervalId_) | 298 if (!this.repeatBackspaceIntervalId_) |
| 199 this.onPinClear_(); | 299 this.onPinClear_(); |
| 200 this.clearAndReset_(); | 300 this.clearAndReset_(); |
| 301 | |
| 302 if (!event.target.receivedFocusFromKeyboard) | |
| 303 this.focus(); | |
| 304 event.preventDefault(); | |
| 201 }, | 305 }, |
| 202 | 306 |
| 203 /** Called when a key event is pressed while the input element has focus. */ | 307 /** |
| 308 * Helper function to check whether a given |event| should be processed by | |
| 309 * the numeric only input. | |
| 310 * @param {Event} event The event object. | |
| 311 * @private | |
| 312 */ | |
| 313 isValidKeyForInput_: function(event) { | |
|
jdufault
2016/11/02 22:23:16
Since this is taking an event instead of a keyCode
sammiequon
2016/11/03 00:26:33
Done.
| |
| 314 // Valid if the key is a number, and shift is not pressed. | |
| 315 if ((event.keyCode >= 48 && event.keyCode <= 57) && !event.shiftKey) | |
| 316 return true; | |
| 317 | |
| 318 // Valid if the key is one of the selected special keys defined in | |
| 319 // |PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES|. | |
| 320 if (PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES.indexOf(event.keyCode) > -1) | |
| 321 return true; | |
| 322 | |
| 323 // Valid if a is pressed while the control key is pressed to allow users to | |
| 324 // quickly select the entire PIN. | |
| 325 if (event.keyCode == 65 && event.ctrlKey) | |
| 326 return true; | |
| 327 | |
| 328 // The rest of the keys are invalid. | |
| 329 return false; | |
| 330 }, | |
| 331 | |
| 332 /** | |
| 333 * Called when a key event is pressed while the input element has focus. | |
| 334 * @param {Event} event The event object. | |
| 335 * @private | |
| 336 */ | |
| 204 onInputKeyDown_: function(event) { | 337 onInputKeyDown_: function(event) { |
| 205 // Up/down pressed, swallow the event to prevent the input value from | 338 // Up/down pressed, swallow the event to prevent the input value from |
| 206 // being incremented or decremented. | 339 // being incremented or decremented. |
| 207 if (event.keyCode == 38 || event.keyCode == 40) { | 340 if (event.keyCode == 38 || event.keyCode == 40) { |
| 208 event.preventDefault(); | 341 event.preventDefault(); |
| 209 return; | 342 return; |
| 210 } | 343 } |
| 211 | 344 |
| 212 // Enter pressed. | 345 // Enter pressed. |
| 213 if (event.keyCode == 13) { | 346 if (event.keyCode == 13) { |
| 214 this.firePinSubmitEvent_(); | 347 this.firePinSubmitEvent_(); |
| 215 event.preventDefault(); | 348 event.preventDefault(); |
| 216 return; | 349 return; |
| 217 } | 350 } |
| 218 }, | |
| 219 | 351 |
| 220 /** | 352 // Do not pass events that are not numbers or special keys we care about. We |
| 221 * Keypress does not handle backspace but handles the char codes nicely, so we | 353 // use this instead of input type number because there are several issues |
| 222 * have a seperate event to process the backspaces. | 354 // with input type number, such as no selectionStart/selectionEnd and |
| 223 * @param {Event} event Keydown Event object. | 355 // entered non numbers causes the caret to jump to the left. |
| 224 * @private | 356 if (!isValidKeyForInput_(event)) { |
|
jdufault
2016/11/02 22:23:16
This seems like it should be throwing errors?
thi
sammiequon
2016/11/03 00:26:33
Thanks. It just lets everything through so I didn'
| |
| 225 */ | |
| 226 onKeyDown_: function(event) { | |
| 227 // Backspace pressed. | |
| 228 if (event.keyCode == 8) { | |
| 229 this.onPinClear_(); | |
| 230 event.preventDefault(); | 357 event.preventDefault(); |
| 231 return; | 358 return; |
| 232 } | 359 } |
| 233 }, | 360 }, |
| 234 | 361 |
| 235 /** | 362 /** |
| 236 * Called when a key press event is fired while the number button is focused. | 363 * Disables the backspace button if nothing is entered. |
| 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. | |
| 277 * @param {string} value | 364 * @param {string} value |
| 278 * @private | 365 * @private |
| 279 */ | 366 */ |
| 280 hasInput_: function(value) { | 367 hasInput_: function(value) { |
| 281 return value.length > 0; | 368 return value.length > 0; |
| 282 }, | 369 }, |
| 283 | 370 |
| 284 /** | 371 /** |
| 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. | 372 * Computes the value of the pin input placeholder. |
| 296 * @param {boolean} enablePassword | 373 * @param {boolean} enablePassword |
| 297 * @private | 374 * @private |
| 298 */ | 375 */ |
| 299 getInputPlaceholder_: function(enablePassword) { | 376 getInputPlaceholder_: function(enablePassword) { |
| 300 return enablePassword ? this.i18n('pinKeyboardPlaceholderPinPassword') : | 377 return enablePassword ? this.i18n('pinKeyboardPlaceholderPinPassword') : |
| 301 this.i18n('pinKeyboardPlaceholderPin'); | 378 this.i18n('pinKeyboardPlaceholderPin'); |
| 302 }, | 379 }, |
| 303 | 380 |
| 304 /** | 381 /** |
| 305 * Computes the direction of the pin input. | 382 * Computes the direction of the pin input. |
| 306 * @param {string} password | 383 * @param {string} password |
| 307 * @private | 384 * @private |
| 308 */ | 385 */ |
| 309 isInputRtl_: function(password) { | 386 isInputRtl_: function(password) { |
| 310 // +password will convert a string to a number or to NaN if that's not | 387 // +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 | 388 // possible. Number.isInteger will verify the value is not a NaN and that it |
| 312 // does not contain decimals. | 389 // does not contain decimals. |
| 313 // This heuristic will fail for inputs like '1.0'. | 390 // This heuristic will fail for inputs like '1.0'. |
| 314 // | 391 // |
| 315 // Since we still support users entering their passwords through the PIN | 392 // 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 | 393 // keyboard, we swap the input box to rtl when we think it is a password |
| 317 // (just numbers), if the document direction is rtl. | 394 // (just numbers), if the document direction is rtl. |
| 318 return (document.dir == 'rtl') && !Number.isInteger(+password); | 395 return (document.dir == 'rtl') && !Number.isInteger(+password); |
| 319 }, | 396 }, |
| 320 }); | 397 }); |
| 321 })(); | 398 })(); |
| OLD | NEW |