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

Unified 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 3 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
index d8b2762fb104855a57eb10cc72b4413c231f46ea..cbb0f164d2467b9cbefb58971df208b04159d755 100644
--- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
+++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
@@ -12,9 +12,9 @@
* the PIN keyboard's value.
*
* Events:
- * pin-change: Fired when the PIN value has changed. The pin is available at
+ * pin-change: Fired when the PIN value has changed. The PIN is available at
* event.detail.pin.
- * submit: Fired when the PIN is submitted. The pin is available at
+ * submit: Fired when the PIN is submitted. The PIN is available at
* event.detail.pin.
*
* Example:
@@ -40,6 +40,14 @@ var REPEAT_BACKSPACE_DELAY_MS = 150;
*/
var INITIAL_BACKSPACE_DELAY_MS = 500;
+/**
+ * The key codes of the keys allowed to be used on the pin input, in addition to
+ * number keys. Currently we allow backspace(8), tab(9), left(37) and right(39).
+ * @type {Array<number>}
+ * @const
+ */
+var PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES = [8, 9, 37, 39];
+
Polymer({
is: 'pin-keyboard',
@@ -51,6 +59,7 @@ Polymer({
/**
* Whether or not the keyboard's input element should be numerical
* or password.
+ * @private
*/
enablePassword: {
type: Boolean,
@@ -58,14 +67,9 @@ Polymer({
},
/**
- * Whether or not the keyboard's input should be shown.
+ * The value stored in the keyboard's input element.
+ * @private
*/
- hideInput: {
- type: Boolean,
- value: false
- },
-
- /** The value stored in the keyboard's input element. */
value: {
type: String,
notify: true,
@@ -74,6 +78,17 @@ Polymer({
},
/**
+ * The password element the pin keyboard is associated with.
jdufault 2016/11/02 19:06:45 I would extend this comment to also say that a def
sammiequon 2016/11/02 21:31:41 Done.
+ * @type {HTMLInputElement|undefined}
+ * @private
+ */
+ passwordElement: {
+ type: Object,
+ value: null,
+ observer: 'onPasswordElementAttached_'
+ },
+
+ /**
* The intervalID used for the backspace button set/clear interval.
* @private
*/
@@ -93,14 +108,22 @@ Polymer({
},
/**
- * @override
+ * Called when a password element is attached to the pin keyboard.
+ * @private
+ */
+ onPasswordElementAttached_: function() {
+ this.inputElement.addEventListener('input',
+ this.handleInputChanged_.bind(this));
+ },
+
+ /**
+ * Called when the user uses the keyboard to enter a value into the input
+ * element.
+ * @param {Event} event The event object.
+ * @private
*/
- attached: function() {
- // Remove the space/enter key binds from the polymer
- // iron-a11y-keys-behavior.
- var digitButtons = Polymer.dom(this.root).querySelectorAll('.digit-button');
- for (var i = 0; i < digitButtons.length; ++i)
- digitButtons[i].keyEventTarget = null;
+ handleInputChanged_: function(event) {
+ this.value = event.target.value;
},
/**
@@ -108,22 +131,55 @@ Polymer({
* @type {!HTMLInputElement}
*/
get inputElement() {
- return this.$$('#pin-input');
+ return this.passwordElement ? this.passwordElement : this.$$('#pin-input');
+ },
+
+ /**
+ * Gets the selection range of the input field.
+ * @type {Array<number>}
+ */
+ get selectionRange() {
+ return [this.inputElement.selectionStart, this.inputElement.selectionEnd];
+ },
+
+ /**
+ * Sets the selection range of the input field.
+ * @param {Array<number>} range The new range of the input element.
+ */
+ set selectionRange(range) {
+ this.inputElement.selectionStart = range[0];
+ this.inputElement.selectionEnd = range[1];
},
/** Transfers focus to the input element. */
focus: function() {
- this.$$('#pin-input').focus();
+ this.inputElement.focus();
},
/**
* Called when a keypad number has been tapped.
- * @param {!{target: !PaperButtonElement}} event
+ * @param {Event} event The event object.
* @private
*/
- onNumberTap_: function(event, detail) {
+ onNumberTap_: function(event) {
var numberValue = event.target.getAttribute('value');
- this.value += numberValue;
+
+ // Add the number where the caret is, then update the selection range of the
+ // input element.
+ this.value = this.value.substring(0, this.selectionRange[0]) + numberValue +
+ this.value.substring(this.selectionRange[1]);
+ this.selectionRange = [this.selectionRange[0] + 1,
+ this.selectionRange[0] == this.selectionRange[1] ?
jdufault 2016/11/02 19:06:45 Can this be simplified to this.selectionRange =
sammiequon 2016/11/02 21:31:41 Done.
+ this.selectionRange[1] + 1 :
+ this.selectionRange[0] + 1];
jdufault 2016/11/02 19:06:45 I think having separate selectionStart/selectionEn
sammiequon 2016/11/02 21:31:41 Done.
+
+ // If a number button is clicked, we do not want to switch focus to the
+ // button, therefore we transfer focus back to the input, but if a number
+ // button is tabbed into, it should keep focus, so users can use tab and
+ // spacebar/return to enter their PIN.
+ if (!event.target.receivedFocusFromKeyboard)
+ this.focus();
+ event.preventDefault();
},
/** Fires a submit event with the current PIN value. */
@@ -138,8 +194,15 @@ Polymer({
* @param {string} previous
*/
onPinValueChange_: function(value, previous) {
- if (value != previous)
+ if (value != previous) {
+ // The selection caret gets placed at the end after altering the
+ // password element, so we store the previous location(s) and reapply
+ // them after the the new value is set.
+ var selectionRange = this.selectionRange;
+ this.inputElement.value = this.value;
+ this.selectionRange = selectionRange;
this.fire('pin-change', { pin: value });
+ }
},
/**
@@ -148,7 +211,18 @@ Polymer({
* @private
*/
onPinClear_: function() {
- this.value = this.value.substring(0, this.value.length - 1);
+ // If the input is shown, clear the text based on the caret location or
+ // selected region of the input element.
+ var selectionRange = this.selectionRange;
+
+ // If it is just a caret, remove the character in front of the caret.
+ if (selectionRange[0] == selectionRange[1])
+ selectionRange[0]--;
+ this.value = this.value.substring(0, selectionRange[0]) +
+ this.value.substring(selectionRange[1]);
+
+ // Move the caret or selected region to the correct new place.
+ this.selectionRange = [selectionRange[0], selectionRange[0]];
},
/**
@@ -163,6 +237,10 @@ Polymer({
this.repeatBackspaceIntervalId_ = setInterval(
this.onPinClear_.bind(this), REPEAT_BACKSPACE_DELAY_MS);
}.bind(this), INITIAL_BACKSPACE_DELAY_MS);
+
+ if (!event.target.receivedFocusFromKeyboard)
+ this.focus();
+ event.preventDefault();
},
/**
@@ -184,6 +262,10 @@ Polymer({
*/
onBackspacePointerOut_: function(event) {
this.clearAndReset_();
+
+ if (!event.target.receivedFocusFromKeyboard)
+ this.focus();
+ event.preventDefault();
},
/**
@@ -198,9 +280,17 @@ Polymer({
if (!this.repeatBackspaceIntervalId_)
this.onPinClear_();
this.clearAndReset_();
+
+ if (!event.target.receivedFocusFromKeyboard)
+ this.focus();
+ event.preventDefault();
},
- /** Called when a key event is pressed while the input element has focus. */
+ /**
+ * Called when a key event is pressed while the input element has focus.
+ * @param {Event} event The event object.
+ * @private
+ */
onInputKeyDown_: function(event) {
// Up/down pressed, swallow the event to prevent the input value from
// being incremented or decremented.
@@ -215,65 +305,26 @@ Polymer({
event.preventDefault();
return;
}
- },
- /**
- * Keypress does not handle backspace but handles the char codes nicely, so we
- * have a seperate event to process the backspaces.
- * @param {Event} event Keydown Event object.
- * @private
- */
- onKeyDown_: function(event) {
- // Backspace pressed.
- if (event.keyCode == 8) {
- this.onPinClear_();
+ // Do not pass events that are not numbers or special keys we care about. We
+ // use this instead of input type number because there are several issues
+ // with input type number, such as no selectionStart/selectionEnd and
+ // entered non numbers causes the caret to jump to the left.
+ var isUsableKey = (event.keyCode >= 48 && event.keyCode <= 57) &&
jdufault 2016/11/02 19:06:45 I think this will be cleaner as a helper function.
sammiequon 2016/11/02 21:31:41 Done. Though I pass the event through to avoid too
+ !event.shiftKey;
+ isUsableKey = isUsableKey ||
+ PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES.indexOf(event.keyCode) > -1;
+ // Allow ctrl + a for users to quickly select the entire PIN.
+ isUsableKey = isUsableKey || (event.keyCode == 65 && event.ctrlKey);
+
+ if (!isUsableKey) {
event.preventDefault();
return;
}
},
/**
- * Called when a key press event is fired while the number button is focused.
- * Ideally we would want to pass focus back to the input element, but the we
- * cannot or the virtual keyboard will keep poping up.
- * @param {Event} event Keypress Event object.
- * @private
- */
- onKeyPress_: function(event) {
- // If the active element is the input element, the input element itself will
- // handle the keypresses, so we do not handle them here.
- if (this.shadowRoot.activeElement == this.inputElement)
- return;
-
- var code = event.keyCode;
-
- // Enter pressed.
- if (code == 13) {
- this.firePinSubmitEvent_();
- event.preventDefault();
- return;
- }
-
- // Space pressed. We want the old polymer function of space activating the
- // button with focus.
- if (code == 32) {
- // Check if target was a number button.
- if (event.target.hasAttribute('value')) {
- this.value += event.target.getAttribute('value');
- return;
- }
- // Check if target was backspace button.
- if (event.target.classList.contains('backspace-button')) {
- this.onPinClear_();
- return;
- }
- }
-
- this.value += String.fromCharCode(code);
- },
-
- /**
- * Disables the submit and backspace button if nothing is entered.
+ * Disables the backspace button if nothing is entered.
* @param {string} value
* @private
*/
@@ -282,16 +333,6 @@ Polymer({
},
/**
- * Computes whether the input type for the pin input should be password or
- * numerical.
- * @param {boolean} enablePassword
- * @private
- */
- getInputType_: function(enablePassword) {
- return enablePassword ? 'password' : 'number';
- },
-
- /**
* Computes the value of the pin input placeholder.
* @param {boolean} enablePassword
* @private

Powered by Google App Engine
This is Rietveld 408576698