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

Unified Diff: chrome/browser/resources/options2/editable_text_field.js

Issue 10827283: This updates the StaticIP configuration UI to match new mocks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix unit test Created 8 years, 4 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/options2/editable_text_field.js
diff --git a/chrome/browser/resources/options2/editable_text_field.js b/chrome/browser/resources/options2/editable_text_field.js
new file mode 100644
index 0000000000000000000000000000000000000000..7f578b4e4a89216dc2193a1071886703991eb656
--- /dev/null
+++ b/chrome/browser/resources/options2/editable_text_field.js
@@ -0,0 +1,375 @@
+// Copyright (c) 2012 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.
+
+cr.define('options', function() {
+ var EditableTextField = cr.ui.define('div');
+
+ /**
+ * Decorates an element as an editable text field.
+ * @param {!HTMLElement} el The element to decorate.
+ */
+ EditableTextField.decorate = function(el) {
+ el.__proto__ = EditableTextField.prototype;
+ el.decorate();
+ };
+
+ EditableTextField.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ /**
+ * The actual input element in this field.
+ * @type {?HTMLElement}
+ * @private
+ */
+ editField_: null,
+
+ /**
+ * The static text displayed when this field isn't editable.
+ * @type {?HTMLElement}
+ * @private
+ */
+ staticText_: null,
+
+ /**
+ * The data model for this field.
+ * @type {?Object}
+ * @private
+ */
+ model_: null,
+
+ /**
+ * Whether or not the current edit should be considered canceled, rather
+ * than committed, when editing ends.
+ * @type {boolean}
+ * @private
+ */
+ editCanceled_: true,
+
+ /** @inheritDoc */
+ decorate: function() {
+ this.classList.add('editable-text-field');
+
+ this.createEditableTextCell();
+
+ if (this.hasAttribute('i18n-placeholder-text')) {
+ var identifier = this.getAttribute('i18n-placeholder-text');
+ var localizedText = loadTimeData.getString(identifier);
+ if (localizedText)
+ this.setAttribute('placeholder-text', localizedText);
+ }
+
+ this.addEventListener('keydown', this.handleKeyDown_);
+ this.editField_.addEventListener('focus', this.handleFocus_.bind(this));
+ this.editField_.addEventListener('blur', this.handleBlur_.bind(this));
+ this.checkForEmpty_();
+ },
+
+ /**
+ * Indicates that this field has no value in the model, and the placeholder
+ * text (if any) should be shown.
+ * @type {boolean}
+ */
+ get empty() {
+ return this.hasAttribute('empty');
+ },
+
+ /**
+ * The placeholder text to be used when the model or its value is empty.
+ * @type {string}
+ */
+ get placeholderText() {
+ return this.getAttribute('placeholder-text');
+ },
+ set placeholderText(text) {
+ if (text)
+ this.setAttribute('placeholder-text', text);
+ else
+ this.removeAttribute('placeholder-text');
+
+ this.checkForEmpty_();
+ },
+
+ /**
+ * Returns the input element in this text field.
+ * @type {HTMLElement} The element that is the actual input field.
+ */
+ get editField() {
+ return this.editField_;
+ },
+
+ /**
+ * Whether the user is currently editing the list item.
+ * @type {boolean}
+ */
+ get editing() {
+ return this.hasAttribute('editing');
+ },
+ set editing(editing) {
+ if (this.editing == editing)
+ return;
+
+ if (editing)
+ this.setAttribute('editing', '');
+ else
+ this.removeAttribute('editing');
+
+ if (editing) {
+ this.editCanceled_ = false;
+
+ if (this.empty) {
+ this.removeAttribute('empty');
+ if (this.editField)
+ this.editField.value = '';
+ }
+ if (this.editField) {
+ this.editField.focus();
+ this.editField.select();
+ }
+ } else {
+ if (!this.editCanceled_ && this.hasBeenEdited &&
+ this.currentInputIsValid) {
+ this.updateStaticValues_();
+ cr.dispatchSimpleEvent(this, 'commitedit', true);
+ } else {
+ this.resetEditableValues_();
+ cr.dispatchSimpleEvent(this, 'canceledit', true);
+ }
+ this.checkForEmpty_();
+ }
+ },
+
+ /**
+ * Whether the item is editable.
+ * @type {boolean}
+ */
+ get editable() {
+ return this.hasAttribute('editable');
+ },
+ set editable(editable) {
+ if (this.editable == editable)
+ return;
+
+ if (editable)
+ this.setAttribute('editable', '');
+ else
+ this.removeAttribute('editable');
+ this.editable_ = editable;
+ },
+
+ /**
+ * The data model for this field.
+ * @type {Object}
+ */
+ get model() {
+ return this.model_;
+ },
+ set model(model) {
+ this.model_ = model;
+ this.checkForEmpty_(); // This also updates the editField value.
+ this.updateStaticValues_();
+ },
+
+ /**
+ * The HTML element that should have focus initially when editing starts,
+ * if a specific element wasn't clicked. Defaults to the first <input>
+ * element; can be overridden by subclasses if a different element should be
+ * focused.
+ * @type {?HTMLElement}
+ */
+ get initialFocusElement() {
+ return this.querySelector('input');
+ },
+
+ /**
+ * Whether the input in currently valid to submit. If this returns false
+ * when editing would be submitted, either editing will not be ended,
+ * or it will be cancelled, depending on the context. Can be overridden by
+ * subclasses to perform input validation.
+ * @type {boolean}
+ */
+ get currentInputIsValid() {
+ return true;
+ },
+
+ /**
+ * Returns true if the item has been changed by an edit. Can be overridden
+ * by subclasses to return false when nothing has changed to avoid
+ * unnecessary commits.
+ * @type {boolean}
+ */
+ get hasBeenEdited() {
+ return true;
+ },
+
+ /**
+ * Mutates the input during a successful commit. Can be overridden to
+ * provide a way to "clean up" valid input so that it conforms to a
+ * desired format. Will only be called when commit succeeds for valid
+ * input, or when the model is set.
+ * @param {string} value Input text to be mutated.
+ * @return {string} mutated text.
+ */
+ mutateInput: function(value) {
+ return value;
+ },
+
+ /**
+ * Creates a div containing an <input>, as well as static text, keeping
+ * references to them so they can be manipulated.
+ * @param {string} text The text of the cell.
+ * @private
+ */
+ createEditableTextCell: function(text) {
+ // This function should only be called once.
+ if (this.editField_)
+ return;
+
+ var container = this.ownerDocument.createElement('div');
+
+ var textEl = this.ownerDocument.createElement('div');
+ textEl.className = 'static-text';
+ textEl.textContent = text;
+ textEl.setAttribute('displaymode', 'static');
+ this.appendChild(textEl);
+ this.staticText_ = textEl;
+
+ var inputEl = this.ownerDocument.createElement('input');
+ inputEl.className = 'editable-text';
+ inputEl.type = 'text';
+ inputEl.value = text;
+ inputEl.setAttribute('displaymode', 'edit');
+ inputEl.staticVersion = textEl;
+ this.appendChild(inputEl);
+ this.editField_ = inputEl;
+ },
+
+ /**
+ * Resets the editable version of any controls created by
+ * createEditableTextCell to match the static text.
+ * @private
+ */
+ resetEditableValues_: function() {
+ var editField = this.editField_;
+ var staticLabel = editField.staticVersion;
+ if (!staticLabel)
+ return;
+
+ if (editField instanceof HTMLInputElement)
+ editField.value = staticLabel.textContent;
+
+ editField.setCustomValidity('');
+ },
+
+ /**
+ * Sets the static version of any controls created by createEditableTextCell
+ * to match the current value of the editable version. Called on commit so
+ * that there's no flicker of the old value before the model updates. Also
+ * updates the model's value with the mutated value of the edit field.
+ * @private
+ */
+ updateStaticValues_: function() {
+ var editField = this.editField_;
+ var staticLabel = editField.staticVersion;
+ if (!staticLabel)
+ return;
+
+ if (editField instanceof HTMLInputElement) {
+ staticLabel.textContent = editField.value;
+ this.model_.value = this.mutateInput(editField.value);
+ }
+ },
+
+ /**
+ * Checks to see if the model or its value are empty. If they are, then set
+ * the edit field to the placeholder text, if any, and if not, set it to the
+ * model's value.
+ * @private
+ */
+ checkForEmpty_: function() {
+ var editField = this.editField_;
+ if (!editField)
+ return;
+
+ if (!this.model_ || !this.model_.value) {
+ this.setAttribute('empty', '');
+ editField.value = this.placeholderText || '';
+ } else {
+ this.removeAttribute('empty');
+ editField.value = this.model_.value;
+ }
+ },
+
+ /**
+ * Called when this widget receives focus.
+ * @param {Event} e the focus event.
+ * @private
+ */
+ handleFocus_: function(e) {
+ if (this.editing)
+ return;
+
+ this.editing = true;
+ if (this.editField_)
+ this.editField_.focus();
+ },
+
+ /**
+ * Called when this widget loses focus.
+ * @param {Event} e the blur event.
+ * @private
+ */
+ handleBlur_: function(e) {
+ if (!this.editing)
+ return;
+
+ this.editing = false;
+ },
+
+ /**
+ * Called when a key is pressed. Handles committing and canceling edits.
+ * @param {Event} e The key down event.
+ * @private
+ */
+ handleKeyDown_: function(e) {
+ if (!this.editing)
+ return;
+
+ var endEdit;
+ switch (e.keyIdentifier) {
+ case 'U+001B': // Esc
+ this.editCanceled_ = true;
+ endEdit = true;
+ break;
+ case 'Enter':
+ if (this.currentInputIsValid)
+ endEdit = true;
+ break;
+ }
+
+ if (endEdit) {
+ // Blurring will trigger the edit to end.
+ this.ownerDocument.activeElement.blur();
+ // Make sure that handled keys aren't passed on and double-handled.
+ // (e.g., esc shouldn't both cancel an edit and close a subpage)
+ e.stopPropagation();
+ }
+ },
+ };
+
+ /**
+ * Takes care of committing changes to EditableTextField items when the
+ * window loses focus.
+ */
+ window.addEventListener('blur', function(e) {
+ var itemAncestor = findAncestor(document.activeElement, function(node) {
+ return node instanceof EditableTextField;
+ });
+ if (itemAncestor)
+ document.activeElement.blur();
+ });
+
+ return {
+ EditableTextField: EditableTextField,
+ };
+});

Powered by Google App Engine
This is Rietveld 408576698