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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js

Issue 2644233007: DevTools: Use real focus in TreeOutline (Closed)
Patch Set: test results Created 3 years, 10 months 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
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/ui/treeoutline.css ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 12 matching lines...) Expand all
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 /** 29 /**
30 * @unrestricted 30 * @unrestricted
31 */ 31 */
32 UI.TreeOutline = class extends Common.Object { 32 UI.TreeOutline = class extends Common.Object {
33 /** 33 constructor() {
34 * @param {boolean=} nonFocusable
35 */
36 constructor(nonFocusable) {
37 super(); 34 super();
38 this._createRootElement(); 35 this._createRootElement();
39 36
37 /** @type {?UI.TreeElement} */
40 this.selectedTreeElement = null; 38 this.selectedTreeElement = null;
41 this.expandTreeElementsWhenArrowing = false; 39 this.expandTreeElementsWhenArrowing = false;
42 /** @type {?function(!UI.TreeElement, !UI.TreeElement):number} */ 40 /** @type {?function(!UI.TreeElement, !UI.TreeElement):number} */
43 this._comparator = null; 41 this._comparator = null;
44 42
45 this.contentElement = this._rootElement._childrenListNode; 43 this.contentElement = this._rootElement._childrenListNode;
46 this.contentElement.addEventListener('keydown', this._treeKeyDown.bind(this) , true); 44 this.contentElement.addEventListener('keydown', this._treeKeyDown.bind(this) , true);
47 this.contentElement.addEventListener('focus', setFocused.bind(this, true), f alse);
48 this.contentElement.addEventListener('blur', setFocused.bind(this, false), f alse);
49 45
50 this.setFocusable(!nonFocusable); 46 this._focusable = true;
51 47 this.setFocusable(this._focusable);
48 if (this._focusable)
49 this.contentElement.setAttribute('tabIndex', -1);
52 this.element = this.contentElement; 50 this.element = this.contentElement;
53 51
54 // Adjust to allow computing margin-left for the selection element. 52 // Adjust to allow computing margin-left for the selection element.
55 // Check the padding-left for the li element for correct value. 53 // Check the padding-left for the li element for correct value.
56 this._paddingSize = 0; 54 this._paddingSize = 0;
57
58 /**
59 * @param {boolean} isFocused
60 * @this {UI.TreeOutline}
61 */
62 function setFocused(isFocused) {
63 this._focused = isFocused;
64 if (this.selectedTreeElement)
65 this.selectedTreeElement._setFocused(this._focused);
66 }
67 } 55 }
68 56
69 _createRootElement() { 57 _createRootElement() {
70 this._rootElement = new UI.TreeElement(); 58 this._rootElement = new UI.TreeElement();
71 this._rootElement.treeOutline = this; 59 this._rootElement.treeOutline = this;
72 this._rootElement.root = true; 60 this._rootElement.root = true;
73 this._rootElement.selectable = false; 61 this._rootElement.selectable = false;
74 this._rootElement.expanded = true; 62 this._rootElement.expanded = true;
75 this._rootElement._childrenListNode.classList.remove('children'); 63 this._rootElement._childrenListNode.classList.remove('children');
76 } 64 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 * @param {?function(!UI.TreeElement, !UI.TreeElement):number} comparator 131 * @param {?function(!UI.TreeElement, !UI.TreeElement):number} comparator
144 */ 132 */
145 setComparator(comparator) { 133 setComparator(comparator) {
146 this._comparator = comparator; 134 this._comparator = comparator;
147 } 135 }
148 136
149 /** 137 /**
150 * @param {boolean} focusable 138 * @param {boolean} focusable
151 */ 139 */
152 setFocusable(focusable) { 140 setFocusable(focusable) {
153 if (focusable) 141 if (focusable) {
154 this.contentElement.setAttribute('tabIndex', 0); 142 this._focusable = true;
155 else 143 this.contentElement.setAttribute('tabIndex', -1);
144 if (this.selectedTreeElement)
145 this.selectedTreeElement._setFocusable(true);
146 } else {
147 this._focusable = false;
156 this.contentElement.removeAttribute('tabIndex'); 148 this.contentElement.removeAttribute('tabIndex');
149 if (this.selectedTreeElement)
150 this.selectedTreeElement._setFocusable(false);
151 }
157 } 152 }
158 153
159 focus() { 154 focus() {
160 this.contentElement.focus(); 155 if (this.selectedTreeElement)
156 this.selectedTreeElement.listItemElement.focus();
157 else
158 this.contentElement.focus();
161 } 159 }
162 160
163 /** 161 /**
164 * @param {!UI.TreeElement} element 162 * @param {!UI.TreeElement} element
165 */ 163 */
166 _bindTreeElement(element) { 164 _bindTreeElement(element) {
167 if (element.treeOutline) 165 if (element.treeOutline)
168 console.error('Binding element for the second time: ' + new Error().stack) ; 166 console.error('Binding element for the second time: ' + new Error().stack) ;
169 element.treeOutline = this; 167 element.treeOutline = this;
170 element.onbind(); 168 element.onbind();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 * @param {number} paddingSize 214 * @param {number} paddingSize
217 */ 215 */
218 setPaddingSize(paddingSize) { 216 setPaddingSize(paddingSize) {
219 this._paddingSize = paddingSize; 217 this._paddingSize = paddingSize;
220 } 218 }
221 219
222 /** 220 /**
223 * @param {!Event} event 221 * @param {!Event} event
224 */ 222 */
225 _treeKeyDown(event) { 223 _treeKeyDown(event) {
226 if (event.target !== this.contentElement) 224 if (!this.selectedTreeElement || event.target !== this.selectedTreeElement.l istItemElement || event.shiftKey ||
227 return; 225 event.metaKey || event.ctrlKey)
228
229 if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ct rlKey)
230 return; 226 return;
231 227
232 var handled = false; 228 var handled = false;
233 if (event.key === 'ArrowUp' && !event.altKey) { 229 if (event.key === 'ArrowUp' && !event.altKey) {
234 handled = this.selectPrevious(); 230 handled = this.selectPrevious();
235 } else if (event.key === 'ArrowDown' && !event.altKey) { 231 } else if (event.key === 'ArrowDown' && !event.altKey) {
236 handled = this.selectNext(); 232 handled = this.selectNext();
237 } else if (event.key === 'ArrowLeft') { 233 } else if (event.key === 'ArrowLeft') {
238 handled = this.selectedTreeElement.collapseOrAscend(event.altKey); 234 handled = this.selectedTreeElement.collapseOrAscend(event.altKey);
239 } else if (event.key === 'ArrowRight') { 235 } else if (event.key === 'ArrowRight') {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 /** 318 /**
323 * @param {(string|!Node)=} title 319 * @param {(string|!Node)=} title
324 * @param {boolean=} expandable 320 * @param {boolean=} expandable
325 */ 321 */
326 constructor(title, expandable) { 322 constructor(title, expandable) {
327 /** @type {?UI.TreeOutline} */ 323 /** @type {?UI.TreeOutline} */
328 this.treeOutline = null; 324 this.treeOutline = null;
329 this.parent = null; 325 this.parent = null;
330 this.previousSibling = null; 326 this.previousSibling = null;
331 this.nextSibling = null; 327 this.nextSibling = null;
328 this._boundOnFocus = this._onFocus.bind(this);
329 this._boundOnBlur = this._onBlur.bind(this);
332 330
333 this._listItemNode = createElement('li'); 331 this._listItemNode = createElement('li');
334 this._titleElement = this._listItemNode.createChild('span', 'tree-element-ti tle'); 332 this._titleElement = this._listItemNode.createChild('span', 'tree-element-ti tle');
335 this._listItemNode.treeElement = this; 333 this._listItemNode.treeElement = this;
336 if (title) 334 if (title)
337 this.title = title; 335 this.title = title;
338 this._listItemNode.addEventListener('mousedown', this._handleMouseDown.bind( this), false); 336 this._listItemNode.addEventListener('mousedown', this._handleMouseDown.bind( this), false);
339 this._listItemNode.addEventListener('click', this._treeElementToggled.bind(t his), false); 337 this._listItemNode.addEventListener('click', this._treeElementToggled.bind(t his), false);
340 this._listItemNode.addEventListener('dblclick', this._handleDoubleClick.bind (this), false); 338 this._listItemNode.addEventListener('dblclick', this._handleDoubleClick.bind (this), false);
341 339
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 this._trailingIconsElement = createElementWithClass('div', 'trailing-icons '); 663 this._trailingIconsElement = createElementWithClass('div', 'trailing-icons ');
666 this._trailingIconsElement.classList.add('icons-container'); 664 this._trailingIconsElement.classList.add('icons-container');
667 this._listItemNode.appendChild(this._trailingIconsElement); 665 this._listItemNode.appendChild(this._trailingIconsElement);
668 this._ensureSelection(); 666 this._ensureSelection();
669 } 667 }
670 this._trailingIconsElement.removeChildren(); 668 this._trailingIconsElement.removeChildren();
671 for (var icon of icons) 669 for (var icon of icons)
672 this._trailingIconsElement.appendChild(icon); 670 this._trailingIconsElement.appendChild(icon);
673 } 671 }
674 672
675 /**
676 * @param {boolean} focused
677 */
678 _setFocused(focused) {
679 this._focused = focused;
680 this._listItemNode.classList.toggle('force-white-icons', focused);
681 }
682 673
683 /** 674 /**
684 * @return {string} 675 * @return {string}
685 */ 676 */
686 get tooltip() { 677 get tooltip() {
687 return this._tooltip || ''; 678 return this._tooltip || '';
688 } 679 }
689 680
690 /** 681 /**
691 * @param {string} x 682 * @param {string} x
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 1002
1012 if (this.treeOutline.selectedTreeElement) 1003 if (this.treeOutline.selectedTreeElement)
1013 this.treeOutline.selectedTreeElement.deselect(); 1004 this.treeOutline.selectedTreeElement.deselect();
1014 this.treeOutline.selectedTreeElement = null; 1005 this.treeOutline.selectedTreeElement = null;
1015 1006
1016 if (this.treeOutline._rootElement === this) 1007 if (this.treeOutline._rootElement === this)
1017 return false; 1008 return false;
1018 1009
1019 this.selected = true; 1010 this.selected = true;
1020 1011
1021 if (!omitFocus) 1012 this.treeOutline.selectedTreeElement = this;
1022 this.treeOutline.focus(); 1013 if (this.treeOutline._focusable)
1014 this._setFocusable(true);
1015 if (!omitFocus || this.treeOutline.contentElement.hasFocus())
1016 this.listItemElement.focus();
1023 1017
1024 // Focusing on another node may detach "this" from tree.
1025 if (!this.treeOutline)
1026 return false;
1027 this.treeOutline.selectedTreeElement = this;
1028 this._listItemNode.classList.add('selected'); 1018 this._listItemNode.classList.add('selected');
1029 this._setFocused(this.treeOutline._focused);
1030 this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementSelec ted, this); 1019 this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementSelec ted, this);
1031 return this.onselect(selectedByUser); 1020 return this.onselect(selectedByUser);
1032 } 1021 }
1033 1022
1034 /** 1023 /**
1024 * @param {boolean} focusable
1025 */
1026 _setFocusable(focusable) {
1027 if (focusable) {
1028 this._listItemNode.setAttribute('tabIndex', 0);
1029 this._listItemNode.addEventListener('focus', this._boundOnFocus, false);
1030 this._listItemNode.addEventListener('blur', this._boundOnBlur, false);
1031 } else {
1032 this._listItemNode.removeAttribute('tabIndex');
1033 this._listItemNode.removeEventListener('focus', this._boundOnFocus, false) ;
1034 this._listItemNode.removeEventListener('blur', this._boundOnBlur, false);
1035 }
1036 }
1037
1038 _onFocus() {
1039 this._listItemNode.classList.add('force-white-icons');
1040 }
1041
1042 _onBlur() {
1043 this._listItemNode.classList.remove('force-white-icons');
1044 }
1045
1046 /**
1035 * @param {boolean=} omitFocus 1047 * @param {boolean=} omitFocus
1036 */ 1048 */
1037 revealAndSelect(omitFocus) { 1049 revealAndSelect(omitFocus) {
1038 this.reveal(true); 1050 this.reveal(true);
1039 this.select(omitFocus); 1051 this.select(omitFocus);
1040 } 1052 }
1041 1053
1042 /** 1054 deselect() {
1043 * @param {boolean=} supressOnDeselect 1055 var hadFocus = this._listItemNode.hasFocus();
1044 */ 1056 this.selected = false;
1045 deselect(supressOnDeselect) { 1057 this._listItemNode.classList.remove('selected');
1046 if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !t his.selected) 1058 this._setFocusable(false);
1047 return;
1048 1059
1049 this.selected = false; 1060 if (this.treeOutline && this.treeOutline.selectedTreeElement === this) {
1050 this.treeOutline.selectedTreeElement = null; 1061 this.treeOutline.selectedTreeElement = null;
1051 this._listItemNode.classList.remove('selected'); 1062 if (hadFocus)
1052 this._setFocused(false); 1063 this.treeOutline.focus();
1064 }
1053 } 1065 }
1054 1066
1055 _populateIfNeeded() { 1067 _populateIfNeeded() {
1056 if (this.treeOutline && this._expandable && !this._children) { 1068 if (this.treeOutline && this._expandable && !this._children) {
1057 this._children = []; 1069 this._children = [];
1058 this.onpopulate(); 1070 this.onpopulate();
1059 } 1071 }
1060 } 1072 }
1061 1073
1062 onpopulate() { 1074 onpopulate() {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 var paddingLeftValue = window.getComputedStyle(this._listItemNode).paddingLe ft; 1206 var paddingLeftValue = window.getComputedStyle(this._listItemNode).paddingLe ft;
1195 console.assert(paddingLeftValue.endsWith('px')); 1207 console.assert(paddingLeftValue.endsWith('px'));
1196 var computedLeftPadding = parseFloat(paddingLeftValue); 1208 var computedLeftPadding = parseFloat(paddingLeftValue);
1197 var left = this._listItemNode.totalOffsetLeft() + computedLeftPadding; 1209 var left = this._listItemNode.totalOffsetLeft() + computedLeftPadding;
1198 return event.pageX >= left && event.pageX <= left + UI.TreeElement._ArrowTog gleWidth && this._expandable; 1210 return event.pageX >= left && event.pageX <= left + UI.TreeElement._ArrowTog gleWidth && this._expandable;
1199 } 1211 }
1200 }; 1212 };
1201 1213
1202 /** @const */ 1214 /** @const */
1203 UI.TreeElement._ArrowToggleWidth = 10; 1215 UI.TreeElement._ArrowToggleWidth = 10;
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/ui/treeoutline.css ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698