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; | |
| 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 var listItem = this; | |
| 53 | |
| 54 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
| |
| 55 if (listItem.editable) | |
| 56 listItem.editing = listItem.selected; | |
| 57 }); | |
| 58 | |
| 59 this.addEventListener('keydown', this.handleKeyDown_.bind(this)); | |
| 60 }, | |
| 61 | |
| 62 /** | |
| 63 * Whether the user is currently editing the list item. | |
| 64 * @type {boolean} | |
| 65 */ | |
| 66 get editing() { | |
| 67 return this.hasAttribute('editing'); | |
| 68 }, | |
| 69 set editing(editing) { | |
| 70 if (this.editing == editing) | |
| 71 return; | |
| 72 | |
| 73 if (editing) | |
| 74 this.setAttribute('editing', ''); | |
| 75 else | |
| 76 this.removeAttribute('editing'); | |
| 77 | |
| 78 | |
|
Evan Stade
2011/01/11 21:06:01
remove extra line
stuartmorgan
2011/01/11 23:18:41
Done.
| |
| 79 if (editing) { | |
| 80 this.editCancelled_ = false; | |
| 81 | |
| 82 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.
| |
| 83 | |
| 84 var focusElement = this.initialFocusElement(); | |
| 85 // When this is called in response to the selectedChange event, | |
| 86 // the list grabs focus immediately afterwards. Thus we must delay | |
| 87 // our focus grab. | |
| 88 if (focusElement) { | |
| 89 window.setTimeout(function() { | |
| 90 focusElement.focus(); | |
| 91 focusElement.select(); | |
| 92 }, 50); | |
| 93 } | |
| 94 } else { | |
| 95 if (!this.editCancelled_ && this.hasBeenEdited() && | |
| 96 this.currentInputIsValid()) | |
|
Evan Stade
2011/01/11 21:06:01
curlies for multi-line conditional
stuartmorgan
2011/01/11 23:18:41
Done.
| |
| 97 this.onEditCommitted(); | |
| 98 else | |
| 99 this.onEditCancelled(); | |
| 100 } | |
| 101 }, | |
| 102 | |
| 103 /** | |
| 104 * Whether the item is editable. | |
| 105 * @type {boolean} | |
| 106 */ | |
| 107 get editable() { | |
| 108 return this.editable_; | |
| 109 }, | |
| 110 set editable(editable) { | |
| 111 this.editable_ = editable; | |
| 112 if (!editable) | |
| 113 this.editing = false; | |
| 114 }, | |
| 115 | |
| 116 /** | |
| 117 * Returns the HTML element that should have focus initially when editing | |
| 118 * starts. | |
| 119 * Should be overriden by subclasses. | |
| 120 * @return {HTMLElement} The element to focus when editing starts | |
| 121 */ | |
| 122 initialFocusElement: function() { | |
|
arv (Not doing code reviews)
2011/01/11 21:52:45
Use getter?
stuartmorgan
2011/01/11 23:18:41
Done.
| |
| 123 return null; | |
| 124 }, | |
| 125 | |
| 126 /** | |
| 127 * Returns true if the input in currently valid to submit. If this returns | |
| 128 * false when editing would be submitted, either editing will not be ended, | |
| 129 * or it will be cancelled, depending on the context. | |
| 130 * Can be overrided by subclasses to perform input validation. | |
| 131 */ | |
| 132 currentInputIsValid: function() { | |
|
arv (Not doing code reviews)
2011/01/11 21:52:45
use getter?
stuartmorgan
2011/01/11 23:18:41
Done.
| |
| 133 return true; | |
| 134 }, | |
| 135 | |
| 136 /** | |
| 137 * Returns true if the item has been changed by an edit. | |
| 138 * Can be overrided by subclasses to return false when nothing has changed | |
| 139 * to avoid unnecessary commits. | |
| 140 */ | |
| 141 hasBeenEdited: function() { | |
| 142 return true; | |
| 143 }, | |
| 144 | |
| 145 /** | |
| 146 * Called when editing mode starts. | |
| 147 * Can be overridden by subclasses to do any pre-edit tasks. | |
| 148 */ | |
| 149 onEditStarted: function() { | |
| 150 }, | |
| 151 | |
| 152 /** | |
| 153 * Called when editing mode ends without cancelling. | |
| 154 * Should be overridden by subclasses to do any post-edit tasks, such as | |
| 155 * commiting the change. | |
| 156 */ | |
| 157 onEditCommitted: function() { | |
| 158 }, | |
| 159 | |
| 160 /** | |
| 161 * Called when editing mode is cancelled. | |
| 162 * Should be overridden by subclasses to do any post-cancellation tasks, | |
| 163 * such as undoing changes to the editable controls. | |
| 164 */ | |
| 165 onEditCancelled: function() { | |
| 166 }, | |
| 167 | |
| 168 /** | |
| 169 * Called a key is pressed. Handles committing and cancelling edits. | |
| 170 * @param {Event} e The key down event. | |
| 171 * @private | |
| 172 */ | |
| 173 handleKeyDown_: function(e) { | |
| 174 if (!this.editing) | |
| 175 return; | |
| 176 | |
| 177 var endEdit = false; | |
| 178 switch (e.keyIdentifier) { | |
| 179 case 'U+001B': // Esc | |
| 180 this.editCancelled_ = true; | |
| 181 endEdit = true; | |
| 182 break; | |
| 183 case 'Enter': | |
| 184 if (this.currentInputIsValid()) | |
| 185 endEdit = true; | |
| 186 break; | |
| 187 } | |
| 188 | |
| 189 if (endEdit) { | |
| 190 // Blurring will trigger the edit to end; see InlineEditableItemList. | |
| 191 this.ownerDocument.activeElement.blur(); | |
| 192 // Make sure that handled keys aren't passed on and double-handled. | |
| 193 // (e.g., esc shouldn't both cancel an edit and close a subpage) | |
| 194 e.stopPropagation(); | |
| 195 } | |
| 196 }, | |
| 197 }; | |
| 198 | |
| 199 var InlineEditableItemList = cr.ui.define('list'); | |
| 200 | |
| 201 InlineEditableItemList.prototype = { | |
| 202 __proto__: DeletableItemList.prototype, | |
| 203 | |
| 204 /** @inheritDoc */ | |
| 205 decorate: function() { | |
| 206 DeletableItemList.prototype.decorate.call(this); | |
| 207 this.addEventListener('blur', this.handleBlur_.bind(this), true); | |
| 208 }, | |
| 209 | |
| 210 /** | |
| 211 * Called when an element in the list is blurred. Removes selection (thus | |
| 212 * ending edit) if focus moves outside the list. | |
| 213 * @param {Event} e The blur event. | |
| 214 * @private | |
| 215 */ | |
| 216 handleBlur_: function(e) { | |
| 217 // When the blur event happens we do not know who is getting focus so we | |
| 218 // delay this a bit until we know if the new focus node is outside the | |
| 219 // list. | |
| 220 var list = this; | |
| 221 var doc = e.target.ownerDocument; | |
| 222 window.setTimeout(function() { | |
| 223 var activeElement = doc.activeElement; | |
| 224 if (!list.contains(activeElement)) | |
| 225 list.selectionModel.unselectAll(); | |
| 226 }, 50); | |
| 227 }, | |
| 228 }; | |
| 229 | |
| 230 // Export | |
| 231 return { | |
| 232 InlineEditableItem: InlineEditableItem, | |
| 233 InlineEditableItemList: InlineEditableItemList, | |
| 234 }; | |
| 235 | |
|
Evan Stade
2011/01/11 21:06:01
extra line here and at eof
stuartmorgan
2011/01/11 23:18:41
Done.
| |
| 236 }); | |
| 237 | |
| OLD | NEW |