Bug 1555929 - Use handleEvent and on_<event name> pattern in MozTab and MozTabbrowserTab. r=bgrins

Differential Revision: https://phabricator.services.mozilla.com/D33272

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dão Gottwald 2019-05-31 17:32:26 +00:00
parent 97b937e201
commit b6e691a46f
2 changed files with 281 additions and 247 deletions

View File

@ -11,171 +11,15 @@ class MozTabbrowserTab extends MozElements.MozTab {
constructor() {
super();
this.addEventListener("mouseover", (event) => {
if (event.originalTarget.classList.contains("tab-close-button")) {
this.mOverCloseButton = true;
}
this._mouseenter();
});
this.addEventListener("mouseout", (event) => {
if (event.originalTarget.classList.contains("tab-close-button")) {
this.mOverCloseButton = false;
}
this._mouseleave();
});
this.addEventListener("dragstart", (event) => {
this.style.MozUserFocus = "";
}, true);
this.addEventListener("dragstart", (event) => {
if (this.mOverCloseButton) {
event.stopPropagation();
}
});
this.addEventListener("mousedown", (event) => {
let tabContainer = this.parentNode;
if (tabContainer._closeTabByDblclick &&
event.button == 0 &&
event.detail == 1) {
this._selectedOnFirstMouseDown = this.selected;
}
if (this.selected) {
this.style.MozUserFocus = "ignore";
} else if (event.originalTarget.classList.contains("tab-close-button") ||
event.originalTarget.classList.contains("tab-icon-sound") ||
event.originalTarget.classList.contains("tab-icon-overlay")) {
// Prevent tabbox.xml from selecting the tab.
event.stopPropagation();
}
if (event.button == 1) {
gBrowser.warmupTab(gBrowser._findTabToBlurTo(this));
}
if (event.button == 0 && tabContainer._multiselectEnabled) {
let shiftKey = event.shiftKey;
let accelKey = event.getModifierState("Accel");
if (shiftKey) {
const lastSelectedTab = gBrowser.lastMultiSelectedTab;
if (!accelKey) {
gBrowser.selectedTab = lastSelectedTab;
// Make sure selection is cleared when tab-switch doesn't happen.
gBrowser.clearMultiSelectedTabs(false);
}
gBrowser.addRangeToMultiSelectedTabs(lastSelectedTab, this);
// Prevent tabbox.xml from selecting the tab.
event.stopPropagation();
} else if (accelKey) {
// Ctrl (Cmd for mac) key is pressed
if (this.multiselected) {
gBrowser.removeFromMultiSelectedTabs(this, true);
} else if (this != gBrowser.selectedTab) {
gBrowser.addToMultiSelectedTabs(this, false);
gBrowser.lastMultiSelectedTab = this;
}
// Prevent tabbox.xml from selecting the tab.
event.stopPropagation();
} else if (!this.selected && this.multiselected) {
gBrowser.lockClearMultiSelectionOnce();
}
}
}, true);
this.addEventListener("mouseup", (event) => {
// Make sure that clear-selection is released.
// Otherwise selection using Shift key may be broken.
gBrowser.unlockClearMultiSelection();
this.style.MozUserFocus = "";
});
this.addEventListener("click", (event) => {
if (event.button != 0) {
return;
}
if (event.getModifierState("Accel") || event.shiftKey) {
return;
}
if (gBrowser.multiSelectedTabsCount > 0 &&
!event.originalTarget.classList.contains("tab-close-button") &&
!event.originalTarget.classList.contains("tab-icon-sound") &&
!event.originalTarget.classList.contains("tab-icon-overlay")) {
// Tabs were previously multi-selected and user clicks on a tab
// without holding Ctrl/Cmd Key
// Force positional attributes to update when the
// target (of the click) is the "active" tab.
let updatePositionalAttr = gBrowser.selectedTab == this;
gBrowser.clearMultiSelectedTabs(updatePositionalAttr);
}
if (event.originalTarget.classList.contains("tab-icon-sound") ||
(event.originalTarget.classList.contains("tab-icon-overlay") &&
(event.originalTarget.hasAttribute("soundplaying") ||
event.originalTarget.hasAttribute("muted") ||
event.originalTarget.hasAttribute("activemedia-blocked")))) {
if (this.multiselected) {
gBrowser.toggleMuteAudioOnMultiSelectedTabs(this);
} else {
this.toggleMuteAudio();
}
return;
}
if (event.originalTarget.classList.contains("tab-close-button")) {
if (this.multiselected) {
gBrowser.removeMultiSelectedTabs();
} else {
gBrowser.removeTab(this, {
animate: true,
byMouse: event.mozInputSource == MouseEvent.MOZ_SOURCE_MOUSE,
});
}
// This enables double-click protection for the tab container
// (see tabbrowser-tabs 'click' handler).
gBrowser.tabContainer._blockDblClick = true;
}
});
this.addEventListener("dblclick", (event) => {
if (event.button != 0) {
return;
}
// for the one-close-button case
if (event.originalTarget.classList.contains("tab-close-button")) {
event.stopPropagation();
}
let tabContainer = this.parentNode;
if (tabContainer._closeTabByDblclick &&
this._selectedOnFirstMouseDown &&
this.selected &&
!(event.originalTarget.classList.contains("tab-icon-sound") ||
event.originalTarget.classList.contains("tab-icon-overlay"))) {
gBrowser.removeTab(this, {
animate: true,
byMouse: event.mozInputSource == MouseEvent.MOZ_SOURCE_MOUSE,
});
}
}, true);
this.addEventListener("animationend", (event) => {
if (event.originalTarget.classList.contains("tab-loading-burst")) {
this.removeAttribute("bursting");
}
});
this.addEventListener("mouseover", this);
this.addEventListener("mouseout", this);
this.addEventListener("dragstart", this, true);
this.addEventListener("dragstart", this);
this.addEventListener("mousedown", this, true);
this.addEventListener("mouseup", this);
this.addEventListener("click", this);
this.addEventListener("dblclick", this, true);
this.addEventListener("animationend", this);
this._selectedOnFirstMouseDown = false;
@ -404,6 +248,175 @@ class MozTabbrowserTab extends MozElements.MozTab {
this._lastAccessed = this.selected ? Infinity : (aDate || Date.now());
}
on_mouseover(event) {
if (event.target.classList.contains("tab-close-button")) {
this.mOverCloseButton = true;
}
this._mouseenter();
}
on_mouseout(event) {
if (event.target.classList.contains("tab-close-button")) {
this.mOverCloseButton = false;
}
this._mouseleave();
}
on_dragstart(event) {
if (event.eventPhase == Event.CAPTURING_PHASE) {
this.style.MozUserFocus = "";
} else if (this.mOverCloseButton) {
event.stopPropagation();
}
}
on_mousedown(event) {
if (event.eventPhase == Event.BUBBLING_PHASE) {
super.on_mousedown(event);
return;
}
let tabContainer = this.parentNode;
if (tabContainer._closeTabByDblclick &&
event.button == 0 &&
event.detail == 1) {
this._selectedOnFirstMouseDown = this.selected;
}
if (this.selected) {
this.style.MozUserFocus = "ignore";
} else if (event.target.classList.contains("tab-close-button") ||
event.target.classList.contains("tab-icon-sound") ||
event.target.classList.contains("tab-icon-overlay")) {
// Prevent tabbox.js from selecting the tab.
event.stopPropagation();
}
if (event.button == 1) {
gBrowser.warmupTab(gBrowser._findTabToBlurTo(this));
}
if (event.button == 0 && tabContainer._multiselectEnabled) {
let shiftKey = event.shiftKey;
let accelKey = event.getModifierState("Accel");
if (shiftKey) {
const lastSelectedTab = gBrowser.lastMultiSelectedTab;
if (!accelKey) {
gBrowser.selectedTab = lastSelectedTab;
// Make sure selection is cleared when tab-switch doesn't happen.
gBrowser.clearMultiSelectedTabs(false);
}
gBrowser.addRangeToMultiSelectedTabs(lastSelectedTab, this);
// Prevent tabbox.xml from selecting the tab.
event.stopPropagation();
} else if (accelKey) {
// Ctrl (Cmd for mac) key is pressed
if (this.multiselected) {
gBrowser.removeFromMultiSelectedTabs(this, true);
} else if (this != gBrowser.selectedTab) {
gBrowser.addToMultiSelectedTabs(this, false);
gBrowser.lastMultiSelectedTab = this;
}
// Prevent tabbox.xml from selecting the tab.
event.stopPropagation();
} else if (!this.selected && this.multiselected) {
gBrowser.lockClearMultiSelectionOnce();
}
}
}
on_mouseup(event) {
// Make sure that clear-selection is released.
// Otherwise selection using Shift key may be broken.
gBrowser.unlockClearMultiSelection();
this.style.MozUserFocus = "";
}
on_click(event) {
if (event.button != 0) {
return;
}
if (event.getModifierState("Accel") || event.shiftKey) {
return;
}
if (gBrowser.multiSelectedTabsCount > 0 &&
!event.target.classList.contains("tab-close-button") &&
!event.target.classList.contains("tab-icon-sound") &&
!event.target.classList.contains("tab-icon-overlay")) {
// Tabs were previously multi-selected and user clicks on a tab
// without holding Ctrl/Cmd Key
// Force positional attributes to update when the
// target (of the click) is the "active" tab.
let updatePositionalAttr = gBrowser.selectedTab == this;
gBrowser.clearMultiSelectedTabs(updatePositionalAttr);
}
if (event.target.classList.contains("tab-icon-sound") ||
(event.target.classList.contains("tab-icon-overlay") &&
(event.target.hasAttribute("soundplaying") ||
event.target.hasAttribute("muted") ||
event.target.hasAttribute("activemedia-blocked")))) {
if (this.multiselected) {
gBrowser.toggleMuteAudioOnMultiSelectedTabs(this);
} else {
this.toggleMuteAudio();
}
return;
}
if (event.target.classList.contains("tab-close-button")) {
if (this.multiselected) {
gBrowser.removeMultiSelectedTabs();
} else {
gBrowser.removeTab(this, {
animate: true,
byMouse: event.mozInputSource == MouseEvent.MOZ_SOURCE_MOUSE,
});
}
// This enables double-click protection for the tab container
// (see tabbrowser-tabs 'click' handler).
gBrowser.tabContainer._blockDblClick = true;
}
}
on_dblclick(event) {
if (event.button != 0) {
return;
}
// for the one-close-button case
if (event.target.classList.contains("tab-close-button")) {
event.stopPropagation();
}
let tabContainer = this.parentNode;
if (tabContainer._closeTabByDblclick &&
this._selectedOnFirstMouseDown &&
this.selected &&
!(event.target.classList.contains("tab-icon-sound") ||
event.target.classList.contains("tab-icon-overlay"))) {
gBrowser.removeTab(this, {
animate: true,
byMouse: event.mozInputSource == MouseEvent.MOZ_SOURCE_MOUSE,
});
}
}
on_animationend(event) {
if (event.target.classList.contains("tab-loading-burst")) {
this.removeAttribute("bursting");
}
}
/**
* While it would make sense to track this in a field, the field will get nuked
* once the node is gone from the DOM, which causes us to think the tab is not
@ -419,8 +432,9 @@ class MozTabbrowserTab extends MozElements.MozTab {
let visibleTabs = tabContainer._getVisibleTabs();
let tabIndex = visibleTabs.indexOf(this);
if (this.selected)
if (this.selected) {
tabContainer._handleTabSelect();
}
if (tabIndex == 0) {
tabContainer._beforeHoveredTab = null;

View File

@ -255,87 +255,8 @@ MozElements.MozTab = class MozTab extends MozElements.BaseText {
constructor() {
super();
this.addEventListener("mousedown", (event) => {
if (event.button != 0 || this.disabled) {
return;
}
this.parentNode.ariaFocusedItem = null;
if (this != this.parentNode.selectedItem) { // Not selected yet
let stopwatchid = this.parentNode.getAttribute("stopwatchid");
if (stopwatchid) {
TelemetryStopwatch.start(stopwatchid);
}
// Call this before setting the 'ignorefocus' attribute because this
// will pass on focus if the formerly selected tab was focused as well.
this.parentNode._selectNewTab(this);
var isTabFocused = false;
try {
isTabFocused = (document.commandDispatcher.focusedElement == this);
} catch (e) {}
// Set '-moz-user-focus' to 'ignore' so that PostHandleEvent() can't
// focus the tab; we only want tabs to be focusable by the mouse if
// they are already focused. After a short timeout we'll reset
// '-moz-user-focus' so that tabs can be focused by keyboard again.
if (!isTabFocused) {
this.setAttribute("ignorefocus", "true");
setTimeout(tab => tab.removeAttribute("ignorefocus"), 0, this);
}
if (stopwatchid) {
TelemetryStopwatch.finish(stopwatchid);
}
}
// Otherwise this tab is already selected and we will fall
// through to mousedown behavior which sets focus on the current tab,
// Only a click on an already selected tab should focus the tab itself.
});
this.addEventListener("keydown", (event) => {
if (event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) {
return;
}
switch (event.keyCode) {
case KeyEvent.DOM_VK_LEFT: {
let direction = window.getComputedStyle(this.parentNode).direction;
this.parentNode.advanceSelectedTab(direction == "ltr" ? -1 : 1,
this.arrowKeysShouldWrap);
event.preventDefault();
} break;
case KeyEvent.DOM_VK_RIGHT: {
let direction = window.getComputedStyle(this.parentNode).direction;
this.parentNode.advanceSelectedTab(direction == "ltr" ? 1 : -1,
this.arrowKeysShouldWrap);
event.preventDefault();
} break;
case KeyEvent.DOM_VK_UP:
this.parentNode.advanceSelectedTab(-1, this.arrowKeysShouldWrap);
event.preventDefault();
break;
case KeyEvent.DOM_VK_DOWN:
this.parentNode.advanceSelectedTab(1, this.arrowKeysShouldWrap);
event.preventDefault();
break;
case KeyEvent.DOM_VK_HOME:
this.parentNode._selectNewTab(this.parentNode.children[0]);
event.preventDefault();
break;
case KeyEvent.DOM_VK_END:
let tabs = this.parentNode.children;
this.parentNode._selectNewTab(tabs[tabs.length - 1], -1);
event.preventDefault();
break;
}
});
this.addEventListener("mousedown", this);
this.addEventListener("keydown", this);
this.arrowKeysShouldWrap = /Mac/.test(navigator.platform);
}
@ -369,6 +290,105 @@ MozElements.MozTab = class MozTab extends MozElements.BaseText {
}
}
/**
* Passes DOM events to the on_<event type> methods.
*/
handleEvent(event) {
let methodName = "on_" + event.type;
if (methodName in this) {
this[methodName](event);
} else {
throw new Error("Unrecognized event: " + event.type);
}
}
on_mousedown(event) {
if (event.button != 0 || this.disabled) {
return;
}
this.parentNode.ariaFocusedItem = null;
if (this == this.parentNode.selectedItem) {
// This tab is already selected and we will fall
// through to mousedown behavior which sets focus on the current tab,
// Only a click on an already selected tab should focus the tab itself.
return;
}
let stopwatchid = this.parentNode.getAttribute("stopwatchid");
if (stopwatchid) {
TelemetryStopwatch.start(stopwatchid);
}
// Call this before setting the 'ignorefocus' attribute because this
// will pass on focus if the formerly selected tab was focused as well.
this.parentNode._selectNewTab(this);
var isTabFocused = false;
try {
isTabFocused = (document.commandDispatcher.focusedElement == this);
} catch (e) {}
// Set '-moz-user-focus' to 'ignore' so that PostHandleEvent() can't
// focus the tab; we only want tabs to be focusable by the mouse if
// they are already focused. After a short timeout we'll reset
// '-moz-user-focus' so that tabs can be focused by keyboard again.
if (!isTabFocused) {
this.setAttribute("ignorefocus", "true");
setTimeout(tab => tab.removeAttribute("ignorefocus"), 0, this);
}
if (stopwatchid) {
TelemetryStopwatch.finish(stopwatchid);
}
}
on_keydown(event) {
if (event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) {
return;
}
switch (event.keyCode) {
case KeyEvent.DOM_VK_LEFT: {
let direction = window.getComputedStyle(this.parentNode).direction;
this.parentNode.advanceSelectedTab(direction == "ltr" ? -1 : 1,
this.arrowKeysShouldWrap);
event.preventDefault();
break;
}
case KeyEvent.DOM_VK_RIGHT: {
let direction = window.getComputedStyle(this.parentNode).direction;
this.parentNode.advanceSelectedTab(direction == "ltr" ? 1 : -1,
this.arrowKeysShouldWrap);
event.preventDefault();
break;
}
case KeyEvent.DOM_VK_UP:
this.parentNode.advanceSelectedTab(-1, this.arrowKeysShouldWrap);
event.preventDefault();
break;
case KeyEvent.DOM_VK_DOWN:
this.parentNode.advanceSelectedTab(1, this.arrowKeysShouldWrap);
event.preventDefault();
break;
case KeyEvent.DOM_VK_HOME:
this.parentNode._selectNewTab(this.parentNode.children[0]);
event.preventDefault();
break;
case KeyEvent.DOM_VK_END: {
let tabs = this.parentNode.children;
this.parentNode._selectNewTab(tabs[tabs.length - 1], -1);
event.preventDefault();
break;
}
}
}
set value(val) {
this.setAttribute("value", val);
return val;