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

Side by Side Diff: chrome/browser/resources/options/inline_editable_list.js

Issue 683813004: Fewer focusable items in chrome://settings/searchEngines (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 cr.define('options', function() { 5 cr.define('options', function() {
6 /** @const */ var DeletableItem = options.DeletableItem; 6 /** @const */ var DeletableItem = options.DeletableItem;
7 /** @const */ var DeletableItemList = options.DeletableItemList; 7 /** @const */ var DeletableItemList = options.DeletableItemList;
8 8
9 /** 9 /**
10 * Creates a new list item with support for inline editing. 10 * Creates a new list item with support for inline editing.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 selectionChanged: function() { 81 selectionChanged: function() {
82 this.updateEditState(); 82 this.updateEditState();
83 }, 83 },
84 84
85 /** 85 /**
86 * Called when this element gains or loses 'lead' status. Updates editing 86 * Called when this element gains or loses 'lead' status. Updates editing
87 * mode accordingly. 87 * mode accordingly.
88 * @private 88 * @private
89 */ 89 */
90 handleLeadChange_: function() { 90 handleLeadChange_: function() {
91 // Add focusability before call to updateEditState.
92 if (this.lead) {
93 this.setEditableValuesFocusable(true);
94 this.setCloseButtonFocusable(true);
95 }
96
91 this.updateEditState(); 97 this.updateEditState();
98
99 // Remove focusability after call to updateEditState.
100 this.setStaticValuesFocusable(false);
101 if (!this.lead) {
102 this.setEditableValuesFocusable(false);
103 this.setCloseButtonFocusable(false);
104 }
92 }, 105 },
93 106
94 /** 107 /**
95 * Updates the edit state based on the current selected and lead states. 108 * Updates the edit state based on the current selected and lead states.
96 */ 109 */
97 updateEditState: function() { 110 updateEditState: function() {
98 if (this.editable) 111 if (this.editable)
99 this.editing = this.selected && this.lead; 112 this.editing = this.selected && this.lead;
100 }, 113 },
101 114
(...skipping 13 matching lines...) Expand all
115 else 128 else
116 this.removeAttribute('editing'); 129 this.removeAttribute('editing');
117 130
118 if (editing) { 131 if (editing) {
119 this.editCancelled_ = false; 132 this.editCancelled_ = false;
120 133
121 cr.dispatchSimpleEvent(this, 'edit', true); 134 cr.dispatchSimpleEvent(this, 'edit', true);
122 135
123 var focusElement = this.editClickTarget_ || this.initialFocusElement; 136 var focusElement = this.editClickTarget_ || this.initialFocusElement;
124 this.editClickTarget_ = null; 137 this.editClickTarget_ = null;
125 138 if (focusElement)
126 if (focusElement) {
127 var self = this;
128 // We should delay to give focus on |focusElement| if this is called
129 // in mousedown event handler. If we did give focus immediately, Blink
130 // would try to focus on an ancestor of the mousedown target element,
131 // and remove focus from |focusElement|.
132 if (focusElement.staticVersion &&
133 focusElement.staticVersion.hasAttribute('tabindex')) {
134 setTimeout(function() {
135 if (self.editing) {
136 if (focusElement.disabled)
137 self.parentNode.focus();
138 self.focusAndMaybeSelect_(focusElement);
139 }
140 focusElement.staticVersion.removeAttribute('tabindex');
141 }, 0);
142 } else {
bondd 2014/10/28 22:29:57 No longer required for new way of focusing element
143 this.focusAndMaybeSelect_(focusElement); 139 this.focusAndMaybeSelect_(focusElement);
144 }
145 }
146 } else { 140 } else {
147 if (!this.editCancelled_ && this.hasBeenEdited && 141 if (!this.editCancelled_ && this.hasBeenEdited &&
148 this.currentInputIsValid) { 142 this.currentInputIsValid) {
149 if (this.isPlaceholder) 143 if (this.isPlaceholder)
150 this.parentNode.focusPlaceholder = true; 144 this.parentNode.focusPlaceholder = true;
151 145
152 this.updateStaticValues_(); 146 this.updateStaticValues_();
153 cr.dispatchSimpleEvent(this, 'commitedit', true); 147 cr.dispatchSimpleEvent(this, 'commitedit', true);
154 } else { 148 } else {
155 this.resetEditableValues_(); 149 this.resetEditableValues_();
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 * Returns true if the item has been changed by an edit. 216 * Returns true if the item has been changed by an edit.
223 * Can be overridden by subclasses to return false when nothing has changed 217 * Can be overridden by subclasses to return false when nothing has changed
224 * to avoid unnecessary commits. 218 * to avoid unnecessary commits.
225 * @type {boolean} 219 * @type {boolean}
226 */ 220 */
227 get hasBeenEdited() { 221 get hasBeenEdited() {
228 return true; 222 return true;
229 }, 223 },
230 224
231 /** 225 /**
226 * Sets whether the editable values can be given focus using the
227 * keyboard+mouse, mouse only, or neither.
Dan Beam 2014/10/29 01:37:13 using the keyboard.
bondd 2014/10/29 17:19:08 Done.
228 *
229 * Result:
230 * If this item is not editable: focusable by neither
231 * else if the field is disabled: focusable by mouse only
232 * else:
233 * if wantFocusable == true: focusable by mouse+keyboard
234 * else: focusable by mouse only
Dan Beam 2014/10/29 01:37:13 ^ I don't think this is required, unfocusable mean
bondd 2014/10/29 17:19:07 I removed the entire "Result" comment block. Is th
235 *
236 * @param {boolean} wantFocusable The desired focusable state.
237 */
238 setEditableValuesFocusable: function(wantFocusable) {
Dan Beam 2014/10/29 01:37:13 wantFocusable => focusable
Dan Beam 2014/10/29 01:37:13 this.editable is loop invariant, I believe, so it'
bondd 2014/10/29 17:19:08 Done.
239 var editFields = this.editFields_;
240 for (var i = 0; i < editFields.length; i++) {
241 if (this.editable) {
242 if (wantFocusable && !editFields[i].disabled)
Dan Beam 2014/10/29 01:37:13 it does seem like [disabled][tabindex=0] is actual
Dan Beam 2014/10/29 01:37:14 can't this whole loop body be editFields[i].tabIn
bondd 2014/10/29 17:19:08 Done. I had guessed that condensing logic like thi
bondd 2014/10/29 17:19:08 Did you mean "it doesn't seem"? That button you li
Dan Beam 2014/10/29 22:28:11 doesn't**
243 editFields[i].tabIndex = 0;
Dan Beam 2014/10/29 01:37:13 indent off
244 else
245 editFields[i].tabIndex = -1;
246 }
Dan Beam 2014/10/29 01:37:13 } else {
247 else {
248 editFields[i].removeAttribute('tabindex');
bondd 2014/10/29 17:19:08 I got rid of this per your above comment re: conde
249 }
250 }
251 },
252
253 /**
254 * Sets whether the static values can be given focus using the
255 * keyboard+mouse, mouse only, or neither.
256 *
257 * Result:
258 * If this item is not editable: focusable by neither
259 * else if the field is disabled: focusable by mouse only
260 * else:
261 * if wantFocusable == true: focusable by mouse+keyboard
262 * else: focusable by mouse only
263 *
264 * @param {boolean} wantFocusable The desired focusable state.
265 */
266 setStaticValuesFocusable: function(wantFocusable) {
267 var editFields = this.editFields_;
268 for (var i = 0; i < editFields.length; i++) {
269 var staticVersion = editFields[i].staticVersion;
270 if (!staticVersion)
271 continue;
272
273 if (this.editable) {
Dan Beam 2014/10/29 01:37:13 same general nits here as in setEditableValuesFocu
bondd 2014/10/29 17:19:08 Done.
274 if (wantFocusable && !staticVersion.disabled)
275 staticVersion.tabIndex = 0;
276 else
277 staticVersion.tabIndex = -1;
278 }
279 else {
280 staticVersion.removeAttribute('tabindex');
281 }
Dan Beam 2014/10/29 01:37:13 indent off (-2 \s)
282 }
283 },
284
285 /**
286 * Sets whether the close button can be focused using the keyboard.
287 *
288 * @param {boolean} wantFocusable The desired focusable state.
289 */
290 setCloseButtonFocusable: function(wantFocusable) {
Dan Beam 2014/10/29 01:37:13 why can't we just use an ES5 getter/setter for thi
bondd 2014/10/29 17:19:08 To keep it consistent with setStaticValuesFocusabl
Dan Beam 2014/10/29 22:28:11 that doesn't apply to Chrome code, as you've deter
291 if (this.closeButtonFocusAllowed || !wantFocusable)
292 this.closeButtonElement.tabIndex = wantFocusable ? 0 : -1;
293 },
294
295 /**
232 * Returns a div containing an <input>, as well as static text if 296 * Returns a div containing an <input>, as well as static text if
233 * isPlaceholder is not true. 297 * isPlaceholder is not true.
234 * @param {string} text The text of the cell. 298 * @param {string} text The text of the cell.
235 * @return {HTMLElement} The HTML element for the cell. 299 * @return {HTMLElement} The HTML element for the cell.
236 * @private 300 * @private
237 */ 301 */
238 createEditableTextCell: function(text) { 302 createEditableTextCell: function(text) {
239 var container = /** @type {HTMLElement} */( 303 var container = /** @type {HTMLElement} */(
240 this.ownerDocument.createElement('div')); 304 this.ownerDocument.createElement('div'));
241 var textEl = null; 305 var textEl = null;
(...skipping 19 matching lines...) Expand all
261 if (list && list.focusPlaceholder) { 325 if (list && list.focusPlaceholder) {
262 list.focusPlaceholder = false; 326 list.focusPlaceholder = false;
263 if (list.shouldFocusPlaceholder()) 327 if (list.shouldFocusPlaceholder())
264 inputEl.focus(); 328 inputEl.focus();
265 } 329 }
266 }, 50); 330 }, 50);
267 } 331 }
268 332
269 // In some cases 'focus' event may arrive before 'input'. 333 // In some cases 'focus' event may arrive before 'input'.
270 // To make sure revalidation is triggered we postpone 'focus' handling. 334 // To make sure revalidation is triggered we postpone 'focus' handling.
271 var handler = this.handleFocus_.bind(this); 335 var handler = this.handleFocus.bind(this);
272 inputEl.addEventListener('focus', function() { 336 inputEl.addEventListener('focus', function() {
273 window.setTimeout(function() { 337 window.setTimeout(function() {
274 if (inputEl.ownerDocument.activeElement == inputEl) 338 if (inputEl.ownerDocument.activeElement == inputEl)
275 handler(); 339 handler();
276 }, 0); 340 }, 0);
277 }); 341 });
278 container.appendChild(inputEl); 342 container.appendChild(inputEl);
279 this.addEditField(inputEl, textEl); 343 this.addEditField(inputEl, textEl);
280 344
281 return container; 345 return container;
282 }, 346 },
283 347
284 /** 348 /**
285 * Register an edit field. 349 * Register an edit field.
286 * @param {!Element} control An editable element. It's a form control 350 * @param {!Element} control An editable element. It's a form control
287 * element typically. 351 * element typically.
288 * @param {Element} staticElement An element representing non-editable 352 * @param {Element} staticElement An element representing non-editable
289 * state. 353 * state.
290 */ 354 */
291 addEditField: function(control, staticElement) { 355 addEditField: function(control, staticElement) {
292 control.staticVersion = staticElement; 356 control.staticVersion = staticElement;
357 if (this.editable)
358 control.tabIndex = -1;
359
360 if (control.staticVersion) {
361 if (this.editable)
362 control.staticVersion.tabIndex = -1;
363 control.staticVersion.editableVersion = control;
364
365 var handler = this.handleFocus.bind(this);
366 control.staticVersion.addEventListener('focus', function() {
Dan Beam 2014/10/29 01:37:13 control.staticVersion.addEventListener('focus', th
bondd 2014/10/29 17:19:08 Done.
367 handler();
368 });
369 }
293 this.editFields_.push(control); 370 this.editFields_.push(control);
294 }, 371 },
295 372
296 /** 373 /**
297 * Resets the editable version of any controls created by createEditable* 374 * Resets the editable version of any controls created by createEditable*
298 * to match the static text. 375 * to match the static text.
299 * @private 376 * @private
300 */ 377 */
301 resetEditableValues_: function() { 378 resetEditableValues_: function() {
302 var editFields = this.editFields_; 379 var editFields = this.editFields_;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 445 }
369 }, 446 },
370 447
371 /** 448 /**
372 * Called when the list item is clicked. If the click target corresponds to 449 * Called when the list item is clicked. If the click target corresponds to
373 * an editable item, stores that item to focus when edit mode is started. 450 * an editable item, stores that item to focus when edit mode is started.
374 * @param {Event} e The mouse down event. 451 * @param {Event} e The mouse down event.
375 * @private 452 * @private
376 */ 453 */
377 handleMouseDown_: function(e) { 454 handleMouseDown_: function(e) {
378 if (!this.editable || this.editing) 455 if (!this.editable)
379 return; 456 return;
380 457
381 var clickTarget = e.target; 458 var clickTarget = e.target;
382 var editFields = this.editFields_; 459 var editFields = this.editFields_;
460 var clickField;
Dan Beam 2014/10/29 01:37:14 clickField => editClickTarget
bondd 2014/10/29 17:19:08 Done.
Dan Beam 2014/10/29 22:28:11 editClickTarget (note the "Target")
bondd 2014/10/29 23:08:54 Done.
383 for (var i = 0; i < editFields.length; i++) { 461 for (var i = 0; i < editFields.length; i++) {
384 if (editFields[i].staticVersion == clickTarget) 462 if ((editFields[i] == clickTarget ||
385 clickTarget.tabIndex = 0; 463 editFields[i].staticVersion == clickTarget)) {
bondd 2014/10/28 22:29:57 Oops, double parens (( ))
bondd 2014/10/29 17:19:08 Done.
386 if (editFields[i] == clickTarget || 464 clickField = editFields[i];
387 editFields[i].staticVersion == clickTarget) { 465 break;
388 this.editClickTarget_ = editFields[i];
389 return;
390 } 466 }
391 } 467 }
468
469 if (this.editing) {
470 if (!clickField) {
471 // Clicked on the list item outside of an edit field. Don't lose
472 // focus from currently selected edit field.
Dan Beam 2014/10/29 01:37:13 wrap at 80 cols
bondd 2014/10/29 17:19:08 Done.
473 e.stopPropagation();
474 e.preventDefault();
475 }
476 return;
477 }
478
479 if (clickField && !clickField.disabled)
480 this.editClickTarget_ = clickField;
392 }, 481 },
393 }; 482 };
394 483
395 /** 484 /**
396 * Takes care of committing changes to inline editable list items when the 485 * Takes care of committing changes to inline editable list items when the
397 * window loses focus. 486 * window loses focus.
398 */ 487 */
399 function handleWindowBlurs() { 488 function handleWindowBlurs() {
400 window.addEventListener('blur', function(e) { 489 window.addEventListener('blur', function(e) {
401 var itemAncestor = findAncestor(document.activeElement, function(node) { 490 var itemAncestor = findAncestor(document.activeElement, function(node) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 524
436 /** 525 /**
437 * Called when the list hierarchy as a whole loses or gains focus; starts 526 * Called when the list hierarchy as a whole loses or gains focus; starts
438 * or ends editing for the lead item if necessary. 527 * or ends editing for the lead item if necessary.
439 * @param {Event} e The change event. 528 * @param {Event} e The change event.
440 * @private 529 * @private
441 */ 530 */
442 handleListFocusChange_: function(e) { 531 handleListFocusChange_: function(e) {
443 var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex); 532 var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex);
444 if (leadItem) { 533 if (leadItem) {
445 if (e.newValue) 534 if (e.newValue) {
535 // Add focusability before making other changes.
536 leadItem.setEditableValuesFocusable(true);
537 leadItem.setCloseButtonFocusable(true);
446 leadItem.updateEditState(); 538 leadItem.updateEditState();
447 else 539 // Remove focusability after making other changes.
540 leadItem.setStaticValuesFocusable(false);
541 }
Dan Beam 2014/10/29 01:37:13 } else {
bondd 2014/10/29 17:19:08 Done.
542 else {
543 // Add focusability before making other changes.
544 leadItem.setStaticValuesFocusable(true);
545 leadItem.setCloseButtonFocusable(true);
448 leadItem.editing = false; 546 leadItem.editing = false;
547 // Remove focusability after making other changes.
548 if (!leadItem.isPlaceholder)
549 leadItem.setEditableValuesFocusable(false);
550 }
449 } 551 }
450 }, 552 },
451 553
554 /**
555 * Called after the DataModel for the list has been set.
556 * @override
557 */
558 onSetDataModelComplete: function() {
559 DeletableItemList.prototype.onSetDataModelComplete.call(this);
560
561 var firstItem = this.getListItemByIndex(0);
562 if (firstItem) {
563 firstItem.setStaticValuesFocusable(true);
564 firstItem.setCloseButtonFocusable(true);
565 if (firstItem.isPlaceholder)
566 firstItem.setEditableValuesFocusable(true);
567 }
568 },
569
452 /** 570 /**
453 * May be overridden by subclasses to disable focusing the placeholder. 571 * May be overridden by subclasses to disable focusing the placeholder.
454 * @return {boolean} True if the placeholder element should be focused on 572 * @return {boolean} True if the placeholder element should be focused on
455 * edit commit. 573 * edit commit.
456 */ 574 */
457 shouldFocusPlaceholder: function() { 575 shouldFocusPlaceholder: function() {
458 return true; 576 return true;
459 }, 577 },
460 }; 578 };
461 579
462 // Export 580 // Export
463 return { 581 return {
464 InlineEditableItem: InlineEditableItem, 582 InlineEditableItem: InlineEditableItem,
465 InlineEditableItemList: InlineEditableItemList, 583 InlineEditableItemList: InlineEditableItemList,
466 }; 584 };
467 }); 585 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698