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

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

Issue 2805593002: DevTools: Navigate TabbedPane with arrow keys (Closed)
Patch Set: Created 3 years, 8 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google 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 are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * 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 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 25 matching lines...) Expand all
36 super(true); 36 super(true);
37 this.registerRequiredCSS('ui/tabbedPane.css'); 37 this.registerRequiredCSS('ui/tabbedPane.css');
38 this.element.classList.add('tabbed-pane'); 38 this.element.classList.add('tabbed-pane');
39 this.contentElement.classList.add('tabbed-pane-shadow'); 39 this.contentElement.classList.add('tabbed-pane-shadow');
40 this.contentElement.tabIndex = -1; 40 this.contentElement.tabIndex = -1;
41 this._headerElement = this.contentElement.createChild('div', 'tabbed-pane-he ader'); 41 this._headerElement = this.contentElement.createChild('div', 'tabbed-pane-he ader');
42 this._headerContentsElement = this._headerElement.createChild('div', 'tabbed -pane-header-contents'); 42 this._headerContentsElement = this._headerElement.createChild('div', 'tabbed -pane-header-contents');
43 this._tabSlider = createElementWithClass('div', 'tabbed-pane-tab-slider'); 43 this._tabSlider = createElementWithClass('div', 'tabbed-pane-tab-slider');
44 this._tabsElement = this._headerContentsElement.createChild('div', 'tabbed-p ane-header-tabs'); 44 this._tabsElement = this._headerContentsElement.createChild('div', 'tabbed-p ane-header-tabs');
45 this._tabsElement.setAttribute('role', 'tablist'); 45 this._tabsElement.setAttribute('role', 'tablist');
46 this._tabsElement.addEventListener('keydown', this._keyDown.bind(this), fals e);
46 this._contentElement = this.contentElement.createChild('div', 'tabbed-pane-c ontent'); 47 this._contentElement = this.contentElement.createChild('div', 'tabbed-pane-c ontent');
47 this._contentElement.setAttribute('role', 'tabpanel'); 48 this._contentElement.setAttribute('role', 'tabpanel');
48 this._contentElement.createChild('content'); 49 this._contentElement.createChild('content');
49 /** @type {!Array.<!UI.TabbedPaneTab>} */ 50 /** @type {!Array.<!UI.TabbedPaneTab>} */
50 this._tabs = []; 51 this._tabs = [];
51 /** @type {!Array.<!UI.TabbedPaneTab>} */ 52 /** @type {!Array.<!UI.TabbedPaneTab>} */
52 this._tabsHistory = []; 53 this._tabsHistory = [];
53 /** @type {!Map<string, !UI.TabbedPaneTab>} */ 54 /** @type {!Map<string, !UI.TabbedPaneTab>} */
54 this._tabsById = new Map(); 55 this._tabsById = new Map();
55 this._currentTabLocked = false; 56 this._currentTabLocked = false;
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 */ 537 */
537 _hideTabElement(tab) { 538 _hideTabElement(tab) {
538 this._tabsElement.removeChild(tab.tabElement); 539 this._tabsElement.removeChild(tab.tabElement);
539 tab._shown = false; 540 tab._shown = false;
540 } 541 }
541 542
542 _createDropDownButton() { 543 _createDropDownButton() {
543 var dropDownContainer = createElementWithClass('div', 'tabbed-pane-header-ta bs-drop-down-container'); 544 var dropDownContainer = createElementWithClass('div', 'tabbed-pane-header-ta bs-drop-down-container');
544 var chevronIcon = UI.Icon.create('largeicon-chevron', 'chevron-icon'); 545 var chevronIcon = UI.Icon.create('largeicon-chevron', 'chevron-icon');
545 dropDownContainer.appendChild(chevronIcon); 546 dropDownContainer.appendChild(chevronIcon);
547 dropDownContainer.addEventListener('click', this._onDropDownMouseDown.bind(t his));
aboxhall 2017/04/12 07:25:06 Do we need to make sure we don't run all this code
einbinder 2017/04/17 21:46:39 The ContextMenu consumes the mousedown event if it
aboxhall 2017/04/17 23:03:36 Oh right :)
546 dropDownContainer.addEventListener('mousedown', this._onDropDownMouseDown.bi nd(this)); 548 dropDownContainer.addEventListener('mousedown', this._onDropDownMouseDown.bi nd(this));
547 return dropDownContainer; 549 return dropDownContainer;
548 } 550 }
549 551
550 /** 552 /**
551 * @param {!Event} event 553 * @param {!Event} event
552 */ 554 */
553 _onDropDownMouseDown(event) { 555 _onDropDownMouseDown(event) {
554 if (event.which !== 1) 556 if (event.which !== 1)
555 return; 557 return;
556 var menu = new UI.ContextMenu(event); 558 var x = event.x;
559 var y = event.y;
560 // This wasn't a mouse event, manually set the position
aboxhall 2017/04/12 07:25:06 Can we just do this normally? It doesn't seem like
einbinder 2017/04/17 21:46:39 Done.
561 if (!x && !y) {
562 var rect = this._dropDownButton.getBoundingClientRect();
563 x = (rect.left + rect.right) / 2;
564 y = (rect.top + rect.bottom) / 2;
565 }
566 var menu = new UI.ContextMenu(event, false, x, y);
557 for (var i = 0; i < this._tabs.length; ++i) { 567 for (var i = 0; i < this._tabs.length; ++i) {
558 var tab = this._tabs[i]; 568 var tab = this._tabs[i];
559 if (tab._shown) 569 if (tab._shown)
560 continue; 570 continue;
561 menu.appendCheckboxItem(tab.title, this._dropDownMenuItemSelected.bind(thi s, tab), this._tabsHistory[0] === tab); 571 menu.appendCheckboxItem(tab.title, this._dropDownMenuItemSelected.bind(thi s, tab), this._tabsHistory[0] === tab);
562 } 572 }
563 menu.show(); 573 menu.show();
564 } 574 }
565 575
566 /** 576 /**
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 return; 759 return;
750 760
751 this._hideTab(this._currentTab); 761 this._hideTab(this._currentTab);
752 delete this._currentTab; 762 delete this._currentTab;
753 } 763 }
754 764
755 /** 765 /**
756 * @param {!UI.TabbedPaneTab} tab 766 * @param {!UI.TabbedPaneTab} tab
757 */ 767 */
758 _showTab(tab) { 768 _showTab(tab) {
769 tab.tabElement.tabIndex = 0;
759 tab.tabElement.classList.add('selected'); 770 tab.tabElement.classList.add('selected');
760 UI.ARIAUtils.setSelected(tab.tabElement, true); 771 UI.ARIAUtils.setSelected(tab.tabElement, true);
761 tab.view.show(this.element); 772 tab.view.show(this.element);
762 this._updateTabSlider(); 773 this._updateTabSlider();
763 } 774 }
764 775
765 _updateTabSlider() { 776 _updateTabSlider() {
766 if (!this._currentTab || !this._sliderEnabled) 777 if (!this._currentTab || !this._sliderEnabled)
767 return; 778 return;
768 var left = 0; 779 var left = 0;
769 for (var i = 0; i < this._tabs.length && this._currentTab !== this._tabs[i] && this._tabs[i]._shown; i++) 780 for (var i = 0; i < this._tabs.length && this._currentTab !== this._tabs[i] && this._tabs[i]._shown; i++)
770 left += this._tabs[i]._measuredWidth; 781 left += this._tabs[i]._measuredWidth;
771 var sliderWidth = this._currentTab._shown ? this._currentTab._measuredWidth : this._dropDownButton.offsetWidth; 782 var sliderWidth = this._currentTab._shown ? this._currentTab._measuredWidth : this._dropDownButton.offsetWidth;
772 var scaleFactor = window.devicePixelRatio >= 1.5 ? ' scaleY(0.75)' : ''; 783 var scaleFactor = window.devicePixelRatio >= 1.5 ? ' scaleY(0.75)' : '';
773 this._tabSlider.style.transform = 'translateX(' + left + 'px)' + scaleFactor ; 784 this._tabSlider.style.transform = 'translateX(' + left + 'px)' + scaleFactor ;
774 this._tabSlider.style.width = sliderWidth + 'px'; 785 this._tabSlider.style.width = sliderWidth + 'px';
775 786
776 if (this._tabSlider.parentElement !== this._headerContentsElement) 787 if (this._tabSlider.parentElement !== this._headerContentsElement)
777 this._headerContentsElement.appendChild(this._tabSlider); 788 this._headerContentsElement.appendChild(this._tabSlider);
778 } 789 }
779 790
780 /** 791 /**
781 * @param {!UI.TabbedPaneTab} tab 792 * @param {!UI.TabbedPaneTab} tab
782 */ 793 */
783 _hideTab(tab) { 794 _hideTab(tab) {
795 tab.tabElement.tabIndex = -1;
aboxhall 2017/04/12 07:25:06 Can just remove the tabIndex attribute instead (pr
einbinder 2017/04/17 21:46:39 Done.
784 tab.tabElement.classList.remove('selected'); 796 tab.tabElement.classList.remove('selected');
785 tab.tabElement.setAttribute('aria-selected', 'false'); 797 tab.tabElement.setAttribute('aria-selected', 'false');
786 tab.view.detach(); 798 tab.view.detach();
787 } 799 }
788 800
789 /** 801 /**
790 * @override 802 * @override
791 * @return {!Array.<!Element>} 803 * @return {!Array.<!Element>}
792 */ 804 */
793 elementsToRestoreScrollPositionsFor() { 805 elementsToRestoreScrollPositionsFor() {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 } 847 }
836 848
837 /** 849 /**
838 * @param {boolean} allow 850 * @param {boolean} allow
839 * @param {boolean=} automatic 851 * @param {boolean=} automatic
840 */ 852 */
841 setAllowTabReorder(allow, automatic) { 853 setAllowTabReorder(allow, automatic) {
842 this._allowTabReorder = allow; 854 this._allowTabReorder = allow;
843 this._automaticReorder = automatic; 855 this._automaticReorder = automatic;
844 } 856 }
857
858 /**
859 * @param {!Event} event
860 */
861 _keyDown(event) {
862 if (!this._currentTab)
863 return;
864 var nextTab = null;
aboxhall 2017/04/12 07:25:06 s/nextTab/nextTabElement/ ?
einbinder 2017/04/17 21:46:39 Done.
865 switch (event.keyCode) {
866 case UI.KeyboardShortcut.Keys.Up.code:
867 case UI.KeyboardShortcut.Keys.Left.code:
868 nextTab = this._currentTab.tabElement.previousElementSibling;
869 if (!nextTab && !this._dropDownButton.parentElement)
870 nextTab = this._currentTab.tabElement.parentElement.lastElementChild;
871 break;
872 case UI.KeyboardShortcut.Keys.Down.code:
873 case UI.KeyboardShortcut.Keys.Right.code:
874 nextTab = this._currentTab.tabElement.nextElementSibling;
875 if (!nextTab && !this._dropDownButton.parentElement)
876 nextTab = this._currentTab.tabElement.parentElement.firstElementChild;
877 break;
878 default:
879 return;
880 }
881 if (!nextTab) {
882 this._dropDownButton.click();
aboxhall 2017/04/12 07:25:06 This is pretty counter-intuitive - maybe extract t
einbinder 2017/04/17 21:46:39 I need the event to construct the ContextMenu. I t
aboxhall 2017/04/17 23:03:36 Ah, I see. Yeah it's a bit of a hack using a conte
883 return;
884 }
885 var tab = this._tabs.find(tab => tab.tabElement === nextTab);
886 this.selectTab(tab.id, true);
887 nextTab.focus();
888 }
845 }; 889 };
846 890
847 /** @enum {symbol} */ 891 /** @enum {symbol} */
848 UI.TabbedPane.Events = { 892 UI.TabbedPane.Events = {
849 TabSelected: Symbol('TabSelected'), 893 TabSelected: Symbol('TabSelected'),
850 TabClosed: Symbol('TabClosed'), 894 TabClosed: Symbol('TabClosed'),
851 TabOrderChanged: Symbol('TabOrderChanged') 895 TabOrderChanged: Symbol('TabOrderChanged')
852 }; 896 };
853 897
854 /** 898 /**
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1220 * @param {!Array.<string>} ids 1264 * @param {!Array.<string>} ids
1221 */ 1265 */
1222 closeTabs(tabbedPane, ids) {}, 1266 closeTabs(tabbedPane, ids) {},
1223 1267
1224 /** 1268 /**
1225 * @param {string} tabId 1269 * @param {string} tabId
1226 * @param {!UI.ContextMenu} contextMenu 1270 * @param {!UI.ContextMenu} contextMenu
1227 */ 1271 */
1228 onContextMenu(tabId, contextMenu) {} 1272 onContextMenu(tabId, contextMenu) {}
1229 }; 1273 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698