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

Unified Diff: chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.js

Issue 2874303003: Fork PIN keyboard assets and create additional flag for lock screen (Closed)
Patch Set: Created 3 years, 7 months 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/md_pin_keyboard.js
diff --git a/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.js b/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.js
new file mode 100644
index 0000000000000000000000000000000000000000..d3740c76c39c4fdc94efc0eeaef7bc46903561c7
--- /dev/null
+++ b/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.js
@@ -0,0 +1,400 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'pin-keyboard' is a keyboard that can be used to enter PINs or more generally
+ * numeric values.
+ *
+ * Properties:
+ * value: The value of the PIN keyboard. Writing to this property will adjust
+ * the PIN keyboard's value.
+ *
+ * Events:
+ * 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
+ * event.detail.pin.
+ *
+ * Example:
+ * <pin-keyboard on-pin-change="onPinChange" on-submit="onPinSubmit">
+ * </pin-keyboard>
+ */
+
+(function() {
+
+/**
+ * Once auto backspace starts, the time between individual backspaces.
+ * @type {number}
+ * @const
+ */
+var REPEAT_BACKSPACE_DELAY_MS = 150;
+
+/**
+ * How long the backspace button must be held down before auto backspace
+ * starts.
+ * @type {number}
+ * @const
+ */
+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',
+
+ behaviors: [
+ I18nBehavior,
+ ],
+
+ properties: {
+ /**
+ * Whether or not the keyboard's input element should be numerical
+ * or password.
+ * @private
+ */
+ enablePassword: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * The password element the pin keyboard is associated with. If this is not
+ * set, then a default input element is shown and used.
+ * @type {?Element}
+ * @private
+ */
+ passwordElement: {
+ type: Object,
+ value: function() {
+ return this.$.pinInput.inputElement;
+ },
+ observer: 'onPasswordElementAttached_',
+ },
+
+ /**
+ * The intervalID used for the backspace button set/clear interval.
+ * @private
+ */
+ repeatBackspaceIntervalId_: {
+ type: Number,
+ value: 0,
+ },
+
+ /**
+ * The timeoutID used for the auto backspace.
+ * @private
+ */
+ startAutoBackspaceId_: {
+ type: Number,
+ value: 0,
+ },
+
+ /**
+ * Whether or not to show the default pin input.
+ * @private
+ */
+ showPinInput_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * The value stored in the keyboard's input element.
+ * @private
+ */
+ value: {
+ type: String,
+ notify: true,
+ value: '',
+ observer: 'onPinValueChange_',
+ },
+ },
+
+ /**
+ * Called when a password element is attached to the pin keyboard.
+ * @param {HTMLInputElement} inputElement The PIN keyboard's input element.
+ * @private
+ */
+ onPasswordElementAttached_: function(inputElement) {
+ this.showPinInput_ = inputElement == this.$.pinInput.inputElement;
+ 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
+ */
+ handleInputChanged_: function(event) {
+ this.value = event.target.value;
+ },
+
+ /**
+ * Gets the selection start of the input field.
+ * @type {number}
+ * @private
+ */
+ get selectionStart_() {
+ return this.passwordElement.selectionStart;
+ },
+
+ /**
+ * Gets the selection end of the input field.
+ * @type {number}
+ * @private
+ */
+ get selectionEnd_() {
+ return this.passwordElement.selectionEnd;
+ },
+
+ /**
+ * Sets the selection start of the input field.
+ * @param {number} start The new selection start of the input element.
+ * @private
+ */
+ set selectionStart_(start) {
+ this.passwordElement.selectionStart = start;
+ },
+
+ /**
+ * Sets the selection end of the input field.
+ * @param {number} end The new selection end of the input element.
+ * @private
+ */
+ set selectionEnd_(end) {
+ this.passwordElement.selectionEnd = end;
+ },
+
+ /** Transfers focus to the input element. */
+ focus: function() {
+ this.passwordElement.focus();
+ },
+
+ /**
+ * Called when a keypad number has been tapped.
+ * @param {Event} event The event object.
+ * @private
+ */
+ onNumberTap_: function(event) {
+ var numberValue = event.target.getAttribute('value');
+
+ // Add the number where the caret is, then update the selection range of the
+ // input element.
+ var selectionStart = this.selectionStart_;
+ this.value = this.value.substring(0, this.selectionStart_) + numberValue +
+ this.value.substring(this.selectionEnd_);
+ this.selectionStart_ = selectionStart + 1;
+ this.selectionEnd_ = this.selectionStart_;
+
+ // 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. */
+ firePinSubmitEvent_: function() {
+ this.fire('submit', { pin: this.value });
+ },
+
+ /**
+ * Fires an update event with the current PIN value. The event will only be
+ * fired if the PIN value has actually changed.
+ * @param {string} value
+ * @param {string} previous
+ */
+ onPinValueChange_: function(value, previous) {
+ if (value != previous) {
+ this.passwordElement.value = this.value;
+ this.fire('pin-change', { pin: value });
+ }
+ },
+
+ /**
+ * Called when the user wants to erase the last character of the entered
+ * PIN value.
+ * @private
+ */
+ onPinClear_: function() {
+ // If the input is shown, clear the text based on the caret location or
+ // selected region of the input element. If it is just a caret, remove the
+ // character in front of the caret.
+ var selectionStart = this.selectionStart_;
+ var selectionEnd = this.selectionEnd_;
+ if (selectionStart == selectionEnd)
+ selectionStart--;
+
+ this.value = this.value.substring(0, selectionStart) +
+ this.value.substring(selectionEnd);
+
+ // Move the caret or selected region to the correct new place.
+ this.selectionStart_ = selectionStart;
+ this.selectionEnd_ = selectionStart;
+ },
+
+ /**
+ * Called when the user presses or touches the backspace button. Starts a
+ * timer which starts an interval to repeatedly backspace the pin value until
+ * the interval is cleared.
+ * @param {Event} event The event object.
+ * @private
+ */
+ onBackspacePointerDown_: function(event) {
+ this.startAutoBackspaceId_ = setTimeout(function() {
+ 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();
+ },
+
+ /**
+ * Helper function which clears the timer / interval ids and resets them.
+ * @private
+ */
+ clearAndReset_: function() {
+ clearInterval(this.repeatBackspaceIntervalId_);
+ this.repeatBackspaceIntervalId_ = 0;
+ clearTimeout(this.startAutoBackspaceId_);
+ this.startAutoBackspaceId_ = 0;
+ },
+
+ /**
+ * Called when the user exits the backspace button. Stops the interval
+ * callback.
+ * @param {Event} event The event object.
+ * @private
+ */
+ onBackspacePointerOut_: function(event) {
+ this.clearAndReset_();
+
+ if (!event.target.receivedFocusFromKeyboard)
+ this.focus();
+ event.preventDefault();
+ },
+
+ /**
+ * Called when the user unpresses or untouches the backspace button. Stops the
+ * interval callback and fires a backspace event if there is no interval
+ * running.
+ * @param {Event} event The event object.
+ * @private
+ */
+ onBackspacePointerUp_: function(event) {
+ // If an interval has started, do not fire event on pointer up.
+ if (!this.repeatBackspaceIntervalId_)
+ this.onPinClear_();
+ this.clearAndReset_();
+
+ if (!event.target.receivedFocusFromKeyboard)
+ this.focus();
+ event.preventDefault();
+ },
+
+ /**
+ * Helper function to check whether a given |event| should be processed by
+ * the numeric only input.
+ * @param {Event} event The event object.
+ * @private
+ */
+ isValidEventForInput_: function(event) {
+ // Valid if the key is a number, and shift is not pressed.
+ if ((event.keyCode >= 48 && event.keyCode <= 57) && !event.shiftKey)
+ return true;
+
+ // Valid if the key is one of the selected special keys defined in
+ // |PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES|.
+ if (PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES.indexOf(event.keyCode) > -1)
+ return true;
+
+ // Valid if the key is CTRL+A to allow users to quickly select the entire
+ // PIN.
+ if (event.keyCode == 65 && event.ctrlKey)
+ return true;
+
+ // The rest of the keys are invalid.
+ return false;
+ },
+
+ /**
+ * 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.
+ if (event.keyCode == 38 || event.keyCode == 40) {
+ event.preventDefault();
+ return;
+ }
+
+ // Enter pressed.
+ if (event.keyCode == 13) {
+ this.firePinSubmitEvent_();
+ event.preventDefault();
+ return;
+ }
+
+ // 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.
+ if (!this.isValidEventForInput_(event)) {
+ event.preventDefault();
+ return;
+ }
+ },
+
+ /**
+ * Disables the backspace button if nothing is entered.
+ * @param {string} value
+ * @private
+ */
+ hasInput_: function(value) {
+ return value.length > 0;
+ },
+
+ /**
+ * Computes the value of the pin input placeholder.
+ * @param {boolean} enablePassword
+ * @private
+ */
+ getInputPlaceholder_: function(enablePassword) {
+ return enablePassword ? this.i18n('pinKeyboardPlaceholderPinPassword') :
+ this.i18n('pinKeyboardPlaceholderPin');
+ },
+
+ /**
+ * Computes the direction of the pin input.
+ * @param {string} password
+ * @private
+ */
+ isInputRtl_: function(password) {
+ // +password will convert a string to a number or to NaN if that's not
+ // possible. Number.isInteger will verify the value is not a NaN and that it
+ // does not contain decimals.
+ // This heuristic will fail for inputs like '1.0'.
+ //
+ // Since we still support users entering their passwords through the PIN
+ // keyboard, we swap the input box to rtl when we think it is a password
+ // (just numbers), if the document direction is rtl.
+ return (document.dir == 'rtl') && !Number.isInteger(+password);
+ },
+});
+})();

Powered by Google App Engine
This is Rietveld 408576698