 Chromium Code Reviews
 Chromium Code Reviews Issue 6151004:
  DOMUI Prefs: Replace search engine edit overlay with inline editing.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 6151004:
  DOMUI Prefs: Replace search engine edit overlay with inline editing.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| Index: chrome/browser/resources/options/inline_editable_list.js | 
| diff --git a/chrome/browser/resources/options/inline_editable_list.js b/chrome/browser/resources/options/inline_editable_list.js | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..bc4996bebd448487c0ffc4b4e2c2d761dc230c19 | 
| --- /dev/null | 
| +++ b/chrome/browser/resources/options/inline_editable_list.js | 
| @@ -0,0 +1,237 @@ | 
| +// Copyright (c) 2010 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() { | 
| + const DeletableItem = options.DeletableItem; | 
| + const DeletableItemList = options.DeletableItemList; | 
| + | 
| + /** | 
| + * Creates a new list item with support for inline editing. | 
| + * @constructor | 
| + * @extends {options.DeletableListItem} | 
| + */ | 
| + function InlineEditableItem() { | 
| + var el = cr.doc.createElement('div'); | 
| + InlineEditableItem.decorate(el); | 
| + return el; | 
| + } | 
| + | 
| + /** | 
| + * Decorates an element as a inline-editable list item. Note that this is | 
| + * a subclass of DeletableItem. | 
| + * @param {!HTMLElement} el The element to decorate. | 
| + */ | 
| + InlineEditableItem.decorate = function(el) { | 
| + el.__proto__ = InlineEditableItem.prototype; | 
| + el.decorate(); | 
| + }; | 
| + | 
| + InlineEditableItem.prototype = { | 
| + __proto__: DeletableItem.prototype, | 
| + | 
| + /** | 
| + * Whether or not this item can be edited. | 
| + * @type {boolean} | 
| + * @private | 
| + */ | 
| + editable_: true, | 
| + | 
| + /** | 
| + * Whether or not the current edit should be considered cancelled, rather | 
| + * than committed, when editing ends. | 
| + * @type {boolean} | 
| + * @private | 
| + */ | 
| + editCancelled_: true, | 
| + | 
| + /** @inheritDoc */ | 
| + decorate: function() { | 
| + DeletableItem.prototype.decorate.call(this); | 
| + | 
| + var listItem = this; | 
| + | 
| + this.addEventListener('selectedChange', function(event) { | 
| 
arv (Not doing code reviews)
2011/01/11 21:52:45
You should be able to override the selected setter
 
stuartmorgan
2011/01/11 23:18:41
Actually, I discovered that there's already a sele
 | 
| + if (listItem.editable) | 
| + listItem.editing = listItem.selected; | 
| + }); | 
| + | 
| + this.addEventListener('keydown', this.handleKeyDown_.bind(this)); | 
| + }, | 
| + | 
| + /** | 
| + * 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'); | 
| + | 
| + | 
| 
Evan Stade
2011/01/11 21:06:01
remove extra line
 
stuartmorgan
2011/01/11 23:18:41
Done.
 | 
| + if (editing) { | 
| + this.editCancelled_ = false; | 
| + | 
| + this.onEditStarted(); | 
| 
arv (Not doing code reviews)
2011/01/11 21:52:45
cr.dispatchEvent
 
stuartmorgan
2011/01/11 23:18:41
Done, for all three onEdit* calls.
 | 
| + | 
| + var focusElement = this.initialFocusElement(); | 
| + // When this is called in response to the selectedChange event, | 
| + // the list grabs focus immediately afterwards. Thus we must delay | 
| + // our focus grab. | 
| + if (focusElement) { | 
| + window.setTimeout(function() { | 
| + focusElement.focus(); | 
| + focusElement.select(); | 
| + }, 50); | 
| + } | 
| + } else { | 
| + if (!this.editCancelled_ && this.hasBeenEdited() && | 
| + this.currentInputIsValid()) | 
| 
Evan Stade
2011/01/11 21:06:01
curlies for multi-line conditional
 
stuartmorgan
2011/01/11 23:18:41
Done.
 | 
| + this.onEditCommitted(); | 
| + else | 
| + this.onEditCancelled(); | 
| + } | 
| + }, | 
| + | 
| + /** | 
| + * Whether the item is editable. | 
| + * @type {boolean} | 
| + */ | 
| + get editable() { | 
| + return this.editable_; | 
| + }, | 
| + set editable(editable) { | 
| + this.editable_ = editable; | 
| + if (!editable) | 
| + this.editing = false; | 
| + }, | 
| + | 
| + /** | 
| + * Returns the HTML element that should have focus initially when editing | 
| + * starts. | 
| + * Should be overriden by subclasses. | 
| + * @return {HTMLElement} The element to focus when editing starts | 
| + */ | 
| + initialFocusElement: function() { | 
| 
arv (Not doing code reviews)
2011/01/11 21:52:45
Use getter?
 
stuartmorgan
2011/01/11 23:18:41
Done.
 | 
| + return null; | 
| + }, | 
| + | 
| + /** | 
| + * Returns true if 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 overrided by subclasses to perform input validation. | 
| + */ | 
| + currentInputIsValid: function() { | 
| 
arv (Not doing code reviews)
2011/01/11 21:52:45
use getter?
 
stuartmorgan
2011/01/11 23:18:41
Done.
 | 
| + return true; | 
| + }, | 
| + | 
| + /** | 
| + * Returns true if the item has been changed by an edit. | 
| + * Can be overrided by subclasses to return false when nothing has changed | 
| + * to avoid unnecessary commits. | 
| + */ | 
| + hasBeenEdited: function() { | 
| + return true; | 
| + }, | 
| + | 
| + /** | 
| + * Called when editing mode starts. | 
| + * Can be overridden by subclasses to do any pre-edit tasks. | 
| + */ | 
| + onEditStarted: function() { | 
| + }, | 
| + | 
| + /** | 
| + * Called when editing mode ends without cancelling. | 
| + * Should be overridden by subclasses to do any post-edit tasks, such as | 
| + * commiting the change. | 
| + */ | 
| + onEditCommitted: function() { | 
| + }, | 
| + | 
| + /** | 
| + * Called when editing mode is cancelled. | 
| + * Should be overridden by subclasses to do any post-cancellation tasks, | 
| + * such as undoing changes to the editable controls. | 
| + */ | 
| + onEditCancelled: function() { | 
| + }, | 
| + | 
| + /** | 
| + * Called a key is pressed. Handles committing and cancelling edits. | 
| + * @param {Event} e The key down event. | 
| + * @private | 
| + */ | 
| + handleKeyDown_: function(e) { | 
| + if (!this.editing) | 
| + return; | 
| + | 
| + var endEdit = false; | 
| + switch (e.keyIdentifier) { | 
| + case 'U+001B': // Esc | 
| + this.editCancelled_ = true; | 
| + endEdit = true; | 
| + break; | 
| + case 'Enter': | 
| + if (this.currentInputIsValid()) | 
| + endEdit = true; | 
| + break; | 
| + } | 
| + | 
| + if (endEdit) { | 
| + // Blurring will trigger the edit to end; see InlineEditableItemList. | 
| + 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(); | 
| + } | 
| + }, | 
| + }; | 
| + | 
| + var InlineEditableItemList = cr.ui.define('list'); | 
| + | 
| + InlineEditableItemList.prototype = { | 
| + __proto__: DeletableItemList.prototype, | 
| + | 
| + /** @inheritDoc */ | 
| + decorate: function() { | 
| + DeletableItemList.prototype.decorate.call(this); | 
| + this.addEventListener('blur', this.handleBlur_.bind(this), true); | 
| + }, | 
| + | 
| + /** | 
| + * Called when an element in the list is blurred. Removes selection (thus | 
| + * ending edit) if focus moves outside the list. | 
| + * @param {Event} e The blur event. | 
| + * @private | 
| + */ | 
| + handleBlur_: function(e) { | 
| + // When the blur event happens we do not know who is getting focus so we | 
| + // delay this a bit until we know if the new focus node is outside the | 
| + // list. | 
| + var list = this; | 
| + var doc = e.target.ownerDocument; | 
| + window.setTimeout(function() { | 
| + var activeElement = doc.activeElement; | 
| + if (!list.contains(activeElement)) | 
| + list.selectionModel.unselectAll(); | 
| + }, 50); | 
| + }, | 
| + }; | 
| + | 
| + // Export | 
| + return { | 
| + InlineEditableItem: InlineEditableItem, | 
| + InlineEditableItemList: InlineEditableItemList, | 
| + }; | 
| + | 
| 
Evan Stade
2011/01/11 21:06:01
extra line here and at eof
 
stuartmorgan
2011/01/11 23:18:41
Done.
 | 
| +}); | 
| + |