Bug 1469902 - Migrate <tabbox> to a Custom Element
MozReview-Commit-ID: HNDiMYmKgkg
--- a/toolkit/content/customElements.js
+++ b/toolkit/content/customElements.js
@@ -61,13 +61,14 @@ class MozXULElement extends XULElement {
}
// Attach the base class to the window so other scripts can use it:
window.MozXULElement = MozXULElement;
for (let script of [
"chrome://global/content/elements/stringbundle.js",
"chrome://global/content/elements/general.js",
+ "chrome://global/content/elements/tabbox.js",
]) {
Services.scriptloader.loadSubScript(script, window);
}
}
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -98,13 +98,14 @@ toolkit.jar:
content/global/bindings/timepicker.js (widgets/timepicker.js)
content/global/bindings/toolbar.xml (widgets/toolbar.xml)
content/global/bindings/toolbarbutton.xml (widgets/toolbarbutton.xml)
* content/global/bindings/tree.xml (widgets/tree.xml)
content/global/bindings/videocontrols.xml (widgets/videocontrols.xml)
* content/global/bindings/wizard.xml (widgets/wizard.xml)
content/global/elements/general.js (widgets/general.js)
content/global/elements/stringbundle.js (widgets/stringbundle.js)
+ content/global/elements/tabbox.js (widgets/tabbox.js)
#ifdef XP_MACOSX
content/global/macWindowMenu.js
#endif
content/global/gmp-sources/openh264.json (gmp-sources/openh264.json)
content/global/gmp-sources/widevinecdm.json (gmp-sources/widevinecdm.json)
new file mode 100644
--- /dev/null
+++ b/toolkit/content/widgets/tabbox.js
@@ -0,0 +1,184 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+{
+
+class MozTabbox extends MozXULElement {
+ connectedCallback() {
+ this._handleMetaAltArrows = /Mac/.test(navigator.platform);
+
+ this._eventNode = this;
+
+ switch (this.getAttribute("eventnode")) {
+ case "parent":
+ this._eventNode = this.parentNode;
+ break;
+ case "window":
+ this._eventNode = window;
+ break;
+ case "document":
+ this._eventNode = document;
+ break;
+ }
+ Services.els.addSystemEventListener(this._eventNode, "keydown", this, false);
+ this.disconnectedCallback = this.disconnectedCallback.bind(this);
+ window.addEventListener("unload", this.disconnectedCallback, { once: true });
+ }
+
+ set handleCtrlTab(val) {
+ this.setAttribute("handleCtrlTab", val);
+ return val;
+ }
+
+ get handleCtrlTab() {
+ return (this.getAttribute("handleCtrlTab") != "false");
+ }
+ /**
+ * _tabs and _tabpanels are deprecated, they exist only for
+ * backwards compatibility.
+ */
+ get _tabs() {
+ return this.tabs;
+ }
+
+ get _tabpanels() {
+ return this.tabpanels;
+ }
+
+ get tabs() {
+ if (this.hasAttribute("tabcontainer")) {
+ return document.getElementById(this.getAttribute("tabcontainer"));
+ }
+ return this.getElementsByTagNameNS(
+ "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
+ "tabs").item(0);
+ }
+
+ get tabpanels() {
+ return this.getElementsByTagNameNS(
+ "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
+ "tabpanels").item(0);
+ }
+
+ set selectedIndex(val) {
+ var tabs = this.tabs;
+ if (tabs)
+ tabs.selectedIndex = val;
+ this.setAttribute("selectedIndex", val);
+ return val;
+ }
+
+ get selectedIndex() {
+ var tabs = this.tabs;
+ return tabs ? tabs.selectedIndex : -1;
+ }
+
+ set selectedTab(val) {
+ if (val) {
+ var tabs = this.tabs;
+ if (tabs)
+ tabs.selectedItem = val;
+ }
+ return val;
+ }
+
+ get selectedTab() {
+ var tabs = this.tabs;
+ return tabs && tabs.selectedItem;
+ }
+
+ set selectedPanel(val) {
+ if (val) {
+ var tabpanels = this.tabpanels;
+ if (tabpanels)
+ tabpanels.selectedPanel = val;
+ }
+ return val;
+ }
+
+ get selectedPanel() {
+ var tabpanels = this.tabpanels;
+ return tabpanels && tabpanels.selectedPanel;
+ }
+
+ set eventNode(val) {
+ if (val != this._eventNode) {
+ const nsIEventListenerService =
+ Ci.nsIEventListenerService;
+ let els = Cc["@mozilla.org/eventlistenerservice;1"]
+ .getService(nsIEventListenerService);
+ els.addSystemEventListener(val, "keydown", this, false);
+ els.removeSystemEventListener(this._eventNode, "keydown", this, false);
+ this._eventNode = val;
+ }
+ return val;
+ }
+
+ get eventNode() {
+ return this._eventNode;
+ }
+
+ handleEvent(event) {
+ if (!event.isTrusted) {
+ // Don't let untrusted events mess with tabs.
+ return;
+ }
+
+ // Don't check if the event was already consumed because tab
+ // navigation should always work for better user experience.
+
+ switch (event.keyCode) {
+ case event.DOM_VK_TAB:
+ if (event.ctrlKey && !event.altKey && !event.metaKey)
+ if (this.tabs && this.handleCtrlTab) {
+ this.tabs.advanceSelectedTab(event.shiftKey ? -1 : 1, true);
+ event.preventDefault();
+ }
+ break;
+ case event.DOM_VK_PAGE_UP:
+ if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey &&
+ this.tabs) {
+ this.tabs.advanceSelectedTab(-1, true);
+ event.preventDefault();
+ }
+ break;
+ case event.DOM_VK_PAGE_DOWN:
+ if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey &&
+ this.tabs) {
+ this.tabs.advanceSelectedTab(1, true);
+ event.preventDefault();
+ }
+ break;
+ case event.DOM_VK_LEFT:
+ if (event.metaKey && event.altKey && !event.shiftKey && !event.ctrlKey)
+ if (this.tabs && this._handleMetaAltArrows) {
+ var offset = window.getComputedStyle(this)
+ .direction == "ltr" ? -1 : 1;
+ this.tabs.advanceSelectedTab(offset, true);
+ event.preventDefault();
+ }
+ break;
+ case event.DOM_VK_RIGHT:
+ if (event.metaKey && event.altKey && !event.shiftKey && !event.ctrlKey)
+ if (this.tabs && this._handleMetaAltArrows) {
+ offset = window.getComputedStyle(this)
+ .direction == "ltr" ? 1 : -1;
+ this.tabs.advanceSelectedTab(offset, true);
+ event.preventDefault();
+ }
+ break;
+ }
+ }
+
+ disconnectedCallback() {
+ window.removeEventListener("unload", this.disconnectedCallback, { once: true });
+ Services.els.removeSystemEventListener(this._eventNode, "keydown", this, false);
+ }
+}
+
+customElements.define("tabbox", MozTabbox);
+
+}
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -653,17 +653,16 @@ deck {
stack {
display: -moz-stack;
}
/********** tabbox *********/
tabbox {
- -moz-binding: url("chrome://global/content/bindings/tabbox.xml#tabbox");
-moz-box-orient: vertical;
}
tabs {
-moz-binding: url("chrome://global/content/bindings/tabbox.xml#tabs");
-moz-box-orient: horizontal;
}