summaryrefslogtreecommitdiffstats
path: root/comm/mail/base/content/widgets/tabmail-tab.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/base/content/widgets/tabmail-tab.js')
-rw-r--r--comm/mail/base/content/widgets/tabmail-tab.js179
1 files changed, 179 insertions, 0 deletions
diff --git a/comm/mail/base/content/widgets/tabmail-tab.js b/comm/mail/base/content/widgets/tabmail-tab.js
new file mode 100644
index 0000000000..7de115149b
--- /dev/null
+++ b/comm/mail/base/content/widgets/tabmail-tab.js
@@ -0,0 +1,179 @@
+/* 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";
+
+/* global MozElements, MozXULElement */
+
+// Wrap in a block to prevent leaking to window scope.
+{
+ /**
+ * The MozTabmailTab widget behaves as a tab in the messenger window.
+ * It is used to navigate between different views. It displays information
+ * about the view: i.e. name and icon.
+ *
+ * @augments {MozElements.MozTab}
+ */
+ class MozTabmailTab extends MozElements.MozTab {
+ static get inheritedAttributes() {
+ return {
+ ".tab-background": "pinned,selected,titlechanged",
+ ".tab-line": "selected=visuallyselected",
+ ".tab-content": "pinned,selected,titlechanged,title=label",
+ ".tab-throbber": "fadein,pinned,busy,progress,selected",
+ ".tab-icon-image": "fadein,pinned,selected",
+ ".tab-label-container": "pinned,selected=visuallyselected",
+ ".tab-text": "text=label,accesskey,fadein,pinned,selected",
+ ".tab-close-button": "fadein,pinned,selected=visuallyselected",
+ };
+ }
+
+ connectedCallback() {
+ if (this.delayConnectedCallback() || this.hasChildNodes()) {
+ return;
+ }
+
+ this.setAttribute("is", "tabmail-tab");
+ this.appendChild(
+ MozXULElement.parseXULToFragment(
+ `
+ <stack class="tab-stack" flex="1">
+ <vbox class="tab-background">
+ <hbox class="tab-line"></hbox>
+ </vbox>
+ <html:div class="tab-content">
+ <hbox class="tab-throbber" role="presentation"></hbox>
+ <html:img class="tab-icon-image" alt="" role="presentation" />
+ <hbox class="tab-label-container"
+ onoverflow="this.setAttribute('textoverflow', 'true');"
+ onunderflow="this.removeAttribute('textoverflow');"
+ flex="1">
+ <label class="tab-text tab-label" role="presentation"></label>
+ </hbox>
+ <!-- We make the button non-focusable, otherwise each close
+ - button creates a new tab stop. See bug 1754097 -->
+ <html:button class="plain-button tab-close-button"
+ tabindex="-1"
+ title="&closeTab.label;">
+ <!-- Button title should provide the accessible context. -->
+ <html:img class="tab-close-icon" alt=""
+ src="chrome://global/skin/icons/close.svg" />
+ </html:button>
+ </html:div>
+ </stack>
+ `,
+ ["chrome://messenger/locale/tabmail.dtd"]
+ )
+ );
+
+ this.addEventListener(
+ "dragstart",
+ event => {
+ document.dragTab = this;
+ },
+ true
+ );
+
+ this.addEventListener(
+ "dragover",
+ event => {
+ document.dragTab = null;
+ },
+ true
+ );
+
+ let closeButton = this.querySelector(".tab-close-button");
+
+ // Prevent switching to the tab before closing it by stopping the
+ // mousedown event.
+ closeButton.addEventListener("mousedown", event => {
+ if (event.button != 0) {
+ return;
+ }
+ event.stopPropagation();
+ });
+
+ closeButton.addEventListener("click", () =>
+ document.getElementById("tabmail").removeTabByNode(this)
+ );
+
+ // Middle mouse button click on the tab also closes it.
+ this.addEventListener("click", event => {
+ if (event.button != 1) {
+ return;
+ }
+ document.getElementById("tabmail").removeTabByNode(this);
+ });
+
+ this.setAttribute("context", "tabContextMenu");
+
+ this.mCorrespondingMenuitem = null;
+
+ this.initializeAttributeInheritance();
+ }
+
+ get linkedBrowser() {
+ let tabmail = document.getElementById("tabmail");
+ let tab = tabmail._getTabContextForTabbyThing(this, false)[1];
+ return tabmail.getBrowserForTab(tab);
+ }
+
+ get mode() {
+ let tabmail = document.getElementById("tabmail");
+ let tab = tabmail._getTabContextForTabbyThing(this, false)[1];
+ return tab.mode;
+ }
+
+ /**
+ * Set the displayed icon for the tab.
+ *
+ * If a fallback source if given, it will be used instead if the given icon
+ * source is missing or loads with an error.
+ *
+ * If both sources are null, then the icon will become invisible.
+ *
+ * @param {string|null} iconSrc - The icon source to display in the tab, or
+ * null to just use the fallback source.
+ * @param {?string} [fallbackSrc] - The fallback source to display if the
+ * iconSrc is missing or broken.
+ */
+ setIcon(iconSrc, fallbackSrc) {
+ let icon = this.querySelector(".tab-icon-image");
+ if (!fallbackSrc) {
+ if (iconSrc) {
+ icon.setAttribute("src", iconSrc);
+ } else {
+ icon.removeAttribute("src");
+ }
+ return;
+ }
+ if (!iconSrc) {
+ icon.setAttribute("src", fallbackSrc);
+ return;
+ }
+ if (iconSrc == icon.getAttribute("src")) {
+ return;
+ }
+
+ // Set the tab image, and use the fallback if an error occurs.
+ // Set up a one time listener for either error or load.
+ let listener = event => {
+ icon.removeEventListener("error", listener);
+ icon.removeEventListener("load", listener);
+ if (event.type == "error") {
+ icon.setAttribute("src", fallbackSrc);
+ }
+ };
+ icon.addEventListener("error", listener);
+ icon.addEventListener("load", listener);
+ icon.setAttribute("src", iconSrc);
+ }
+ }
+
+ MozXULElement.implementCustomInterface(MozTabmailTab, [
+ Ci.nsIDOMXULSelectControlItemElement,
+ ]);
+
+ customElements.define("tabmail-tab", MozTabmailTab, { extends: "tab" });
+}