Bug 489154 Allow openTab for contentTab tab panels to switch to, rather than open, existing tabs. r=mkmelin
authorMark Banner <bugzilla@standard8.plus.com>
Fri, 24 Apr 2009 19:53:47 +0100
changeset 2475 eaae6740e85e9da0b2720cbb2dec521b0d3881ad
parent 2474 ed6115c470eb97b9461cea60fed2a8dcfd959a97
child 2476 1a60aac99d5bb4d154711ffa3e29e01bbc2f0b71
push idunknown
push userunknown
push dateunknown
reviewersmkmelin
bugs489154
Bug 489154 Allow openTab for contentTab tab panels to switch to, rather than open, existing tabs. r=mkmelin
mail/base/content/specialTabs.js
mail/base/content/tabmail.xml
--- a/mail/base/content/specialTabs.js
+++ b/mail/base/content/specialTabs.js
@@ -64,16 +64,40 @@ var specialTabs = {
     name: "contentTab",
     perTabPanel: "vbox",
     modes: {
       contentTab: {
         type: "contentTab",
         maxTabs: 10
       }
     },
+    shouldSwitchTo: function onSwitchTo(aContentPage, aTitle) {
+      let tabmail = document.getElementById("tabmail");
+      let tabInfo = tabmail.tabInfo;
+
+      // Remove any anchors - especially for the about: pages, we just want
+      // to re-use the same tab.
+      let regEx = new RegExp("#.*");
+
+      let contentUrl = aContentPage.replace(regEx, "");
+
+      for (let selectedIndex = 0; selectedIndex < tabInfo.length;
+           ++selectedIndex) {
+        if (tabInfo[selectedIndex].mode.name == this.name &&
+            tabInfo[selectedIndex].panel.firstChild
+                                  .getAttribute("src")
+                                  .replace(regEx, "") == contentUrl) {
+          // Ensure we go to the correct location on the page.
+          tabInfo[selectedIndex].panel.firstChild
+                                .setAttribute("src", aContentPage);
+          return selectedIndex;
+        }
+      }
+      return -1;
+    },
     // XXX it would be nice to have an onload listener and set the title
     // after the load, however tabmail doesn't support that at the moment.
     openTab: function onTabOpened(aTab, aContentPage, aTitle) {
       // You can't dynamically change an iframe from a non-content to a content
       // type, therefore we dynamically create the element instead.
       let iframe = document.createElement("iframe");
       iframe.setAttribute("type", "content");
       iframe.setAttribute("flex", "1");
--- a/mail/base/content/tabmail.xml
+++ b/mail/base/content/tabmail.xml
@@ -124,16 +124,22 @@
     -     Generally, this would be the same as the mode name, but you can do as
     -     you please.
     - * isDefault: This should only be present and should be true for the tab
     -     mode that is the tab displayed automatically on startup.
     - * maxTabs: The maximum number of this mode that can be opened at a time.
     -     If this limit is reached, any additional calls to openTab for this
     -     mode will simply result in the first existing tab of this mode being
     -     displayed.
+    - * shouldSwitchTo(arguments...): Optional function. Called when
+    -     openTab is called on the top-level tabmail binding. It is used to
+    -     decide if the openTab function should switch to an existing tab or
+    -     actually open a new tab.
+    -     If the openTab function should switch to an existing tab, return the
+    -     index of that tab; otherwise return -1.
     - * openTab(aTab, arguments...): Called when a tab of the given mode is
     -     in the process of being opened.  aTab will have its "mode" attribute
     -     set to the mode definition of the tab mode being opened.  You should
     -     set the "title" attribute on it, and may set any other attributes
     -     you wish for your own use in subsequent functions.  Note that 'this'
     -     points to the tab type definition, not the mode definition as you
     -     might expect.  This allows you to place common logic code on the
     -     tab type for use by multiple modes and to defer to it.  Any arguments
@@ -295,17 +301,31 @@
             <![CDATA[
           let tabMode = this.tabModes[aTabModeName];
           // if we are already at our limit for this mode, show an existing one
           if (tabMode.tabs.length == tabMode.maxTabs) {
             let desiredTab = tabMode.tabs[0];
             this.tabContainer.selectedIndex = this.tabInfo.indexOf(desiredTab);
             return;
           }
-          
+
+          // If the mode wants us to, we should switch to an existing tab
+          // rather than open a new one.
+          let shouldSwitchToFunc = tabMode.shouldSwitchTo ||
+                                   tabMode.tabType.shouldSwitchTo;
+
+          if (shouldSwitchToFunc) {
+            let args = Array.prototype.slice.call(arguments, 1);
+            let tabIndex = shouldSwitchToFunc.apply(tabMode.tabType, args);
+            if (tabIndex >= 0) {
+              this.selectTabByIndex(null, tabIndex);
+              return;
+            }
+          }
+
           // we need to save the state before it gets corrupted
           this.saveCurrentTabState();
 
           let tab = {mode: tabMode, canClose: true};
           tabMode.tabs.push(tab);
 
           var t = document.createElementNS(
             "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",