diff --git a/content/treestyletab/hacks.js b/content/treestyletab/hacks.js index c91b0700..37ffd3a9 100644 --- a/content/treestyletab/hacks.js +++ b/content/treestyletab/hacks.js @@ -574,10 +574,7 @@ TreeStyleTabService.overrideExtensionsOnInitAfter = function TSTService_override window.getRowHeight.toSource().replace( 'var tabs = getBrowser().mTabContainer.childNodes;', ).replace( /tabs.item\(([^\)]+)\)/g, diff --git a/content/treestyletab/treestyletabbrowser.js b/content/treestyletab/treestyletabbrowser.js index ecd8c696..162e54e2 100644 --- a/content/treestyletab/treestyletabbrowser.js +++ b/content/treestyletab/treestyletabbrowser.js @@ -131,20 +131,19 @@ TreeStyleTabBrowser.prototype = { getTabById : function TSTBrowser_getTabById(aId, aTabBrowserChildren) { if (!aId) return null; + if (!aTabBrowserChildren) return aId in this._tabsCache ? this._tabsCache[aId] : null ; - if (aTabBrowserChildren.__treestyletab__linkedTabBrowser) - return aTabBrowserChildren.__treestyletab__linkedTabBrowser.treeStyleTab.getTabById(aId); - - return this.utils.getTabById(aId, aTabBrowserChildren); + var b = this.getTabBrowserFromChild(aTabBrowserChildren); + return b ? b.treeStyleTab.getTabById(aId) : null ; }, getParentTab : function TSTBrowser_getParentTab(aTab) /* PUBLIC API */ { if (!aTab) return null; - var parent = aTab.getAttribute(this.kPARENT); - return aTab.__treestyletab__linkedTabBrowser.treeStyleTab.getTabById(parent); + var b = this.getTabBrowserFromChild(aTab); + return b.treeStyleTab.getTabById(aTab.getAttribute(this.kPARENT)); }, // getParentTab : function TSTBrowser_getParentTab(aTab) /* PUBLIC API */ @@ -578,11 +577,10 @@ TreeStyleTabBrowser.prototype = { '{ if (!this.treeStyleTab.warnAboutClosingTabSubtreeOf(this.selectedTab)) return;' )); - let (tabs, i, maxi) { - tabs = this.getTabs(b); - for (i = 0, maxi = tabs.snapshotLength; i < maxi; i++) + let (tabs = this.getTabsArray(b)) { + for each (let tab in tabs) { - this.initTab(tabs.snapshotItem(i)); + this.initTab(tab); } } @@ -1673,7 +1671,7 @@ TreeStyleTabBrowser.prototype = { // for last tab closing, we have to open new tab manually if running on Firefox 3.0. if ( !('_beginRemoveTab' in b) && !('_endRemoveTab' in b) && // Firefox 3.0.x - this.getTabs(b).snapshotLength == 1 // last tab + this.getTabsArray(b).length == 1 // last tab ) { b.addTab('about:blank'); } @@ -1925,7 +1923,7 @@ TreeStyleTabBrowser.prototype = { var old = aEvent.detail; if (old > tab._tPos) old--; - old = this.getTabs(b).snapshotItem(old); + old = this.getTabsArray(b)[old]; prev = this.getPreviousSiblingTab(old); next = this.getNextSiblingTab(old); @@ -1963,7 +1961,7 @@ TreeStyleTabBrowser.prototype = { if (aOldPosition === void(0)) aOldPosition = aTab._tPos; var pos = this.getChildIndex(aTab, parent); - var oldPos = this.getChildIndex(this.getTabs(this.mTabBrowser).snapshotItem(aOldPosition), parent); + var oldPos = this.getChildIndex(this.getTabsArray(this.mTabBrowser)[aOldPosition], parent); var delta; if (pos == oldPos) { // no move? return; @@ -2677,10 +2675,10 @@ TreeStyleTabBrowser.prototype = { { if (!this.getTreePref('enableSubtreeIndent.allTabsPopup')) return; var items = aEvent.target.childNodes; - var tabs = this.getTabs(this.mTabBrowser); + var tabs = this.getTabsArray(this.mTabBrowser); for (var i = 0, maxi = items.length; i < maxi; i++) { - items[i].style.paddingLeft = tabs.snapshotItem(i).getAttribute(this.kNEST)+'em'; + items[i].style.paddingLeft = tabs[i].getAttribute(this.kNEST)+'em'; } }, @@ -2942,7 +2940,7 @@ TreeStyleTabBrowser.prototype = { var newRoots = []; var shouldClose = ( aInfo.action & this.kACTION_IMPORT && - this.getTabs(sourceBrowser).snapshotLength == draggedTabs.length + this.getTabsArray(sourceBrowser).length == draggedTabs.length ); var oldTabs = []; var newTabs = []; @@ -3155,7 +3153,7 @@ TreeStyleTabBrowser.prototype = { action : this.kACTIONS_FOR_DESTINATION | this.kACTION_IMPORT }; var tabsInfo = this.getDraggedTabsInfoFromOneTab(actionInfo, aTab); - return tabsInfo.draggedTabs.length == this.getTabs(this.mTabBrowser).snapshotLength; + return tabsInfo.draggedTabs.length == this.getTabsArray(this.mTabBrowser).length; }, /* commands */ diff --git a/modules/utils.js b/modules/utils.js index 0b94573d..99275105 100644 --- a/modules/utils.js +++ b/modules/utils.js @@ -689,11 +689,9 @@ var TreeStyleTabUtils = { .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShell); - var tabs = this.getTabs(b); - var tab; - for (var i = 0, maxi = tabs.snapshotLength; i < maxi; i++) + var tabs = this.getTabsArray(b); + for each (var tab in tabs) { - tab = tabs.snapshotItem(i); if (tab.linkedBrowser.docShell == docShell) return tab; } @@ -837,7 +835,7 @@ var TreeStyleTabUtils = { ).booleanValue; }, - getTabs : function TSTUtils_getTabs(aTabBrowserChild) + getTabs : function TSTUtils_getTabs(aTabBrowserChild) /* OBSOLETE */ { var b = this.getTabBrowserFromChild(aTabBrowserChild); return this.evaluateXPath( @@ -848,109 +846,84 @@ var TreeStyleTabUtils = { getTabsArray : function TSTUtils_getTabsArray(aTabBrowserChild) { - var tabs = this.getTabs(aTabBrowserChild); - var array = []; - for (var i = 0, maxi = tabs.snapshotLength; i < maxi; i++) - { - array.push(tabs.snapshotItem(i)); - } - return array; + var b = this.getTabBrowserFromChild(aTabBrowserChild); + return Array.slice(b.mTabContainer.childNodes); }, getFirstTab : function TSTUtils_getFirstTab(aTabBrowserChild) { var b = this.getTabBrowserFromChild(aTabBrowserChild); - return this.evaluateXPath( - 'child::xul:tab[1]', - b.mTabContainer, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE - ).singleNodeValue; + return b.mTabContainer.firstChild; }, getLastTab : function TSTUtils_getLastTab(aTabBrowserChild) { var b = this.getTabBrowserFromChild(aTabBrowserChild); - return this.evaluateXPath( - 'child::xul:tab[last()]', - b.mTabContainer, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE - ).singleNodeValue; + return b.mTabContainer.lastChild; }, getNextTab : function TSTUtils_getNextTab(aTab) { if (!aTab) return null; - return this.evaluateXPath( - 'following-sibling::xul:tab[1]', - aTab, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE - ).singleNodeValue; + var tab = aTab.nextSibling; + return (tab && tab.localName == 'tab') ? tab : null ; }, getPreviousTab : function TSTUtils_getPreviousTab(aTab) { if (!aTab) return null; - return this.evaluateXPath( - 'preceding-sibling::xul:tab[1]', - aTab, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE - ).singleNodeValue; + var tab = aTab.previousSibling; + return (tab && tab.localName == 'tab') ? tab : null ; }, getTabIndex : function TSTUtils_getTabIndex(aTab) { if (!aTab) return -1; - return this.evaluateXPath( - 'count(preceding-sibling::xul:tab)', - aTab, - Ci.nsIDOMXPathResult.NUMBER_TYPE - ).numberValue; + var b = this.getTabBrowserFromChild(aTab); + return this.getTabsArray(b).indexOf(aTab); }, getNextVisibleTab : function TSTUtils_getNextVisibleTab(aTab) { if (!aTab) return null; - if (!this.canCollapseSubtree(aTab)) + var b = this.getTabBrowserFromChild(aTab); + if (!this.canCollapseSubtree(b)) return this.getNextTab(aTab); - return this.evaluateXPath( - 'following-sibling::xul:tab[not(@'+this.kCOLLAPSED+'="true")][1]', - aTab, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE - ).singleNodeValue; + var tabs = this.getVisibleTabsArray(b); + if (tabs.indexOf(aTab) < 0) tabs.push(aTab); + tabs.sort(this.sortTabsByOrder); + + var index = tabs.indexOf(aTab); + return (index < tabs.length-1) ? tabs[index+1] : null ; }, getPreviousVisibleTab : function TSTUtils_getPreviousVisibleTab(aTab) { if (!aTab) return null; - if (!this.canCollapseSubtree(aTab)) + var b = this.getTabBrowserFromChild(aTab); + if (!this.canCollapseSubtree(b)) return this.getPreviousTab(aTab); - return this.evaluateXPath( - 'preceding-sibling::xul:tab[not(@'+this.kCOLLAPSED+'="true")][1]', - aTab, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE - ).singleNodeValue; + var tabs = this.getVisibleTabsArray(b); + if (tabs.indexOf(aTab) < 0) tabs.push(aTab); + tabs.sort(this.sortTabsByOrder); + + var index = tabs.indexOf(aTab); + return (index > 0) ? tabs[index-1] : null ; }, getLastVisibleTab : function TSTUtils_getLastVisibleTab(aTabBrowserChild) { var b = this.getTabBrowserFromChild(aTabBrowserChild); if (!b) return null; - - if (!this.canCollapseSubtree(b)) - return this.getLastTab(b); - - return this.evaluateXPath( - 'child::xul:tab[not(@'+this.kCOLLAPSED+'="true")][last()]', - b.mTabContainer, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE - ).singleNodeValue; + var tabs = this.getVisibleTabsArray(b); + return tabs.length ? tabs[tabs.length-1] : null ; }, - getVisibleTabs : function TSTUtils_getVisibleTabs(aTabBrowserChild) + getVisibleTabs : function TSTUtils_getVisibleTabs(aTabBrowserChild) /* OBSOLETE */ { var b = this.getTabBrowserFromChild(aTabBrowserChild); if (!this.canCollapseSubtree(b)) @@ -963,20 +936,22 @@ var TreeStyleTabUtils = { return XPathResult; }, + getVisibleTabsArray : function TSTUtils_getVisibleTabsArray(aTabBrowserChild) + { + var b = this.getTabBrowserFromChild(aTabBrowserChild); + var tabs = this.getTabsArray(b); + return this.canCollapseSubtree(b) ? + tabs.filter(function(aTab) { + return aTab.getAttribute(this.kCOLLAPSED) != 'true'; + }, this) : + tabs ; + }, + getVisibleIndex : function TSTUtils_getVisibleIndex(aTab) { if (!aTab) return -1; - - if (!this.canCollapseSubtree(aTab)) - return this.getTabIndex(aTab); - - return aTab.getAttribute(this.kCOLLAPSED) == 'true' ? - -1 : - this.evaluateXPath( - 'count(preceding-sibling::xul:tab[not(@'+this.kCOLLAPSED+'="true")])', - aTab, - Ci.nsIDOMXPathResult.NUMBER_TYPE - ).numberValue; + var b = this.getTabBrowserFromChild(aTab); + return this.getVisibleTabsArray(b).indexOf(aTab); }, /* notify "ready to open child tab(s)" */ @@ -1246,7 +1221,7 @@ var TreeStyleTabUtils = { var b = this.getTabBrowserFromChild(aTab); return ( this.shouldCloseTabSubtreeOf(aTab) && - this.getDescendantTabs(aTab).length + 1 == this.getTabs(b).snapshotLength + this.getDescendantTabs(aTab).length + 1 == this.getTabsArray(b).length ); }, shouldCloseLastTabSubTreeOf : function() { return this.shouldCloseLastTabSubtreeOf.apply(this, arguments); }, // obsolete, for backward compatibility diff --git a/tests/unit/treestyletab_tabUtils.test.js b/tests/unit/treestyletab_tabUtils.test.js index 22bf7dc7..6045ce4d 100644 --- a/tests/unit/treestyletab_tabUtils.test.js +++ b/tests/unit/treestyletab_tabUtils.test.js @@ -253,6 +253,22 @@ function test_getVisibleTabs() assert.equals(4, visibleResult.snapshotLength); } +function test_getVisibleTabsArray() +{ + tabs[1].setAttribute(sv.kCOLLAPSED, true); + tabs[3].setAttribute(sv.kCOLLAPSED, true); + + gBrowser.setAttribute(sv.kALLOW_COLLAPSE, true); + + var visibleTabs = sv.getVisibleTabsArray(tabs[0]); + assert.equals([tabs[0], tabs[2]], visibleTabs); + + gBrowser.removeAttribute(sv.kALLOW_COLLAPSE); + + visibleTabs = sv.getVisibleTabsArray(tabs[0]); + assert.equals([tabs[0], tabs[1], tabs[2], tabs[3]], visibleTabs); +} + function test_getVisibleIndex() { tabs[1].setAttribute(sv.kCOLLAPSED, true);