Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 cr.define('options', function() { | |
| 6 const DeletableItem = options.DeletableItem; | |
|
arv (Not doing code reviews)
2011/01/11 23:29:29
It would be good if we could move these to cr.ui i
stuartmorgan
2011/01/12 00:26:51
Sure; added to my TODO list.
| |
| 7 const DeletableItemList = options.DeletableItemList; | |
| 8 | |
| 9 /** | |
| 10 * Creates a new list item with support for inline editing. | |
| 11 * @constructor | |
| 12 * @extends {options.DeletableListItem} | |
| 13 */ | |
| 14 function InlineEditableItem() { | |
| 15 var el = cr.doc.createElement('div'); | |
| 16 InlineEditableItem.decorate(el); | |
| 17 return el; | |
| 18 } | |
| 19 | |
| 20 /** | |
| 21 * Decorates an element as a inline-editable list item. Note that this is | |
| 22 * a subclass of DeletableItem. | |
| 23 * @param {!HTMLElement} el The element to decorate. | |
| 24 */ | |
| 25 InlineEditableItem.decorate = function(el) { | |
| 26 el.__proto__ = InlineEditableItem.prototype; | |
| 27 el.decorate(); | |
| 28 }; | |
| 29 | |
| 30 InlineEditableItem.prototype = { | |
| 31 __proto__: DeletableItem.prototype, | |
| 32 | |
| 33 /** | |
| 34 * Whether or not this item can be edited. | |
| 35 * @type {boolean} | |
| 36 * @private | |
| 37 */ | |
| 38 editable_: true, | |
| 39 | |
| 40 /** | |
| 41 * Whether or not the current edit should be considered cancelled, rather | |
| 42 * than committed, when editing ends. | |
| 43 * @type {boolean} | |
| 44 * @private | |
| 45 */ | |
| 46 editCancelled_: true, | |
| 47 | |
| 48 /** @inheritDoc */ | |
| 49 decorate: function() { | |
| 50 DeletableItem.prototype.decorate.call(this); | |
| 51 | |
| 52 this.addEventListener('keydown', this.handleKeyDown_.bind(this)); | |
| 53 }, | |
| 54 | |
| 55 /** @inheritDoc */ | |
| 56 selectionChanged: function() { | |
| 57 if (this.editable) | |
| 58 this.editing = this.selected; | |
| 59 }, | |
| 60 | |
| 61 /** | |
| 62 * Whether the user is currently editing the list item. | |
| 63 * @type {boolean} | |
| 64 */ | |
| 65 get editing() { | |
| 66 return this.hasAttribute('editing'); | |
| 67 }, | |
| 68 set editing(editing) { | |
| 69 if (this.editing == editing) | |
| 70 return; | |
| 71 | |
| 72 if (editing) | |
| 73 this.setAttribute('editing', ''); | |
| 74 else | |
| 75 this.removeAttribute('editing'); | |
| 76 | |
| 77 if (editing) { | |
| 78 this.editCancelled_ = false; | |
| 79 | |
| 80 cr.dispatchSimpleEvent(this, 'edit', true); | |
| 81 | |
| 82 var focusElement = this.initialFocusElement; | |
| 83 // When this is called in response to the selectedChange event, | |
| 84 // the list grabs focus immediately afterwards. Thus we must delay | |
| 85 // our focus grab. | |
| 86 if (focusElement) { | |
| 87 window.setTimeout(function() { | |
| 88 focusElement.focus(); | |
| 89 focusElement.select(); | |
| 90 }, 50); | |
| 91 } | |
| 92 } else { | |
| 93 if (!this.editCancelled_ && this.hasBeenEdited() && | |
| 94 this.currentInputIsValid) { | |
| 95 cr.dispatchSimpleEvent(this, 'commitedit', true); | |
| 96 } else { | |
| 97 cr.dispatchSimpleEvent(this, 'canceledit', true); | |
| 98 } | |
| 99 } | |
| 100 }, | |
| 101 | |
| 102 /** | |
| 103 * Whether the item is editable. | |
| 104 * @type {boolean} | |
| 105 */ | |
| 106 get editable() { | |
| 107 return this.editable_; | |
| 108 }, | |
| 109 set editable(editable) { | |
| 110 this.editable_ = editable; | |
| 111 if (!editable) | |
| 112 this.editing = false; | |
| 113 }, | |
| 114 | |
| 115 /** | |
| 116 * The HTML element that should have focus initially when editing starts. | |
| 117 * Should be overriden by subclasses. | |
| 118 * @type {HTMLElement} | |
| 119 */ | |
| 120 get initialFocusElement() { | |
| 121 return null; | |
| 122 }, | |
| 123 | |
| 124 /** | |
| 125 * Whether the input in currently valid to submit. If this returns false | |
| 126 * when editing would be submitted, either editing will not be ended, | |
| 127 * or it will be cancelled, depending on the context. | |
| 128 * Can be overrided by subclasses to perform input validation. | |
| 129 */ | |
| 130 get currentInputIsValid() { | |
| 131 return true; | |
| 132 }, | |
| 133 | |
| 134 /** | |
| 135 * Returns true if the item has been changed by an edit. | |
| 136 * Can be overrided by subclasses to return false when nothing has changed | |
| 137 * to avoid unnecessary commits. | |
| 138 */ | |
| 139 hasBeenEdited: function() { | |
| 140 return true; | |
| 141 }, | |
| 142 | |
| 143 /** | |
| 144 * Called a key is pressed. Handles committing and cancelling edits. | |
| 145 * @param {Event} e The key down event. | |
| 146 * @private | |
| 147 */ | |
| 148 handleKeyDown_: function(e) { | |
| 149 if (!this.editing) | |
| 150 return; | |
| 151 | |
| 152 var endEdit = false; | |
| 153 switch (e.keyIdentifier) { | |
| 154 case 'U+001B': // Esc | |
| 155 this.editCancelled_ = true; | |
| 156 endEdit = true; | |
| 157 break; | |
| 158 case 'Enter': | |
| 159 if (this.currentInputIsValid) | |
| 160 endEdit = true; | |
| 161 break; | |
| 162 } | |
| 163 | |
| 164 if (endEdit) { | |
| 165 // Blurring will trigger the edit to end; see InlineEditableItemList. | |
| 166 this.ownerDocument.activeElement.blur(); | |
| 167 // Make sure that handled keys aren't passed on and double-handled. | |
| 168 // (e.g., esc shouldn't both cancel an edit and close a subpage) | |
| 169 e.stopPropagation(); | |
| 170 } | |
| 171 }, | |
| 172 }; | |
| 173 | |
| 174 var InlineEditableItemList = cr.ui.define('list'); | |
| 175 | |
| 176 InlineEditableItemList.prototype = { | |
| 177 __proto__: DeletableItemList.prototype, | |
| 178 | |
| 179 /** @inheritDoc */ | |
| 180 decorate: function() { | |
| 181 DeletableItemList.prototype.decorate.call(this); | |
| 182 this.addEventListener('blur', this.handleBlur_.bind(this), true); | |
| 183 }, | |
| 184 | |
| 185 /** | |
| 186 * Called when an element in the list is blurred. Removes selection (thus | |
| 187 * ending edit) if focus moves outside the list. | |
| 188 * @param {Event} e The blur event. | |
| 189 * @private | |
| 190 */ | |
| 191 handleBlur_: function(e) { | |
| 192 // When the blur event happens we do not know who is getting focus so we | |
| 193 // delay this a bit until we know if the new focus node is outside the | |
| 194 // list. | |
| 195 var list = this; | |
| 196 var doc = e.target.ownerDocument; | |
| 197 window.setTimeout(function() { | |
| 198 var activeElement = doc.activeElement; | |
| 199 if (!list.contains(activeElement)) | |
| 200 list.selectionModel.unselectAll(); | |
| 201 }, 50); | |
| 202 }, | |
| 203 }; | |
| 204 | |
| 205 // Export | |
| 206 return { | |
| 207 InlineEditableItem: InlineEditableItem, | |
| 208 InlineEditableItemList: InlineEditableItemList, | |
| 209 }; | |
| 210 }); | |
| OLD | NEW |