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

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: set*ValuesFocusable changes 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) { 139 this.focusAndMaybeSelect_(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 {
143 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 keyboard.
227 * @param {boolean} focusable The desired focusable state.
228 */
229 setEditableValuesFocusable: function(focusable) {
230 focusable = focusable && this.editable;
231 var editFields = this.editFields_;
232 for (var i = 0; i < editFields.length; i++) {
233 editFields[i].tabIndex = focusable && !editFields[i].disabled ? 0 : -1;
Dan Beam 2014/10/30 01:45:49 i think when editFields[i].disabled == true, tabIn
bondd 2014/10/30 15:00:04 Done.
234 }
235 },
236
237 /**
238 * Sets whether the static values can be given focus using the keyboard.
239 * @param {boolean} focusable The desired focusable state.
240 */
241 setStaticValuesFocusable: function(focusable) {
242 var editFields = this.editFields_;
243 for (var i = 0; i < editFields.length; i++) {
244 var staticVersion = editFields[i].staticVersion;
245 if (staticVersion) {
Dan Beam 2014/10/30 01:45:49 if (!staticVersion) continue; ... less indent .
bondd 2014/10/30 15:00:04 Done.
246 if (this.editable) {
247 staticVersion.tabIndex = focusable && !staticVersion.disabled ?
248 0 : -1;
249 } else {
250 // staticVersion remains visible when !this.editable. Remove
251 // tabindex so that it will not become focused by clicking on it and
252 // have selection box drawn around it.
bondd 2014/10/30 01:25:32 Added comment to explain why removeAttribute call
253 staticVersion.removeAttribute('tabindex');
254 }
255 }
256 }
257 },
258
259 /**
260 * Sets whether the close button can be focused using the keyboard.
261 *
Dan Beam 2014/10/30 01:45:49 nit: remove extra line
bondd 2014/10/30 15:00:04 Done.
262 * @param {boolean} focusable The desired focusable state.
263 */
264 setCloseButtonFocusable: function(focusable) {
265 this.closeButtonElement.tabIndex =
Dan Beam 2014/10/30 01:45:49 indent off (2\s is default, 4\s for continuations)
bondd 2014/10/30 15:00:04 Done.
266 focusable && this.closeButtonFocusAllowed ? 0 : -1;
267 },
268
269 /**
232 * Returns a div containing an <input>, as well as static text if 270 * Returns a div containing an <input>, as well as static text if
233 * isPlaceholder is not true. 271 * isPlaceholder is not true.
234 * @param {string} text The text of the cell. 272 * @param {string} text The text of the cell.
235 * @return {HTMLElement} The HTML element for the cell. 273 * @return {HTMLElement} The HTML element for the cell.
236 * @private 274 * @private
237 */ 275 */
238 createEditableTextCell: function(text) { 276 createEditableTextCell: function(text) {
239 var container = /** @type {HTMLElement} */( 277 var container = /** @type {HTMLElement} */(
240 this.ownerDocument.createElement('div')); 278 this.ownerDocument.createElement('div'));
241 var textEl = null; 279 var textEl = null;
(...skipping 19 matching lines...) Expand all
261 if (list && list.focusPlaceholder) { 299 if (list && list.focusPlaceholder) {
262 list.focusPlaceholder = false; 300 list.focusPlaceholder = false;
263 if (list.shouldFocusPlaceholder()) 301 if (list.shouldFocusPlaceholder())
264 inputEl.focus(); 302 inputEl.focus();
265 } 303 }
266 }, 50); 304 }, 50);
267 } 305 }
268 306
269 // In some cases 'focus' event may arrive before 'input'. 307 // In some cases 'focus' event may arrive before 'input'.
270 // To make sure revalidation is triggered we postpone 'focus' handling. 308 // To make sure revalidation is triggered we postpone 'focus' handling.
271 var handler = this.handleFocus_.bind(this); 309 var handler = this.handleFocus.bind(this);
272 inputEl.addEventListener('focus', function() { 310 inputEl.addEventListener('focus', function() {
273 window.setTimeout(function() { 311 window.setTimeout(function() {
274 if (inputEl.ownerDocument.activeElement == inputEl) 312 if (inputEl.ownerDocument.activeElement == inputEl)
275 handler(); 313 handler();
276 }, 0); 314 }, 0);
277 }); 315 });
278 container.appendChild(inputEl); 316 container.appendChild(inputEl);
279 this.addEditField(inputEl, textEl); 317 this.addEditField(inputEl, textEl);
280 318
281 return container; 319 return container;
282 }, 320 },
283 321
284 /** 322 /**
285 * Register an edit field. 323 * Register an edit field.
286 * @param {!Element} control An editable element. It's a form control 324 * @param {!Element} control An editable element. It's a form control
287 * element typically. 325 * element typically.
288 * @param {Element} staticElement An element representing non-editable 326 * @param {Element} staticElement An element representing non-editable
289 * state. 327 * state.
290 */ 328 */
291 addEditField: function(control, staticElement) { 329 addEditField: function(control, staticElement) {
292 control.staticVersion = staticElement; 330 control.staticVersion = staticElement;
331 if (this.editable)
332 control.tabIndex = -1;
333
334 if (control.staticVersion) {
335 if (this.editable)
336 control.staticVersion.tabIndex = -1;
337 control.staticVersion.editableVersion = control;
338 control.staticVersion.addEventListener('focus',
339 this.handleFocus.bind(this));
340 }
293 this.editFields_.push(control); 341 this.editFields_.push(control);
294 }, 342 },
295 343
296 /** 344 /**
297 * Resets the editable version of any controls created by createEditable* 345 * Resets the editable version of any controls created by createEditable*
298 * to match the static text. 346 * to match the static text.
299 * @private 347 * @private
300 */ 348 */
301 resetEditableValues_: function() { 349 resetEditableValues_: function() {
302 var editFields = this.editFields_; 350 var editFields = this.editFields_;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 416 }
369 }, 417 },
370 418
371 /** 419 /**
372 * Called when the list item is clicked. If the click target corresponds to 420 * 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. 421 * an editable item, stores that item to focus when edit mode is started.
374 * @param {Event} e The mouse down event. 422 * @param {Event} e The mouse down event.
375 * @private 423 * @private
376 */ 424 */
377 handleMouseDown_: function(e) { 425 handleMouseDown_: function(e) {
378 if (!this.editable || this.editing) 426 if (!this.editable)
379 return; 427 return;
380 428
381 var clickTarget = e.target; 429 var clickTarget = e.target;
382 var editFields = this.editFields_; 430 var editFields = this.editFields_;
431 var editClickTarget;
383 for (var i = 0; i < editFields.length; i++) { 432 for (var i = 0; i < editFields.length; i++) {
384 if (editFields[i].staticVersion == clickTarget)
385 clickTarget.tabIndex = 0;
386 if (editFields[i] == clickTarget || 433 if (editFields[i] == clickTarget ||
387 editFields[i].staticVersion == clickTarget) { 434 editFields[i].staticVersion == clickTarget) {
388 this.editClickTarget_ = editFields[i]; 435 editClickTarget = editFields[i];
389 return; 436 break;
390 } 437 }
391 } 438 }
439
440 if (this.editing) {
441 if (!editClickTarget) {
442 // Clicked on the list item outside of an edit field. Don't lose focus
443 // from currently selected edit field.
444 e.stopPropagation();
445 e.preventDefault();
446 }
447 return;
448 }
449
450 if (editClickTarget && !editClickTarget.disabled)
451 this.editClickTarget_ = editClickTarget;
392 }, 452 },
393 }; 453 };
394 454
395 /** 455 /**
396 * Takes care of committing changes to inline editable list items when the 456 * Takes care of committing changes to inline editable list items when the
397 * window loses focus. 457 * window loses focus.
398 */ 458 */
399 function handleWindowBlurs() { 459 function handleWindowBlurs() {
400 window.addEventListener('blur', function(e) { 460 window.addEventListener('blur', function(e) {
401 var itemAncestor = findAncestor(document.activeElement, function(node) { 461 var itemAncestor = findAncestor(document.activeElement, function(node) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 495
436 /** 496 /**
437 * Called when the list hierarchy as a whole loses or gains focus; starts 497 * Called when the list hierarchy as a whole loses or gains focus; starts
438 * or ends editing for the lead item if necessary. 498 * or ends editing for the lead item if necessary.
439 * @param {Event} e The change event. 499 * @param {Event} e The change event.
440 * @private 500 * @private
441 */ 501 */
442 handleListFocusChange_: function(e) { 502 handleListFocusChange_: function(e) {
443 var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex); 503 var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex);
444 if (leadItem) { 504 if (leadItem) {
445 if (e.newValue) 505 if (e.newValue) {
506 // Add focusability before making other changes.
507 leadItem.setEditableValuesFocusable(true);
508 leadItem.setCloseButtonFocusable(true);
446 leadItem.updateEditState(); 509 leadItem.updateEditState();
447 else 510 // Remove focusability after making other changes.
511 leadItem.setStaticValuesFocusable(false);
512 } else {
513 // Add focusability before making other changes.
514 leadItem.setStaticValuesFocusable(true);
515 leadItem.setCloseButtonFocusable(true);
448 leadItem.editing = false; 516 leadItem.editing = false;
517 // Remove focusability after making other changes.
518 if (!leadItem.isPlaceholder)
519 leadItem.setEditableValuesFocusable(false);
520 }
449 } 521 }
450 }, 522 },
451 523
524 /**
525 * Called after the DataModel for the list has been set.
526 * @override
527 */
528 onSetDataModelComplete: function() {
529 DeletableItemList.prototype.onSetDataModelComplete.call(this);
530
531 var firstItem = this.getListItemByIndex(0);
532 if (firstItem) {
533 firstItem.setStaticValuesFocusable(true);
534 firstItem.setCloseButtonFocusable(true);
535 if (firstItem.isPlaceholder)
536 firstItem.setEditableValuesFocusable(true);
537 }
538 },
539
452 /** 540 /**
453 * May be overridden by subclasses to disable focusing the placeholder. 541 * May be overridden by subclasses to disable focusing the placeholder.
454 * @return {boolean} True if the placeholder element should be focused on 542 * @return {boolean} True if the placeholder element should be focused on
455 * edit commit. 543 * edit commit.
456 */ 544 */
457 shouldFocusPlaceholder: function() { 545 shouldFocusPlaceholder: function() {
458 return true; 546 return true;
459 }, 547 },
460 }; 548 };
461 549
462 // Export 550 // Export
463 return { 551 return {
464 InlineEditableItem: InlineEditableItem, 552 InlineEditableItem: InlineEditableItem,
465 InlineEditableItemList: InlineEditableItemList, 553 InlineEditableItemList: InlineEditableItemList,
466 }; 554 };
467 }); 555 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698