2009-12-25 11:51:24 -05:00
/ * * * * * * B E G I N L I C E N S E B L O C K * * * * *
2009-12-25 11:38:14 -05:00
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the "License" ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is the Tree Style Tab .
*
2012-10-13 14:31:06 -04:00
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi .
2013-01-04 01:17:22 -05:00
* Portions created by the Initial Developer are Copyright ( C ) 2010 - 2013
2009-12-25 11:38:14 -05:00
* the Initial Developer . All Rights Reserved .
*
2012-10-13 14:31:06 -04:00
* Contributor ( s ) : YUKI "Piro" Hiroshi < piro . outsider . reflex @ gmail . com >
2009-12-25 11:38:14 -05:00
*
* Alternatively , the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later ( the "GPL" ) , or
* the GNU Lesser General Public License Version 2.1 or later ( the "LGPL" ) ,
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above . If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL , and not to allow others to
* use your version of this file under the terms of the MPL , indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL . If you do not delete
* the provisions above , a recipient may use your version of this file under
* the terms of any one of the MPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * * /
2009-12-25 11:51:24 -05:00
2012-09-27 02:40:14 -04:00
const EXPORTED _SYMBOLS = [ 'TreeStyleTabBase' ] ;
2009-12-25 12:55:55 -05:00
2010-07-06 23:13:33 -04:00
const Cc = Components . classes ;
const Ci = Components . interfaces ;
2013-01-04 12:44:01 -05:00
const Cu = Components . utils ;
2013-01-03 23:04:02 -05:00
2013-01-04 12:44:01 -05:00
Cu . import ( 'resource://gre/modules/XPCOMUtils.jsm' ) ;
Cu . import ( 'resource://gre/modules/Services.jsm' ) ;
2013-01-05 21:50:55 -05:00
Cu . import ( 'resource://treestyletab-modules/constants.js' ) ;
2009-12-25 13:23:18 -05:00
2013-01-03 23:06:20 -05:00
XPCOMUtils . defineLazyGetter ( this , 'window' , function ( ) {
Cu . import ( 'resource://treestyletab-modules/lib/namespace.jsm' ) ;
return getNamespaceFor ( 'piro.sakura.ne.jp' ) ;
} ) ;
XPCOMUtils . defineLazyGetter ( this , 'prefs' , function ( ) {
Cu . import ( 'resource://treestyletab-modules/lib/prefs.js' ) ;
return window [ 'piro.sakura.ne.jp' ] . prefs ;
} ) ;
2011-05-25 23:11:08 -04:00
XPCOMUtils . defineLazyGetter ( this , 'jstimer' , function ( ) {
var jstimer = { } ;
2013-01-04 12:44:01 -05:00
Cu . import ( 'resource://treestyletab-modules/lib/jstimer.jsm' , jstimer ) ;
2011-05-25 23:11:08 -04:00
return jstimer ;
} ) ;
XPCOMUtils . defineLazyGetter ( this , 'extensions' , function ( ) {
2013-01-04 12:44:01 -05:00
Cu . import ( 'resource://treestyletab-modules/lib/extensions.js' , { } ) ;
2011-05-25 23:11:08 -04:00
return window [ 'piro.sakura.ne.jp' ] . extensions ;
} ) ;
XPCOMUtils . defineLazyGetter ( this , 'animationManager' , function ( ) {
2013-01-04 12:44:01 -05:00
Cu . import ( 'resource://treestyletab-modules/lib/animationManager.js' , { } ) ;
2011-05-25 23:11:08 -04:00
return window [ 'piro.sakura.ne.jp' ] . animationManager ;
} ) ;
XPCOMUtils . defineLazyGetter ( this , 'autoScroll' , function ( ) {
2013-01-04 12:44:01 -05:00
Cu . import ( 'resource://treestyletab-modules/lib/autoScroll.js' , { } ) ;
2011-05-25 23:11:08 -04:00
return window [ 'piro.sakura.ne.jp' ] . autoScroll ;
} ) ;
2013-01-02 19:41:23 -05:00
XPCOMUtils . defineLazyModuleGetter ( this , 'UninstallationListener' ,
'resource://treestyletab-modules/lib/UninstallationListener.js' ) ;
2013-01-03 23:07:32 -05:00
XPCOMUtils . defineLazyModuleGetter ( this , 'Deferred' ,
'resource://treestyletab-modules/lib/jsdeferred.js' ) ;
2012-11-11 08:48:42 -05:00
XPCOMUtils . defineLazyModuleGetter ( this , 'confirmWithPopup' , 'resource://treestyletab-modules/lib/confirmWithPopup.js' ) ;
XPCOMUtils . defineLazyModuleGetter ( this , 'utils' , 'resource://treestyletab-modules/utils.js' , 'TreeStyleTabUtils' ) ;
2012-10-19 08:38:35 -04:00
2013-01-05 11:52:47 -05:00
XPCOMUtils . defineLazyServiceGetter ( this , 'SessionStore' ,
'@mozilla.org/browser/sessionstore;1' , 'nsISessionStore' ) ;
2013-01-03 22:59:45 -05:00
if ( Services . appinfo . OS === 'WINNT' ) {
XPCOMUtils . defineLazyModuleGetter ( this , 'AeroPeek' ,
'resource://gre/modules/WindowsPreviewPerTab.jsm' , 'AeroPeek' ) ;
}
2013-01-04 01:30:08 -05:00
2012-09-27 02:40:14 -04:00
var TreeStyleTabBase = {
2013-01-05 21:50:55 -05:00
_ _proto _ _ : TreeStyleTabConstants ,
2009-12-25 11:51:24 -05:00
2013-01-04 01:30:08 -05:00
tabsHash : null ,
inWindowDestoructionProcess : false ,
2009-12-25 13:13:33 -05:00
/* base variables */
2012-08-30 13:46:50 -04:00
baseIndentVertical : 12 ,
baseIndentHorizontal : 4 ,
2009-12-25 13:13:33 -05:00
shouldDetectClickOnIndentSpaces : true ,
smoothScrollEnabled : true ,
smoothScrollDuration : 150 ,
animationEnabled : true ,
indentDuration : 200 ,
collapseDuration : 150 ,
2009-12-25 13:45:52 -05:00
shouldExpandTwistyArea : true ,
2010-07-25 12:13:19 -04:00
scrollToNewTabMode : false ,
2012-01-13 11:45:51 -05:00
counterRoleHorizontal : - 1 ,
counterRoleVertical : - 1 ,
2013-01-05 11:52:47 -05:00
get SessionStore ( ) {
return SessionStore ;
2009-12-25 12:55:55 -05:00
} ,
2011-12-02 15:01:38 -05:00
get FocusManager ( )
{
2012-01-13 03:38:12 -05:00
if ( ! this . _FocusManager ) {
this . _FocusManager = Cc [ '@mozilla.org/focus-manager;1' ] . getService ( Ci . nsIFocusManager ) ;
2011-12-02 15:01:38 -05:00
}
return this . _FocusManager ;
} ,
2012-01-13 03:38:12 -05:00
_FocusManager : null ,
2011-12-02 15:01:38 -05:00
2013-01-04 01:30:08 -05:00
get extensions ( ) { return extensions ; } ,
2011-05-25 23:11:08 -04:00
get animationManager ( ) { return animationManager ; } ,
get autoScroll ( ) { return autoScroll ; } ,
2011-05-25 23:15:47 -04:00
get Deferred ( ) { return Deferred ; } ,
2013-01-03 22:59:45 -05:00
get AeroPeek ( ) { return AeroPeek ; } , // for Windows
2013-01-04 01:30:08 -05:00
2013-03-05 12:56:29 -05:00
init : function TSTBase _init ( )
2009-12-25 11:38:14 -05:00
{
if ( this . _initialized ) return ;
2012-09-17 13:15:08 -04:00
this . isMac = Services . appinfo . OS == 'Darwin' ;
2010-10-24 23:06:02 -04:00
this . applyPlatformDefaultPrefs ( ) ;
2013-01-05 12:36:29 -05:00
utils . migratePrefs ( ) ;
2009-12-25 12:55:55 -05:00
2013-01-05 21:47:50 -05:00
prefs . addPrefListener ( this ) ;
2009-12-25 13:13:33 -05:00
2013-01-02 19:41:23 -05:00
this . initUninstallationListener ( ) ;
2012-08-30 14:48:00 -04:00
this . onPrefChange ( 'extensions.treestyletab.indent.vertical' ) ;
2012-08-30 13:46:50 -04:00
this . onPrefChange ( 'extensions.treestyletab.indent.horizontal' ) ;
2009-12-25 13:13:33 -05:00
this . onPrefChange ( 'extensions.treestyletab.clickOnIndentSpaces.enabled' ) ;
this . onPrefChange ( 'browser.tabs.loadFolderAndReplace.override' ) ;
this . onPrefChange ( 'browser.tabs.insertRelatedAfterCurrent.override' ) ;
2010-03-31 06:34:30 -04:00
this . onPrefChange ( 'extensions.stm.tabBarMultiRows.override' ) ; // Super Tab Mode
2009-12-25 13:13:33 -05:00
this . onPrefChange ( 'extensions.treestyletab.tabbar.scroll.smooth' ) ;
this . onPrefChange ( 'extensions.treestyletab.tabbar.scroll.duration' ) ;
2010-07-25 12:13:19 -04:00
this . onPrefChange ( 'extensions.treestyletab.tabbar.scrollToNewTab.mode' ) ;
2011-03-24 22:42:50 -04:00
this . onPrefChange ( 'extensions.treestyletab.tabbar.narrowScrollbar.size' ) ;
2012-11-27 13:34:57 -05:00
this . onPrefChange ( 'browser.tabs.animate' ) ;
2009-12-25 13:13:33 -05:00
this . onPrefChange ( 'extensions.treestyletab.animation.indent.duration' ) ;
this . onPrefChange ( 'extensions.treestyletab.animation.collapse.duration' ) ;
this . onPrefChange ( 'extensions.treestyletab.twisty.expandSensitiveArea' ) ;
2012-01-13 11:45:51 -05:00
this . onPrefChange ( 'extensions.treestyletab.counter.role.horizontal' ) ;
this . onPrefChange ( 'extensions.treestyletab.counter.role.vertical' ) ;
2010-04-06 09:38:05 -04:00
2011-10-27 15:17:22 -04:00
try {
this . overrideExtensions ( ) ;
}
catch ( e ) {
dump ( e + '\n' ) ;
}
2009-12-25 11:38:14 -05:00
} ,
_initialized : false ,
2013-01-04 01:30:08 -05:00
2013-03-05 12:56:29 -05:00
applyPlatformDefaultPrefs : function TSTBase _applyPlatformDefaultPrefs ( )
2010-10-24 23:06:02 -04:00
{
2012-09-17 13:15:08 -04:00
var OS = Services . appinfo . OS ;
2010-11-18 02:04:31 -05:00
var processed = { } ;
2013-01-05 21:56:20 -05:00
var originalKeys = prefs . getDescendant ( 'extensions.treestyletab.platform.' + OS ) ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = originalKeys . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let originalKey = originalKeys [ i ] ;
2012-02-04 13:15:38 -05:00
let key = originalKey . replace ( 'platform.' + OS + '.' , '' ) ;
2013-01-05 21:47:50 -05:00
prefs . setDefaultPref ( key , prefs . getPref ( originalKey ) ) ;
2010-11-18 02:04:31 -05:00
processed [ key ] = true ;
2012-02-04 13:15:38 -05:00
}
2013-01-05 21:56:20 -05:00
originalKeys = prefs . getDescendant ( 'extensions.treestyletab.platform.default' ) ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = originalKeys . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let originalKey = originalKeys [ i ] ;
2012-02-04 13:15:38 -05:00
let key = originalKey . replace ( 'platform.default.' , '' ) ;
2010-11-18 02:04:31 -05:00
if ( ! ( key in processed ) )
2013-01-05 21:47:50 -05:00
prefs . setDefaultPref ( key , prefs . getPref ( originalKey ) ) ;
2012-02-04 13:15:38 -05:00
}
2010-10-24 23:06:02 -04:00
} ,
2013-01-05 12:36:29 -05:00
2013-01-05 21:50:55 -05:00
initUninstallationListener : function TSTWindow _initUninstallationListener ( )
2013-01-02 19:41:23 -05:00
{
var restorePrefs = function ( ) {
// Remove pref listener before restore backuped prefs.
prefs . removePrefListener ( this ) ;
let restorePrefs = [
'browser.tabs.loadFolderAndReplace' ,
'browser.tabs.insertRelatedAfterCurrent' ,
'extensions.stm.tabBarMultiRows' // Super Tab Mode
] ;
for ( let i = 0 , maxi = restorePrefs . length ; i < maxi ; i ++ )
{
let pref = restorePrefs [ i ] ;
let backup = prefs . getPref ( pref + '.backup' ) ;
if ( backup === null ) continue ;
// restore user preference.
prefs . setPref ( pref , backup ) ;
// clear backup pref.
prefs . clearPref ( pref + '.backup' ) ;
}
} . bind ( this ) ;
new UninstallationListener ( {
id : 'treestyletab@piro.sakura.ne.jp' ,
onuninstalled : restorePrefs ,
ondisabled : restorePrefs
} ) ;
} ,
2013-01-04 01:30:08 -05:00
2013-03-05 12:56:29 -05:00
overrideExtensions : function TSTBase _overrideExtensions ( )
2011-10-27 15:17:22 -04:00
{
2012-05-01 15:56:45 -04:00
// Scriptish
// https://addons.mozilla.org/firefox/addon/scriptish/
2012-10-23 12:43:56 -04:00
if ( utils . getTreePref ( 'compatibility.Scriptish' ) ) {
2012-05-01 15:56:45 -04:00
try {
2013-01-04 12:44:01 -05:00
let tabModule = Cu . import ( 'resource://scriptish/utils/Scriptish_openInTab.js' , { } ) ;
2012-05-01 15:56:45 -04:00
let Scriptish _openInTab = tabModule . Scriptish _openInTab ;
tabModule . Scriptish _openInTab = function ( aURL , aLoadInBackground , aReuse , aChromeWin ) {
aChromeWin . TreeStyleTabService . readyToOpenChildTabNow ( aChromeWin . gBrowser ) ;
return Scriptish _openInTab . apply ( this , arguments ) ;
} ;
}
catch ( e ) {
}
}
2011-10-27 15:17:22 -04:00
} ,
2013-03-05 12:56:29 -05:00
updateNarrowScrollbarStyle : function TSTBase _updateNarrowScrollbarStyle ( )
2011-03-24 22:42:50 -04:00
{
const SSS = Cc [ '@mozilla.org/content/style-sheet-service;1' ]
. getService ( Ci . nsIStyleSheetService ) ;
if ( this . lastAgentSheet &&
SSS . sheetRegistered ( this . lastAgentSheet , SSS . AGENT _SHEET ) )
SSS . unregisterSheet ( this . lastAgentSheet , SSS . AGENT _SHEET ) ;
const style = 'data:text/css,' + encodeURIComponent (
2012-10-12 03:46:37 -04:00
( '@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");' +
'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
' .tabbrowser-arrowscrollbox' +
' > scrollbox' +
' > scrollbar[orient="vertical"],' +
'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
' .tabbrowser-arrowscrollbox' +
' > scrollbox' +
' > scrollbar[orient="vertical"] * {' +
' max-width: %SIZE%;' +
' min-width: %SIZE%;' +
'}' +
'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
' .tabbrowser-arrowscrollbox' +
' > scrollbox' +
' > scrollbar[orient="vertical"] {' +
' font-size: %SIZE%;' +
'}' +
'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
' .tabbrowser-arrowscrollbox' +
' > scrollbox' +
' > scrollbar[orient="vertical"] * {' +
' padding-left: 0;' +
' padding-right: 0;' +
' margin-left: 0;' +
' margin-right: 0;' +
'}' +
'%FORCE_NARROW_SCROLLBAR%' )
2011-12-09 03:55:15 -05:00
. replace ( /%FORCE_NARROW_SCROLLBAR%/g ,
2012-10-23 12:43:56 -04:00
utils . getTreePref ( 'tabbar.narrowScrollbar.overrideSystemAppearance' ) ?
2011-12-09 03:55:15 -05:00
this . kOVERRIDE _SYSTEM _SCROLLBAR _APPEARANCE : '' )
2011-03-24 22:42:50 -04:00
. replace ( /%MODE%/g , this . kMODE )
. replace ( /%NARROW%/g , this . kNARROW _SCROLLBAR )
2012-10-23 12:43:56 -04:00
. replace ( /%SIZE%/g , utils . getTreePref ( 'tabbar.narrowScrollbar.size' ) )
2011-03-24 22:42:50 -04:00
) ;
this . lastAgentSheet = this . makeURIFromSpec ( style ) ;
SSS . loadAndRegisterSheet ( this . lastAgentSheet , SSS . AGENT _SHEET ) ;
} ,
2012-10-12 03:46:37 -04:00
kOVERRIDE _SYSTEM _SCROLLBAR _APPEARANCE :
'tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]' +
' .tabbrowser-arrowscrollbox' +
' > scrollbox' +
' > scrollbar[orient="vertical"] {' +
' appearance: none;' +
' -moz-appearance: none;' +
' background: ThreeDFace;' +
' border: 1px solid ThreeDShadow;' +
'}' ,
2011-03-24 22:42:50 -04:00
lastAgentSheet : null ,
2010-04-06 09:38:05 -04:00
2013-01-04 01:30:08 -05:00
/* references to the owner */
2009-12-25 12:55:55 -05:00
get browserWindow ( )
2010-05-08 01:37:41 -04:00
{
return this . topBrowserWindow ;
} ,
get topBrowserWindow ( )
2009-12-25 12:55:55 -05:00
{
2012-09-17 23:01:39 -04:00
return Services . wm . getMostRecentWindow ( 'navigator:browser' ) ;
2009-12-25 12:55:55 -05:00
} ,
2010-05-08 01:37:41 -04:00
get browserWindows ( )
{
var windows = [ ] ;
2012-09-17 23:01:39 -04:00
var targets = Services . wm . getZOrderDOMWindowEnumerator ( 'navigator:browser' , true ) ;
2010-05-08 01:37:41 -04:00
// By the bug 156333, we cannot find windows by their Z order on Linux.
// https://bugzilla.mozilla.org/show_bug.cgi?id=156333
if ( ! targets . hasMoreElements ( ) )
2012-09-17 23:01:39 -04:00
targets = Services . wm . getEnumerator ( 'navigator:browser' ) ;
2010-05-08 01:37:41 -04:00
while ( targets . hasMoreElements ( ) )
{
let target = targets . getNext ( )
2011-07-20 06:59:59 -04:00
. QueryInterface ( Ci . nsIDOMWindow ) ;
if ( 'nsIDOMWindowInternal' in Ci ) // for Firefox 7 or olders
target = target . QueryInterface ( Ci . nsIDOMWindowInternal ) ;
2010-05-08 01:37:41 -04:00
windows . push ( target ) ;
}
return windows ;
} ,
2009-12-25 12:55:55 -05:00
get browser ( )
{
var w = this . browserWindow ;
return ! w ? null :
'SplitBrowser' in w ? w . SplitBrowser . activeBrowser :
w . gBrowser ;
} ,
2011-05-04 04:10:02 -04:00
get window ( )
2011-04-06 08:05:59 -04:00
{
return this . browser . ownerDocument . defaultView ;
} ,
2013-01-04 01:30:08 -05:00
2010-12-01 19:02:27 -05:00
get currentDragSession ( )
{
return Cc [ '@mozilla.org/widget/dragservice;1' ]
. getService ( Ci . nsIDragService )
. getCurrentSession ( ) ;
} ,
2013-01-04 01:30:08 -05:00
/* calculated behaviors */
2013-03-05 12:56:29 -05:00
dropLinksOnTabBehavior : function TSTBase _dropLinksOnTabBehavior ( )
2009-12-25 13:45:52 -05:00
{
2012-10-23 12:43:56 -04:00
var behavior = utils . getTreePref ( 'dropLinksOnTab.behavior' ) ;
2009-12-25 13:45:52 -05:00
if ( behavior & this . kDROPLINK _FIXED ) return behavior ;
var checked = { value : false } ;
2012-09-17 23:10:11 -04:00
var newChildTab = Services . prompt . confirmEx ( this . browserWindow ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'dropLinkOnTab.title' ) ,
utils . treeBundle . getString ( 'dropLinkOnTab.text' ) ,
2012-09-17 23:10:11 -04:00
( Services . prompt . BUTTON _TITLE _IS _STRING * Services . prompt . BUTTON _POS _0 ) +
( Services . prompt . BUTTON _TITLE _IS _STRING * Services . prompt . BUTTON _POS _1 ) ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'dropLinkOnTab.openNewChildTab' ) ,
utils . treeBundle . getString ( 'dropLinkOnTab.loadInTheTab' ) ,
2009-12-25 13:45:52 -05:00
null ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'dropLinkOnTab.never' ) ,
2009-12-25 13:45:52 -05:00
checked
) == 0 ;
behavior = newChildTab ? this . kDROPLINK _NEWTAB : this . kDROPLINK _LOAD ;
if ( checked . value )
2012-10-23 12:43:56 -04:00
utils . setTreePref ( 'dropLinksOnTab.behavior' , behavior ) ;
2009-12-25 13:45:52 -05:00
return behavior
} ,
kDROPLINK _ASK : 0 ,
kDROPLINK _FIXED : 1 + 2 ,
kDROPLINK _LOAD : 1 ,
kDROPLINK _NEWTAB : 2 ,
2013-03-05 12:56:29 -05:00
openGroupBookmarkBehavior : function TSTBase _openGroupBookmarkBehavior ( )
2009-12-25 13:45:52 -05:00
{
2012-10-23 12:43:56 -04:00
var behavior = utils . getTreePref ( 'openGroupBookmark.behavior' ) ;
2009-12-25 13:45:52 -05:00
if ( behavior & this . kGROUP _BOOKMARK _FIXED ) return behavior ;
var dummyTabFlag = behavior & this . kGROUP _BOOKMARK _USE _DUMMY ;
var checked = { value : false } ;
2012-09-17 23:10:11 -04:00
var button = Services . prompt . confirmEx ( this . browserWindow ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'openGroupBookmarkBehavior.title' ) ,
utils . treeBundle . getString ( 'openGroupBookmarkBehavior.text' ) ,
2012-09-17 23:10:11 -04:00
( Services . prompt . BUTTON _TITLE _IS _STRING * Services . prompt . BUTTON _POS _0 ) +
( Services . prompt . BUTTON _TITLE _IS _STRING * Services . prompt . BUTTON _POS _1 ) +
( Services . prompt . BUTTON _TITLE _IS _STRING * Services . prompt . BUTTON _POS _2 ) ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'openGroupBookmarkBehavior.subTree' ) ,
utils . treeBundle . getString ( 'openGroupBookmarkBehavior.separate' ) ,
utils . treeBundle . getString ( 'openGroupBookmarkBehavior.replace' ) ,
utils . treeBundle . getString ( 'openGroupBookmarkBehavior.never' ) ,
2009-12-25 13:45:52 -05:00
checked
) ;
if ( button < 0 ) button = 1 ;
var behaviors = [
this . kGROUP _BOOKMARK _SUBTREE | dummyTabFlag ,
this . kGROUP _BOOKMARK _SEPARATE ,
this . kGROUP _BOOKMARK _REPLACE
] ;
behavior = behaviors [ button ] ;
if ( checked . value ) {
2012-10-23 12:43:56 -04:00
utils . setTreePref ( 'openGroupBookmark.behavior' , behavior ) ;
2013-01-05 21:47:50 -05:00
prefs . setPref ( 'browser.tabs.loadFolderAndReplace' , ! ! ( behavior & this . kGROUP _BOOKMARK _REPLACE ) ) ;
2009-12-25 13:45:52 -05:00
}
return behavior ;
} ,
kGROUP _BOOKMARK _ASK : 0 ,
kGROUP _BOOKMARK _FIXED : 1 + 2 + 4 ,
kGROUP _BOOKMARK _SUBTREE : 1 ,
kGROUP _BOOKMARK _SEPARATE : 2 ,
kGROUP _BOOKMARK _REPLACE : 4 ,
2010-07-29 22:39:51 -04:00
kGROUP _BOOKMARK _USE _DUMMY : 256 ,
kGROUP _BOOKMARK _USE _DUMMY _FORCE : 1024 ,
2009-12-25 13:45:52 -05:00
kGROUP _BOOKMARK _DONT _RESTORE _TREE _STRUCTURE : 512 ,
2010-07-29 22:39:51 -04:00
kGROUP _BOOKMARK _EXPAND _ALL _TREE : 2048 ,
2009-12-25 13:45:52 -05:00
2013-03-05 12:56:29 -05:00
bookmarkDroppedTabsBehavior : function TSTBase _bookmarkDroppedTabsBehavior ( )
2010-12-20 06:41:22 -05:00
{
2012-10-23 12:43:56 -04:00
var behavior = utils . getTreePref ( 'bookmarkDroppedTabs.behavior' ) ;
2010-12-20 06:41:22 -05:00
if ( behavior & this . kBOOKMARK _DROPPED _TABS _FIXED ) return behavior ;
var checked = { value : false } ;
2012-09-17 23:10:11 -04:00
var button = Services . prompt . confirmEx ( this . browserWindow ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'bookmarkDroppedTabs.title' ) ,
utils . treeBundle . getString ( 'bookmarkDroppedTabs.text' ) ,
2012-09-17 23:10:11 -04:00
( Services . prompt . BUTTON _TITLE _IS _STRING * Services . prompt . BUTTON _POS _0 ) +
( Services . prompt . BUTTON _TITLE _IS _STRING * Services . prompt . BUTTON _POS _1 ) ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'bookmarkDroppedTabs.bookmarkAll' ) ,
utils . treeBundle . getString ( 'bookmarkDroppedTabs.bookmarkOnlyParent' ) ,
2010-12-20 06:41:22 -05:00
null ,
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'bookmarkDroppedTabs.never' ) ,
2010-12-20 06:41:22 -05:00
checked
) ;
if ( button < 0 ) button = 1 ;
var behaviors = [
this . kBOOKMARK _DROPPED _TABS _ALL ,
this . kBOOKMARK _DROPPED _TABS _ONLY _PARENT
] ;
behavior = behaviors [ button ] ;
if ( checked . value )
2012-10-23 12:43:56 -04:00
utils . setTreePref ( 'bookmarkDroppedTabs.behavior' , behavior ) ;
2010-12-20 06:41:22 -05:00
return behavior ;
} ,
kBOOKMARK _DROPPED _TABS _ASK : 0 ,
2011-04-07 14:38:31 -04:00
kBOOKMARK _DROPPED _TABS _FIXED : 1 | 2 ,
2010-12-20 06:41:22 -05:00
kBOOKMARK _DROPPED _TABS _ALL : 1 ,
kBOOKMARK _DROPPED _TABS _ONLY _PARENT : 2 ,
2013-03-05 12:56:29 -05:00
askUndoCloseTabSetBehavior : function TSTBase _askUndoCloseTabSetBehavior ( aRestoredTab , aCount )
2009-12-26 23:56:16 -05:00
{
2010-11-10 11:14:04 -05:00
var behavior = this . undoCloseTabSetBehavior ;
if ( behavior & this . kUNDO _CLOSE _SET ) behavior ^= this . kUNDO _CLOSE _SET ;
var self = this ;
2012-01-17 23:56:50 -05:00
return confirmWithPopup ( {
browser : aRestoredTab . linkedBrowser ,
2013-01-02 21:08:25 -05:00
label : utils . treeBundle . getFormattedString ( 'undoCloseTabSetBehavior.label' , [ aCount ] ) ,
2010-11-10 12:13:18 -05:00
value : 'treestyletab-undo-close-tree' ,
2012-01-17 23:56:50 -05:00
image : 'chrome://treestyletab/content/res/icon.png' ,
2010-11-10 12:13:18 -05:00
buttons : [
2013-01-02 21:08:25 -05:00
utils . treeBundle . getString ( 'undoCloseTabSetBehavior.restoreOnce' ) ,
utils . treeBundle . getString ( 'undoCloseTabSetBehavior.restoreForever' ) ,
utils . treeBundle . getString ( 'undoCloseTabSetBehavior.ignoreForever' )
2012-01-20 10:35:53 -05:00
] ,
persistence : - 1 // don't hide even if the tab is restored after the panel is shown.
2010-11-10 11:14:04 -05:00
} )
. next ( function ( aButtonIndex ) {
2012-01-17 23:56:50 -05:00
if ( aButtonIndex < 2 ) {
2010-11-10 11:14:04 -05:00
behavior |= self . kUNDO _CLOSE _SET ;
2010-11-10 12:05:02 -05:00
}
2012-01-17 23:56:50 -05:00
if ( aButtonIndex > 0 ) {
2010-11-10 12:05:02 -05:00
behavior ^= self . kUNDO _ASK ;
2012-10-23 12:43:56 -04:00
utils . setTreePref ( 'undoCloseTabSet.behavior' , behavior ) ;
2010-11-10 12:05:02 -05:00
}
2010-11-10 11:14:04 -05:00
return behavior ;
} ) ;
} ,
get undoCloseTabSetBehavior ( )
{
2012-10-23 12:43:56 -04:00
return utils . getTreePref ( 'undoCloseTabSet.behavior' ) ;
2009-12-26 23:56:16 -05:00
} ,
kUNDO _ASK : 1 ,
kUNDO _CLOSE _SET : 2 ,
kUNDO _CLOSE _FULL _SET : 256 ,
2013-01-04 01:30:08 -05:00
/* utilities */
2013-03-05 12:56:29 -05:00
doAndWaitDOMEvent : function TSTBase _doAndWaitDOMEvent ( )
2011-01-21 12:15:04 -05:00
{
var type , target , delay , task ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = arguments . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let arg = arguments [ i ] ;
2012-02-04 13:15:38 -05:00
switch ( typeof arg )
2011-01-21 12:15:04 -05:00
{
case 'string' :
2012-02-04 13:15:38 -05:00
type = arg ;
continue ;
2011-01-21 12:15:04 -05:00
case 'number' :
2012-02-04 13:15:38 -05:00
delay = arg ;
continue ;
2011-01-21 12:15:04 -05:00
case 'function' :
2012-02-04 13:15:38 -05:00
task = arg ;
continue ;
2011-01-21 12:15:04 -05:00
default :
2012-02-04 13:15:38 -05:00
target = arg ;
continue ;
2011-01-21 12:15:04 -05:00
}
2012-02-04 13:15:38 -05:00
}
2011-01-21 12:15:04 -05:00
if ( ! target || ! type ) {
if ( task ) task ( ) ;
return ;
}
var done = false ;
var listener = function ( aEvent ) {
2011-05-25 23:11:08 -04:00
jstimer . setTimeout ( function ( ) {
2011-01-21 12:15:04 -05:00
done = true ;
} , delay || 0 ) ;
target . removeEventListener ( type , listener , false ) ;
} ;
if ( task )
2011-03-18 16:00:12 -04:00
Deferred . next ( function ( ) {
2011-01-21 12:15:04 -05:00
try {
task ( ) ;
}
catch ( e ) {
dump ( e + '\n' ) ;
target . removeEventListener ( type , listener , false ) ;
done = true ;
}
2012-02-06 12:13:46 -05:00
} ) . error ( this . defaultDeferredErrorHandler ) ;
2011-01-21 12:15:04 -05:00
target . addEventListener ( type , listener , false ) ;
var thread = Components
. classes [ '@mozilla.org/thread-manager;1' ]
. getService ( )
. mainThread ;
while ( ! done )
{
//dump('WAIT '+type+' '+Date.now()+'\n');
thread . processNextEvent ( true ) ;
}
} ,
2013-03-05 12:56:29 -05:00
findOffsetParent : function TSTBase _findOffsetParent ( aNode )
2011-05-04 04:10:02 -04:00
{
var parent = aNode . parentNode ;
var doc = aNode . ownerDocument || aNode ;
var view = doc . defaultView ;
while ( parent && parent instanceof Ci . nsIDOMElement )
{
let position = view . getComputedStyle ( parent , null ) . getPropertyValue ( 'position' ) ;
if ( position != 'static' )
return parent ;
parent = parent . parentNode ;
}
return doc . documentElement ;
} ,
2013-03-05 12:56:29 -05:00
assertBeforeDestruction : function TSTBase _assertBeforeDestruction ( aNotDestructed )
2012-01-23 14:07:56 -05:00
{
if ( aNotDestructed )
return ;
var message = 'ERROR: accessed after destruction!' ;
var error = new Error ( message ) ;
dump ( message + '\n' + error . stack + '\n' ) ;
throw error ;
} ,
2013-01-04 01:30:08 -05:00
2013-03-05 12:56:29 -05:00
defaultDeferredErrorHandler : function TSTBase _defaultDeferredErrorHandler ( aError )
2012-02-06 12:13:46 -05:00
{
if ( aError . stack )
2013-01-04 12:44:01 -05:00
Cu . reportError ( aError . message + '\n' + aError . stack ) ;
2012-02-06 12:13:46 -05:00
else
2013-01-04 12:44:01 -05:00
Cu . reportError ( aError ) ;
2012-02-06 12:13:46 -05:00
} ,
2009-12-25 12:55:55 -05:00
// event
2013-03-05 12:56:29 -05:00
isNewTabAction : function TSTBase _isNewTabAction ( aEvent )
2009-12-25 12:55:55 -05:00
{
return aEvent . button == 1 || ( aEvent . button == 0 && this . isAccelKeyPressed ( aEvent ) ) ;
} ,
2013-03-05 12:56:29 -05:00
isAccelKeyPressed : function TSTBase _isAccelKeyPressed ( aEvent )
2009-12-25 12:55:55 -05:00
{
if ( // this is releasing of the accel key!
( aEvent . type == 'keyup' ) &&
( aEvent . keyCode == ( this . isMac ? Ci . nsIDOMKeyEvent . DOM _VK _META : Ci . nsIDOMKeyEvent . DOM _VK _CONTROL ) )
) {
return false ;
}
return this . isMac ?
( aEvent . metaKey || ( aEvent . keyCode == Ci . nsIDOMKeyEvent . DOM _VK _META ) ) :
( aEvent . ctrlKey || ( aEvent . keyCode == Ci . nsIDOMKeyEvent . DOM _VK _CONTROL ) ) ;
} ,
2013-03-05 12:56:29 -05:00
isCopyAction : function TSTBase _isCopyAction ( aEvent )
2010-04-06 22:13:58 -04:00
{
return this . isAccelKeyPressed ( aEvent ) ||
( aEvent . dataTransfer && aEvent . dataTransfer . dropEffect == 'copy' ) ;
} ,
2013-03-05 12:56:29 -05:00
isEventFiredOnClosebox : function TSTBase _isEventFiredOnClosebox ( aEvent )
2009-12-25 12:55:55 -05:00
{
return this . evaluateXPath (
'ancestor-or-self::*[contains(concat(" ", normalize-space(@class), " "), " tab-close-button ")]' ,
aEvent . originalTarget || aEvent . target ,
Ci . nsIDOMXPathResult . BOOLEAN _TYPE
) . booleanValue ;
} ,
2013-03-05 12:56:29 -05:00
isEventFiredOnClickable : function TSTBase _isEventFiredOnClickable ( aEvent )
2009-12-25 12:55:55 -05:00
{
return this . evaluateXPath (
2012-01-06 05:38:38 -05:00
'ancestor-or-self::*[contains(" button toolbarbutton scrollbar nativescrollbar popup menupopup panel tooltip splitter textbox ", concat(" ", local-name(), " "))]' ,
aEvent . originalTarget ,
Ci . nsIDOMXPathResult . BOOLEAN _TYPE
) . booleanValue ;
} ,
2013-03-05 12:56:29 -05:00
isEventFiredOnScrollbar : function TSTBase _isEventFiredOnScrollbar ( aEvent )
2012-01-06 05:38:38 -05:00
{
return this . evaluateXPath (
'ancestor-or-self::*[local-name()="scrollbar" or local-name()="nativescrollbar"]' ,
2009-12-25 12:55:55 -05:00
aEvent . originalTarget ,
Ci . nsIDOMXPathResult . BOOLEAN _TYPE
) . booleanValue ;
} ,
2009-12-25 13:45:52 -05:00
2013-03-05 12:56:29 -05:00
isEventFiredOnTwisty : function TSTBase _isEventFiredOnTwisty ( aEvent )
2009-12-25 13:45:52 -05:00
{
var tab = this . getTabFromEvent ( aEvent ) ;
2010-02-04 03:56:21 -05:00
if ( ! tab ||
! this . hasChildTabs ( tab ) ||
! this . canCollapseSubtree ( tab ) )
return false ;
2009-12-25 13:45:52 -05:00
2010-12-27 04:58:02 -05:00
var twisty = tab . ownerDocument . getAnonymousElementByAttribute ( tab , 'class' , this . kTWISTY ) ;
if ( ! twisty )
return false ;
2009-12-25 13:45:52 -05:00
2010-12-27 04:58:02 -05:00
var box = twisty . boxObject ;
2012-02-04 13:15:38 -05:00
var left = box . screenX ;
var top = box . screenY ;
var right = left + box . width ;
var bottom = top + box . height ;
var favicon = this . getFaviconRect ( tab ) ;
2011-01-15 23:46:18 -05:00
if ( ! box . width || ! box . height ) {
2012-02-04 13:15:38 -05:00
left = favicon . left ;
top = favicon . top ;
right = favicon . right ;
bottom = favicon . bottom ;
2011-01-15 23:46:18 -05:00
}
2012-02-02 15:27:57 -05:00
else if (
2011-01-22 14:03:39 -05:00
this . shouldExpandTwistyArea &&
2011-01-15 22:01:59 -05:00
! this . _expandTwistyAreaBlockers . length
) {
2012-02-04 13:15:38 -05:00
left = Math . min ( left , favicon . left ) ;
top = Math . min ( top , favicon . top ) ;
right = Math . max ( right , favicon . right ) ;
bottom = Math . max ( bottom , favicon . bottom ) ;
2010-12-27 04:58:02 -05:00
}
var x = aEvent . screenX ;
var y = aEvent . screenY ;
2012-02-04 13:15:38 -05:00
return ( x >= left && x <= right && y >= top && y <= bottom ) ;
} ,
2013-03-05 12:56:29 -05:00
getFaviconRect : function TSTBase _getFaviconRect ( aTab )
2012-02-04 13:15:38 -05:00
{
var icon = aTab . ownerDocument . getAnonymousElementByAttribute ( aTab , 'class' , 'tab-icon-image' ) ;
var iconBox = icon . boxObject ;
var iconRect = {
left : iconBox . screenX ,
top : iconBox . screenY ,
right : iconBox . screenX + iconBox . width ,
bottom : iconBox . screenY + iconBox . height
} ;
var throbber = aTab . ownerDocument . getAnonymousElementByAttribute ( aTab , 'class' , 'tab-throbber' ) ;
var throbberBox = throbber . boxObject ;
var throbberRect = {
left : throbberBox . screenX ,
top : throbberBox . screenY ,
right : throbberBox . screenX + throbberBox . width ,
bottom : throbberBox . screenY + throbberBox . height
} ;
if ( ! iconBox . width && ! iconBox . height )
return throbberRect ;
if ( ! throbberBox . width && ! throbberBox . height )
return iconRect ;
return {
left : Math . min ( throbberRect . left , iconRect . left ) ,
right : Math . max ( throbberRect . right , iconRect . right ) ,
top : Math . min ( throbberRect . top , iconRect . top ) ,
bottom : Math . max ( throbberRect . bottom , iconRect . bottom )
} ;
2009-12-25 13:45:52 -05:00
} ,
2011-01-21 12:15:04 -05:00
// called with target(nsIDOMEventTarget), document(nsIDOMDocument), type(string) and data(object)
2013-03-05 12:56:29 -05:00
fireDataContainerEvent : function TSTBase _fireDataContainerEvent ( )
2011-01-11 05:29:14 -05:00
{
var target , document , type , data , canBubble , cancellable ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = arguments . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let arg = arguments [ i ] ;
2012-02-04 13:15:38 -05:00
if ( typeof arg == 'boolean' ) {
2011-01-11 05:29:14 -05:00
if ( canBubble === void ( 0 ) )
2012-02-04 13:15:38 -05:00
canBubble = arg ;
2011-01-11 05:29:14 -05:00
else
2012-02-04 13:15:38 -05:00
cancellable = arg ;
2011-01-11 05:29:14 -05:00
}
2012-02-04 13:15:38 -05:00
else if ( typeof arg == 'string' )
type = arg ;
else if ( arg instanceof Ci . nsIDOMDocument )
document = arg ;
else if ( arg instanceof Ci . nsIDOMEventTarget )
target = arg ;
2011-01-11 05:29:14 -05:00
else
2012-02-04 13:15:38 -05:00
data = arg ;
}
2011-01-11 05:29:14 -05:00
if ( ! target )
target = document ;
if ( ! document )
document = target . ownerDocument || target ;
var event = document . createEvent ( 'DataContainerEvent' ) ;
event . initEvent ( type , canBubble , cancellable ) ;
2012-02-04 16:31:03 -05:00
var properties = Object . keys ( data ) ;
for ( let i = 0 , maxi = properties . length ; i < maxi ; i ++ )
2011-01-11 05:29:14 -05:00
{
2012-02-04 16:31:03 -05:00
let property = properties [ i ] ;
let value = data [ property ] ;
2012-02-04 14:03:28 -05:00
event . setData ( property , value ) ;
event [ property ] = value ; // for backward compatibility
2011-01-11 05:29:14 -05:00
}
return target . dispatchEvent ( event ) ;
} ,
2013-03-05 12:56:29 -05:00
registerExpandTwistyAreaBlocker : function TSTBase _registerExpandTwistyAreaBlocker ( aBlocker ) /* PUBLIC API */
2009-12-25 13:45:52 -05:00
{
2009-12-25 13:48:07 -05:00
if ( this . _expandTwistyAreaBlockers . indexOf ( aBlocker ) < 0 )
this . _expandTwistyAreaBlockers . push ( aBlocker ) ;
2009-12-25 13:45:52 -05:00
} ,
2009-12-25 13:48:07 -05:00
_expandTwistyAreaBlockers : [ ] ,
2009-12-25 13:45:52 -05:00
2013-03-05 12:56:29 -05:00
registerExpandTwistyAreaAllowance : function TSTBase _registerExpandTwistyAreaAllowance ( aAllowance ) /* PUBLIC API, obsolete, for backward compatibility */
2009-12-25 13:45:52 -05:00
{
this . registerExpandTwistyAreaBlocker ( aAllowance . toSource ( ) ) ;
} ,
2009-12-25 12:55:55 -05:00
// string
2013-03-05 12:56:29 -05:00
makeNewId : function TSTBase _makeNewId ( )
2009-12-25 12:55:55 -05:00
{
return 'tab-<' + Date . now ( ) + '-' + parseInt ( Math . random ( ) * 65000 ) + '>' ;
} ,
2013-03-05 12:56:29 -05:00
makeNewClosedSetId : function TSTBase _makeNewId ( )
2009-12-25 15:07:00 -05:00
{
return 'tabs-closed-set-<' + Date . now ( ) + '-' + parseInt ( Math . random ( ) * 65000 ) + '>' ;
} ,
2013-03-05 12:56:29 -05:00
makeURIFromSpec : function TSTBase _makeURIFromSpec ( aURI )
2009-12-25 12:55:55 -05:00
{
var newURI ;
aURI = aURI || '' ;
if ( aURI && String ( aURI ) . indexOf ( 'file:' ) == 0 ) {
2012-09-17 11:44:51 -04:00
var fileHandler = Services . io . getProtocolHandler ( 'file' ) . QueryInterface ( Ci . nsIFileProtocolHandler ) ;
2009-12-25 12:55:55 -05:00
var tempLocalFile = fileHandler . getFileFromURLSpec ( aURI ) ;
2012-09-17 11:44:51 -04:00
newURI = Services . io . newFileURI ( tempLocalFile ) ;
2009-12-25 12:55:55 -05:00
}
else {
if ( ! /^\w+\:/ . test ( aURI ) ) aURI = 'http://' + aURI ;
2012-09-17 11:44:51 -04:00
newURI = Services . io . newURI ( aURI , null , null ) ;
2009-12-25 12:55:55 -05:00
}
return newURI ;
} ,
2013-03-05 12:56:29 -05:00
getGroupTabURI : function TSTBase _getGroupTabURI ( aTitle )
2009-12-25 12:55:55 -05:00
{
return 'about:treestyletab-group' + ( aTitle === void ( 0 ) ? '' : '?' + encodeURIComponent ( aTitle ) ) ;
} ,
// xpath
NSResolver : {
lookupNamespaceURI : function ( aPrefix )
{
switch ( aPrefix )
{
case 'xul' :
return 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' ;
case 'html' :
case 'xhtml' :
return 'http://www.w3.org/1999/xhtml' ;
case 'xlink' :
return 'http://www.w3.org/1999/xlink' ;
default :
return '' ;
}
}
} ,
2013-03-05 12:56:29 -05:00
evaluateXPath : function TSTBase _evaluateXPath ( aExpression , aContext , aType )
2009-12-25 12:55:55 -05:00
{
if ( ! aType ) aType = Ci . nsIDOMXPathResult . ORDERED _NODE _SNAPSHOT _TYPE ;
try {
var XPathResult = ( aContext . ownerDocument || aContext ) . evaluate (
aExpression ,
( aContext || document ) ,
this . NSResolver ,
aType ,
null
) ;
}
catch ( e ) {
return {
singleNodeValue : null ,
snapshotLength : 0 ,
snapshotItem : function ( ) {
return null
}
} ;
}
return XPathResult ;
} ,
2013-03-05 12:56:29 -05:00
getArrayFromXPathResult : function TSTBase _getArrayFromXPathResult ( aXPathResult )
2009-12-25 12:55:55 -05:00
{
var max = aXPathResult . snapshotLength ;
var array = new Array ( max ) ;
if ( ! max ) return array ;
for ( var i = 0 ; i < max ; i ++ )
{
array [ i ] = aXPathResult . snapshotItem ( i ) ;
}
return array ;
} ,
2009-12-25 13:13:33 -05:00
/* Session Store API */
2013-03-05 12:56:29 -05:00
getTabValue : function TSTBase _getTabValue ( aTab , aKey )
2009-12-25 13:13:33 -05:00
{
var value = '' ;
try {
2013-01-05 11:52:47 -05:00
value = SessionStore . getTabValue ( aTab , aKey ) ;
2009-12-25 13:13:33 -05:00
}
catch ( e ) {
}
if ( this . useTMPSessionAPI ) {
let TMPValue = aTab . getAttribute ( this . kTMP _SESSION _DATA _PREFIX + aKey ) ;
if ( TMPValue ) value = TMPValue ;
}
return value ;
} ,
2013-03-05 12:56:29 -05:00
setTabValue : function TSTBase _setTabValue ( aTab , aKey , aValue )
2009-12-25 13:13:33 -05:00
{
if ( ! aValue ) return this . deleteTabValue ( aTab , aKey ) ;
aTab . setAttribute ( aKey , aValue ) ;
try {
this . checkCachedSessionDataExpiration ( aTab ) ;
2013-01-05 11:52:47 -05:00
SessionStore . setTabValue ( aTab , aKey , aValue ) ;
2009-12-25 13:13:33 -05:00
}
catch ( e ) {
}
if ( this . useTMPSessionAPI )
aTab . setAttribute ( this . kTMP _SESSION _DATA _PREFIX + aKey , aValue ) ;
return aValue ;
} ,
2013-03-05 12:56:29 -05:00
deleteTabValue : function TSTBase _deleteTabValue ( aTab , aKey )
2009-12-25 13:13:33 -05:00
{
aTab . removeAttribute ( aKey ) ;
try {
this . checkCachedSessionDataExpiration ( aTab ) ;
2013-01-05 11:52:47 -05:00
SessionStore . setTabValue ( aTab , aKey , '' ) ;
SessionStore . deleteTabValue ( aTab , aKey ) ;
2009-12-25 13:13:33 -05:00
}
catch ( e ) {
}
if ( this . useTMPSessionAPI )
aTab . removeAttribute ( this . kTMP _SESSION _DATA _PREFIX + aKey ) ;
} ,
// workaround for http://piro.sakura.ne.jp/latest/blosxom/mozilla/extension/treestyletab/2009-09-29_debug.htm
2013-05-28 03:04:58 -04:00
// This is obsolete for lately Firefox and no need to be updated. See: https://github.com/piroor/treestyletab/issues/508#issuecomment-17526429
2013-03-05 12:56:29 -05:00
checkCachedSessionDataExpiration : function TSTBase _checkCachedSessionDataExpiration ( aTab )
2009-12-25 13:13:33 -05:00
{
2012-01-13 03:38:12 -05:00
var data = aTab . linkedBrowser . _ _SS _data ;
2010-01-28 11:33:00 -05:00
if ( data &&
data . _tabStillLoading &&
2010-09-26 11:32:44 -04:00
aTab . getAttribute ( 'busy' ) != 'true' &&
2013-05-28 03:14:31 -04:00
! utils . isTabNeedToBeRestored ( aTab ) )
2010-01-28 11:33:00 -05:00
data . _tabStillLoading = false ;
2009-12-25 13:13:33 -05:00
} ,
2013-03-05 12:56:29 -05:00
markAsClosedSet : function TSTBase _markAsClosedSet ( aTabs ) /* PUBLIC API */
2009-12-25 22:25:29 -05:00
{
if ( ! aTabs || aTabs . length <= 1 ) return ;
var id = this . makeNewClosedSetId ( ) + '::' + aTabs . length ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = aTabs . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
this . setTabValue ( aTabs [ i ] , this . kCLOSED _SET _ID , id ) ;
2012-02-04 13:15:38 -05:00
}
2009-12-25 22:25:29 -05:00
} ,
2013-03-05 12:56:29 -05:00
unmarkAsClosedSet : function TSTBase _unmarkAsClosedSet ( aTabs ) /* PUBLIC API */
2009-12-25 22:25:29 -05:00
{
if ( ! aTabs || ! aTabs . length ) return ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = aTabs . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
this . deleteTabValue ( aTabs [ i ] , this . kCLOSED _SET _ID ) ;
2012-02-04 13:15:38 -05:00
}
2009-12-25 22:25:29 -05:00
} ,
2011-12-15 00:28:40 -05:00
useTMPSessionAPI : false ,
2009-12-25 13:13:33 -05:00
kTMP _SESSION _DATA _PREFIX : 'tmp-session-data-' ,
2009-12-25 12:55:55 -05:00
// tab
2013-03-05 12:56:29 -05:00
getTabStrip : function TSTBase _getTabStrip ( aTabBrowser )
2010-04-06 09:38:05 -04:00
{
if ( ! ( aTabBrowser instanceof Ci . nsIDOMElement ) )
2010-03-27 10:52:25 -04:00
return null ;
2010-04-06 09:38:05 -04:00
2010-03-25 20:20:51 -04:00
var strip = aTabBrowser . mStrip ;
2010-04-08 19:50:08 -04:00
return ( strip && strip instanceof Ci . nsIDOMElement ) ?
2010-03-25 20:20:51 -04:00
strip :
2011-01-21 12:15:04 -05:00
this . evaluateXPath (
'ancestor::xul:toolbar[1]' ,
2012-09-23 08:04:20 -04:00
aTabBrowser . tabContainer ,
2011-01-21 12:15:04 -05:00
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue || aTabBrowser . tabContainer . parentNode ;
2010-03-23 09:33:00 -04:00
} ,
2010-04-06 09:38:05 -04:00
get tabStrip ( )
2010-03-23 09:33:00 -04:00
{
return this . getTabStrip ( this . browser ) ;
} ,
2013-03-05 12:56:29 -05:00
getTabContainerBox : function TSTBase _getTabContainerBox ( aTabBrowser )
2010-04-29 23:20:18 -04:00
{
if ( ! ( aTabBrowser instanceof Ci . nsIDOMElement ) )
return null ;
var strip = this . getTabStrip ( aTabBrowser ) ;
2011-01-21 12:15:04 -05:00
return strip . treeStyleTabToolbarInnerBox || aTabBrowser . tabContainer ;
2010-04-29 23:20:18 -04:00
} ,
get tabContainerBox ( )
{
return this . getTabContainerBox ( this . browser ) ;
} ,
2013-03-05 12:56:29 -05:00
setTabbrowserAttribute : function TSTBase _setTabbrowserAttribute ( aName , aValue , aTabBrowser )
2010-03-23 12:12:49 -04:00
{
2010-03-28 14:22:15 -04:00
aTabBrowser = aTabBrowser || this . mTabBrowser || this . browser ;
2010-03-23 12:12:49 -04:00
if ( aValue ) {
aTabBrowser . setAttribute ( aName , aValue ) ;
aTabBrowser . mTabContainer . setAttribute ( aName , aValue ) ;
2010-03-25 23:17:16 -04:00
aTabBrowser . treeStyleTab . setTabStripAttribute ( aName , aValue ) ;
2010-03-23 12:12:49 -04:00
}
else {
aTabBrowser . removeAttribute ( aName ) ;
aTabBrowser . mTabContainer . removeAttribute ( aName ) ;
2010-03-25 23:17:16 -04:00
aTabBrowser . treeStyleTab . removeTabStripAttribute ( aName ) ;
2010-03-23 12:12:49 -04:00
}
} ,
2013-03-05 12:56:29 -05:00
removeTabbrowserAttribute : function TSTBase _removeTabbrowserAttribute ( aName , aTabBrowser )
2010-03-28 14:22:15 -04:00
{
this . setTabbrowserAttribute ( aName , null , aTabBrowser ) ;
} ,
2013-03-05 12:56:29 -05:00
setTabStripAttribute : function TSTBase _setTabStripAttribute ( aAttr , aValue )
2010-04-29 23:20:18 -04:00
{
var strip = this . tabStrip ;
if ( ! strip ) return ;
2010-09-13 21:04:00 -04:00
var isFeatureAttribute = aAttr . indexOf ( 'treestyletab-' ) == 0 ;
2010-04-29 23:20:18 -04:00
if ( aValue ) {
2011-05-17 11:27:46 -04:00
if ( this . _tabStripPlaceHolder )
this . _tabStripPlaceHolder . setAttribute ( aAttr , aValue ) ;
if ( ! this . _tabStripPlaceHolder || aAttr != 'ordinal' )
strip . setAttribute ( aAttr , aValue ) ;
if ( strip . treeStyleTabToolbarInnerBox )
strip . treeStyleTabToolbarInnerBox . setAttribute ( aAttr , aValue ) ;
2010-09-13 21:04:00 -04:00
if ( isFeatureAttribute ) {
// Only attributes for TST's feature are applied to the root element.
// (width, height, and other general attributes have to be ignored!)
strip . ownerDocument . defaultView . setTimeout ( function ( aSelf ) {
strip . ownerDocument . documentElement . setAttribute ( aAttr , aValue ) ;
} , 10 , this ) ;
}
2010-04-29 23:20:18 -04:00
}
else {
2011-05-17 11:27:46 -04:00
if ( this . _tabStripPlaceHolder )
this . _tabStripPlaceHolder . removeAttribute ( aAttr ) ;
if ( ! this . _tabStripPlaceHolder || aAttr != 'ordinal' )
strip . removeAttribute ( aAttr ) ;
if ( strip . treeStyleTabToolbarInnerBox )
strip . treeStyleTabToolbarInnerBox . removeAttribute ( aAttr ) ;
2010-09-13 21:04:00 -04:00
if ( isFeatureAttribute ) {
strip . ownerDocument . defaultView . setTimeout ( function ( aSelf ) {
strip . ownerDocument . documentElement . removeAttribute ( aAttr ) ;
} , 10 , this ) ;
}
2010-04-29 23:20:18 -04:00
}
} ,
2013-03-05 12:56:29 -05:00
removeTabStripAttribute : function TSTBase _removeTabStripAttribute ( aAttr )
2010-04-29 23:20:18 -04:00
{
this . setTabStripAttribute ( aAttr , null ) ;
} ,
2013-03-05 12:56:29 -05:00
getTabFromChild : function TSTBase _getTabFromChild ( aTab )
2009-12-25 12:55:55 -05:00
{
return this . evaluateXPath (
2010-03-23 11:12:43 -04:00
'ancestor-or-self::xul:tab' ,
2009-12-25 12:55:55 -05:00
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
} ,
2013-03-05 12:56:29 -05:00
getTabFromEvent : function TSTBase _getTabFromEvent ( aEvent )
2009-12-25 12:55:55 -05:00
{
return this . getTabFromChild ( aEvent . originalTarget || aEvent . target ) ;
} ,
2013-03-05 12:56:29 -05:00
getNewTabButtonFromEvent : function TSTBase _getNewTabButtonFromEvent ( aEvent )
2012-02-28 12:28:05 -05:00
{
return this . evaluateXPath (
'ancestor-or-self::*['
+ '@id="new-tab-button" or '
+ 'contains(concat(" ", normalize-space(@class), " "), " tabs-newtab-button ")'
+ '][1]' ,
aEvent . originalTarget ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
} ,
2013-03-05 12:56:29 -05:00
getSplitterFromEvent : function TSTBase _getSplitterFromEvent ( aEvent )
2010-03-02 09:40:12 -05:00
{
return this . evaluateXPath (
'ancestor-or-self::xul:splitter[contains(concat(" ", normalize-space(@class), " "), " ' + this . kSPLITTER + ' ")]' ,
aEvent . originalTarget ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
} ,
2013-03-05 12:56:29 -05:00
isEventFiredOnGrippy : function TSTBase _isEventFiredOnGrippy ( aEvent )
2010-09-13 13:52:07 -04:00
{
return this . evaluateXPath (
'ancestor-or-self::xul:grippy' ,
aEvent . originalTarget ,
Ci . nsIDOMXPathResult . BOOLEAN _TYPE
) . booleanValue ;
} ,
2013-03-05 12:56:29 -05:00
getTabFromFrame : function TSTBase _getTabFromFrame ( aFrame , aTabBrowser )
2009-12-25 12:55:55 -05:00
{
var b = aTabBrowser || this . browser ;
2010-11-11 20:42:06 -05:00
var top = aFrame . top ;
2012-09-23 02:43:49 -04:00
var tabs = this . getAllTabs ( b ) ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = tabs . length ; i < maxi ; i ++ )
2009-12-25 12:55:55 -05:00
{
2012-02-04 16:31:03 -05:00
let tab = tabs [ i ] ;
2010-11-11 20:42:06 -05:00
if ( tab . linkedBrowser . contentWindow == top )
2009-12-25 12:55:55 -05:00
return tab ;
}
return null ;
} ,
2013-03-05 12:56:29 -05:00
getTabbarFromChild : function TSTBase _getTabbarFromChild ( aNode )
2009-12-25 12:55:55 -05:00
{
return this . evaluateXPath (
2012-10-12 13:24:02 -04:00
'ancestor-or-self::*[contains(concat(" ", normalize-space(@class), " "), " tabbrowser-strip ")] | ' +
2010-04-30 00:00:09 -04:00
'ancestor-or-self::xul:tabs[@tabbrowser] | ' +
2011-01-21 10:01:19 -05:00
'ancestor-or-self::xul:toolbar/child::xul:tabs[@tabbrowser]' ,
2010-03-24 13:20:30 -04:00
aNode ,
2009-12-25 12:55:55 -05:00
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
} ,
2013-03-05 12:56:29 -05:00
getAncestorTabbarFromChild : function TSTBase _getAncestorTabbarFromChild ( aNode )
2011-03-14 12:25:46 -04:00
{
return this . evaluateXPath (
2012-10-12 13:24:02 -04:00
'ancestor-or-self::*[contains(concat(" ", normalize-space(@class), " "), " tabbrowser-strip ")] | ' +
2011-03-14 12:25:46 -04:00
'ancestor-or-self::xul:tabs[@tabbrowser]' ,
aNode ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
} ,
2009-12-25 12:55:55 -05:00
2013-03-05 12:56:29 -05:00
getTabbarFromEvent : function TSTBase _getTabbarFromEvent ( aEvent )
2010-03-24 13:20:30 -04:00
{
return this . getTabbarFromChild ( aEvent . originalTarget || aEvent . target ) ;
} ,
2013-03-05 12:56:29 -05:00
getAncestorTabbarFromEvent : function TSTBase _getAncestorTabbarFromEvent ( aEvent )
2011-03-14 12:25:46 -04:00
{
return this . getAncestorTabbarFromChild ( aEvent . originalTarget || aEvent . target ) ;
} ,
2010-03-24 13:20:30 -04:00
2013-03-05 12:56:29 -05:00
cleanUpTabsArray : function TSTBase _cleanUpTabsArray ( aTabs )
2009-12-25 12:55:55 -05:00
{
var newTabs = [ ] ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = aTabs . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let tab = aTabs [ i ] ;
2012-02-04 13:15:38 -05:00
if ( ! tab || ! tab . parentNode ) continue ; // ignore removed tabs
if ( newTabs . indexOf ( tab ) < 0 ) newTabs . push ( tab ) ;
}
2009-12-25 12:55:55 -05:00
newTabs . sort ( this . sortTabsByOrder ) ;
return newTabs ;
} ,
2013-03-05 12:56:29 -05:00
sortTabsByOrder : function TSTBase _sortTabsByOrder ( aA , aB )
2009-12-25 12:55:55 -05:00
{
return aA . _tPos - aB . _tPos ;
} ,
2013-03-05 12:56:29 -05:00
gatherSubtreeMemberTabs : function TSTBase _gatherSubtreeMemberTabs ( aTabOrTabs , aOnlyChildren )
2009-12-25 12:55:55 -05:00
{
var tabs = aTabOrTabs ;
if ( ! ( tabs instanceof Array ) ) {
tabs = [ aTabOrTabs ] ;
}
var b = this . getTabBrowserFromChild ( tabs [ 0 ] ) ;
var descendant = [ ] ;
for ( var i = 0 , maxi = tabs . length ; i < maxi ; i ++ )
{
descendant = descendant . concat ( b . treeStyleTab . getDescendantTabs ( tabs [ i ] ) ) ;
}
2010-09-18 11:12:14 -04:00
return this . cleanUpTabsArray ( aOnlyChildren ? descendant : tabs . concat ( descendant ) ) ;
2009-12-25 12:55:55 -05:00
} ,
2009-12-27 06:22:44 -05:00
2013-03-05 12:56:29 -05:00
splitTabsToSubtrees : function TSTBase _splitTabsToSubtrees ( aTabs ) /* PUBLIC API */
2009-12-27 06:22:44 -05:00
{
var groups = [ ] ;
2011-05-25 23:11:08 -04:00
2009-12-27 06:22:44 -05:00
var group = [ ] ;
2012-02-04 16:31:03 -05:00
aTabs = this . cleanUpTabsArray ( aTabs ) ;
for ( let i = 0 , maxi = aTabs . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let tab = aTabs [ i ] ;
2012-02-04 13:15:38 -05:00
let parent = this . getParentTab ( tab ) ;
if ( ! parent || group . indexOf ( parent ) < 0 ) {
if ( group . length ) groups . push ( group ) ;
group = [ tab ] ;
}
else {
group . push ( tab ) ;
}
}
2009-12-27 06:22:44 -05:00
if ( group . length ) groups . push ( group ) ;
return groups ;
} ,
2009-12-25 12:55:55 -05:00
// tabbrowser
2013-03-05 12:56:29 -05:00
getTabBrowserFromChild : function TSTBase _getTabBrowserFromChild ( aTabBrowserChild )
2009-12-25 12:55:55 -05:00
{
2010-03-23 13:58:23 -04:00
if ( ! aTabBrowserChild )
return null ;
2009-12-25 12:55:55 -05:00
2010-03-23 13:58:23 -04:00
if ( aTabBrowserChild . _ _treestyletab _ _linkedTabBrowser ) // tab
2009-12-25 12:55:55 -05:00
return aTabBrowserChild . _ _treestyletab _ _linkedTabBrowser ;
2010-03-23 13:58:23 -04:00
if ( aTabBrowserChild . localName == 'tabbrowser' ) // itself
2009-12-25 12:55:55 -05:00
return aTabBrowserChild ;
2012-01-13 11:30:06 -05:00
if ( aTabBrowserChild . tabbrowser ) // tabs
2010-03-23 13:58:23 -04:00
return aTabBrowserChild . tabbrowser ;
2012-01-13 11:30:06 -05:00
if ( aTabBrowserChild . localName == 'toolbar' ) // tabs toolbar
2010-03-27 10:52:25 -04:00
return aTabBrowserChild . getElementsByTagName ( 'tabs' ) [ 0 ] . tabbrowser ;
2012-01-13 11:30:06 -05:00
// tab context menu
2010-04-01 13:37:30 -04:00
var popup = this . evaluateXPath (
'ancestor-or-self::xul:menupopup[@id="tabContextMenu"]' ,
aTabBrowserChild ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2010-04-22 04:24:36 -04:00
if ( popup && 'TabContextMenu' in aTabBrowserChild . ownerDocument . defaultView )
2010-04-22 04:29:18 -04:00
return this . getTabBrowserFromChild ( aTabBrowserChild . ownerDocument . defaultView . TabContextMenu . contextTab ) ;
2010-04-01 13:37:30 -04:00
2010-03-23 10:21:13 -04:00
var b = this . evaluateXPath (
'ancestor::xul:tabbrowser | ' +
2010-04-29 23:51:31 -04:00
'ancestor::xul:tabs[@tabbrowser] |' +
2011-01-21 10:01:19 -05:00
'ancestor::xul:toolbar/descendant::xul:tabs' ,
2009-12-25 12:55:55 -05:00
aTabBrowserChild ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2010-03-23 10:21:13 -04:00
return ( b && b . tabbrowser ) || b ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getTabBrowserFromFrame : function TSTBase _getTabBrowserFromFrame ( aFrame )
2009-12-25 12:55:55 -05:00
{
var w = this . browserWindow ;
return ! w ? null :
( 'SplitBrowser' in w ) ? this . getTabBrowserFromChild ( w . SplitBrowser . getSubBrowserAndBrowserFromFrame ( aFrame . top ) . browser ) :
this . browser ;
} ,
2013-03-05 12:56:29 -05:00
getFrameFromTabBrowserElements : function TSTBase _getFrameFromTabBrowserElements ( aFrameOrTabBrowser )
2009-12-25 12:55:55 -05:00
{
var frame = aFrameOrTabBrowser ;
if ( frame == '[object XULElement]' ) {
if ( frame . localName == 'tab' ) {
frame = frame . linkedBrowser . contentWindow ;
}
else if ( frame . localName == 'browser' ) {
frame = frame . contentWindow ;
}
else {
frame = this . getTabBrowserFromChild ( frame ) ;
if ( ! frame ) return null ;
frame = frame . contentWindow ;
}
}
if ( ! frame )
frame = this . browser . contentWindow ;
return frame ;
} ,
2013-01-04 01:30:08 -05:00
2009-12-25 12:55:55 -05:00
/* get tab(s) */
2013-03-05 12:56:29 -05:00
getTabById : function TSTBase _getTabById ( aId , aTabBrowserChildren )
2009-12-25 12:55:55 -05:00
{
if ( ! aId ) return null ;
2010-03-24 11:38:08 -04:00
if ( aTabBrowserChildren && ! ( aTabBrowserChildren instanceof Ci . nsIDOMNode ) )
aTabBrowserChildren = null ;
2009-12-25 12:55:55 -05:00
var b = this . getTabBrowserFromChild ( aTabBrowserChildren ) || this . browser ;
2010-03-24 11:38:08 -04:00
if ( this . tabsHash ) // XPath-less implementation
return this . tabsHash [ aId ] || null ;
2012-09-23 02:43:49 -04:00
return b . mTabContainer . querySelector ( 'tab[' + this . kID + '="' + aId + '"]' ) ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
isTabDuplicated : function TSTBase _isTabDuplicated ( aTab )
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return false ;
var id = this . getTabValue ( aTab , this . kID ) ;
var b = this . getTabBrowserFromChild ( aTab ) || this . browser ;
2012-09-23 02:51:11 -04:00
var tabs = b . mTabContainer . querySelectorAll ( 'tab[' + this . kID + '="' + id + '"], tab[' + this . kID _RESTORING + '="' + id + '"]' ) ;
return tabs . length > 1 ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
2012-09-23 02:43:49 -04:00
* Returns all tabs in the current group as an array .
2010-09-14 03:39:17 -04:00
* It includes tabs hidden by Tab Panorama .
* /
2013-03-05 12:56:29 -05:00
getAllTabs : function TSTBase _getTabs ( aTabBrowserChild )
2010-09-14 03:39:17 -04:00
{
2012-08-04 18:06:32 -04:00
var b = this . getTabBrowserFromChild ( aTabBrowserChild || this . browser ) ;
2012-01-23 14:07:56 -05:00
this . assertBeforeDestruction ( b && b . mTabContainer ) ;
2012-09-23 02:43:49 -04:00
return Array . slice ( b . mTabContainer . querySelectorAll ( 'tab' ) ) ;
2010-09-14 03:39:17 -04:00
} ,
/ * *
2012-09-23 02:43:49 -04:00
* Returns all tabs in the current group as an array .
2010-09-14 03:39:17 -04:00
* It excludes tabs hidden by Tab Panorama .
* /
2013-03-05 12:56:29 -05:00
getTabs : function TSTBase _getTabs ( aTabBrowserChild )
2009-12-25 12:55:55 -05:00
{
2012-08-04 18:06:32 -04:00
var b = this . getTabBrowserFromChild ( aTabBrowserChild || this . browser ) ;
2012-01-23 14:07:56 -05:00
this . assertBeforeDestruction ( b && b . mTabContainer ) ;
2012-09-23 02:43:49 -04:00
return Array . slice ( b . mTabContainer . querySelectorAll ( 'tab:not([hidden="true"])' ) ) ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getAllTabsArray : function TSTBase _getAllTabsArray ( aTabBrowserChild ) /* for backward compatibility */
2010-09-14 03:39:17 -04:00
{
2012-09-23 02:43:49 -04:00
return this . getAllTabs ( aTabBrowserChild ) ;
2010-09-14 03:39:17 -04:00
} ,
2013-03-05 12:56:29 -05:00
getTabsArray : function TSTBase _getTabsArray ( aTabBrowserChild ) /* for backward compatibility */
2009-12-25 12:55:55 -05:00
{
2012-09-23 02:43:49 -04:00
return this . getTabs ( aTabBrowserChild ) ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the first tab in the current group .
* /
2013-03-05 12:56:29 -05:00
getFirstTab : function TSTBase _getFirstTab ( aTabBrowserChild )
2009-12-25 12:55:55 -05:00
{
2012-08-04 18:06:32 -04:00
var b = this . getTabBrowserFromChild ( aTabBrowserChild || this . browser ) ;
2012-01-23 14:07:56 -05:00
this . assertBeforeDestruction ( b && b . mTabContainer ) ;
2010-09-14 03:05:27 -04:00
var tabs = b . visibleTabs ;
return tabs ? tabs [ 0 ] : b . mTabContainer . firstChild ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the first visible , not collapsed , and not pinned tab .
* /
2013-03-05 12:56:29 -05:00
getFirstNormalTab : function TSTBase _getFirstNormalTab ( aTabBrowserChild )
2010-06-25 11:59:59 -04:00
{
2012-08-04 18:06:32 -04:00
var b = this . getTabBrowserFromChild ( aTabBrowserChild || this . browser ) ;
2012-01-23 14:07:56 -05:00
this . assertBeforeDestruction ( b && b . mTabContainer ) ;
2012-09-23 02:51:11 -04:00
return b . mTabContainer . querySelector ( 'tab:not([pinned="true"]):not([hidden="true"])' ) ;
2010-06-25 11:59:59 -04:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the last tab in the current group .
* /
2013-03-05 12:56:29 -05:00
getLastTab : function TSTBase _getLastTab ( aTabBrowserChild )
2009-12-25 12:55:55 -05:00
{
2012-08-04 18:06:32 -04:00
var b = this . getTabBrowserFromChild ( aTabBrowserChild || this . browser ) ;
2012-01-23 14:07:56 -05:00
this . assertBeforeDestruction ( b && b . mTabContainer ) ;
2010-09-14 03:05:27 -04:00
var tabs = b . visibleTabs ;
return tabs ? tabs [ tabs . length - 1 ] : b . mTabContainer . lastChild ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the next tab in the current group .
* /
2013-03-05 12:56:29 -05:00
getNextTab : function TSTBase _getNextTab ( aTab )
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-09-14 03:05:27 -04:00
var b = this . getTabBrowserFromChild ( aTab ) ;
2012-01-23 14:07:56 -05:00
this . assertBeforeDestruction ( b && b . mTabContainer ) ;
2010-09-14 03:05:27 -04:00
var tabs = b . visibleTabs ;
if ( tabs ) {
let index = tabs . indexOf ( aTab ) ;
if ( index > - 1 )
2010-11-17 12:50:54 -05:00
return tabs . length > index ? tabs [ index + 1 ] : null
2010-09-14 03:05:27 -04:00
}
2010-03-03 10:38:35 -05:00
var tab = aTab . nextSibling ;
return ( tab && tab . localName == 'tab' ) ? tab : null ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the previous tab in the current group .
* /
2013-03-05 12:56:29 -05:00
getPreviousTab : function TSTBase _getPreviousTab ( aTab )
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-09-14 03:05:27 -04:00
var b = this . getTabBrowserFromChild ( aTab ) ;
2012-01-23 14:07:56 -05:00
this . assertBeforeDestruction ( b && b . mTabContainer ) ;
2010-09-14 03:05:27 -04:00
var tabs = b . visibleTabs ;
if ( tabs ) {
let index = tabs . indexOf ( aTab ) ;
if ( index > - 1 )
2010-11-17 12:50:54 -05:00
return 0 < index ? tabs [ index - 1 ] : null
2010-09-14 03:05:27 -04:00
}
2010-03-03 10:38:35 -05:00
var tab = aTab . previousSibling ;
return ( tab && tab . localName == 'tab' ) ? tab : null ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the index of the specified tab , in the current group .
* /
2013-03-05 12:56:29 -05:00
getTabIndex : function TSTBase _getTabIndex ( aTab )
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return - 1 ;
2010-03-03 10:38:35 -05:00
var b = this . getTabBrowserFromChild ( aTab ) ;
2012-09-23 02:43:49 -04:00
return this . getTabs ( b ) . indexOf ( aTab ) ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the next not collapsed tab in the current group .
* /
2013-03-05 12:56:29 -05:00
getNextVisibleTab : function TSTBase _getNextVisibleTab ( aTab )
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-03 10:38:35 -05:00
var b = this . getTabBrowserFromChild ( aTab ) ;
if ( ! this . canCollapseSubtree ( b ) )
2009-12-25 12:55:55 -05:00
return this . getNextTab ( aTab ) ;
2012-09-23 02:43:49 -04:00
var tabs = this . getVisibleTabs ( b ) ;
2010-03-03 10:38:35 -05:00
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 ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the previous not collapsed tab in the current group .
* /
2013-03-05 12:56:29 -05:00
getPreviousVisibleTab : function TSTBase _getPreviousVisibleTab ( aTab )
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-03 10:38:35 -05:00
var b = this . getTabBrowserFromChild ( aTab ) ;
if ( ! this . canCollapseSubtree ( b ) )
2009-12-25 12:55:55 -05:00
return this . getPreviousTab ( aTab ) ;
2012-09-23 02:43:49 -04:00
var tabs = this . getVisibleTabs ( b ) ;
2010-03-03 10:38:35 -05:00
if ( tabs . indexOf ( aTab ) < 0 ) tabs . push ( aTab ) ;
tabs . sort ( this . sortTabsByOrder ) ;
var index = tabs . indexOf ( aTab ) ;
return ( index > 0 ) ? tabs [ index - 1 ] : null ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the last not collapsed tab in the current group .
* /
2013-03-05 12:56:29 -05:00
getLastVisibleTab : function TSTBase _getLastVisibleTab ( aTabBrowserChild )
2009-12-25 12:55:55 -05:00
{
2012-08-04 18:06:32 -04:00
var b = this . getTabBrowserFromChild ( aTabBrowserChild || this . browser ) ;
2009-12-25 12:55:55 -05:00
if ( ! b ) return null ;
2012-09-23 02:43:49 -04:00
var tabs = this . getVisibleTabs ( b ) ;
2010-03-03 10:38:35 -05:00
return tabs . length ? tabs [ tabs . length - 1 ] : null ;
2009-12-25 12:55:55 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns a XPathResult of not collapsed tabs in the current group .
* /
2013-03-05 12:56:29 -05:00
getVisibleTabs : function TSTBase _getVisibleTabs ( aTabBrowserChild ) /* OBSOLETE */
2009-12-25 12:55:55 -05:00
{
2012-08-04 18:06:32 -04:00
var b = this . getTabBrowserFromChild ( aTabBrowserChild || this . browser ) ;
2009-12-25 12:55:55 -05:00
if ( ! this . canCollapseSubtree ( b ) )
return this . getTabs ( b ) ;
2012-09-23 02:43:49 -04:00
return Array . slice ( b . mTabContainer . querySelectorAll ( 'tab:not([' + this . kCOLLAPSED + '="true"]):not([hidden="true"])' ) ) ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getVisibleTabsArray : function TSTBase _getVisibleTabsArray ( aTabBrowserChild ) /* for backward compatibility */
2010-03-03 10:38:35 -05:00
{
2012-09-23 02:43:49 -04:00
return this . getVisibleTabs ( aTabBrowserChild ) ;
2010-03-03 10:38:35 -05:00
} ,
2010-09-14 03:39:17 -04:00
/ * *
* Returns the index of the specified tab , in the array of not collapsed
* tabs in the current group .
* /
2013-03-05 12:56:29 -05:00
getVisibleIndex : function TSTBase _getVisibleIndex ( aTab )
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return - 1 ;
2010-03-03 10:38:35 -05:00
var b = this . getTabBrowserFromChild ( aTab ) ;
2012-09-23 02:43:49 -04:00
return this . getVisibleTabs ( b ) . indexOf ( aTab ) ;
2009-12-25 12:55:55 -05:00
} ,
2012-07-28 22:11:41 -04:00
2013-01-04 01:30:08 -05:00
/ * *
2012-07-28 22:11:41 -04:00
* Returns tabs which are newly opened in the given operation .
* /
2013-03-05 12:56:29 -05:00
getNewTabsWithOperation : function TSTBase _getNewTabsWithOperation ( aOperation , aTabBrowser )
2012-07-28 22:11:41 -04:00
{
var previousTabs = this . getTabsInfo ( aTabBrowser ) ;
aOperation . call ( this ) ;
return this . getNewTabsFromPreviousTabsInfo ( aTabBrowser , previousTabs ) ;
} ,
/ * *
* Returns tabs which are newly opened . This requires the "previous state" .
* /
2013-03-05 12:56:29 -05:00
getNewTabsFromPreviousTabsInfo : function TSTBase _getNewTabsFromPreviousTabsInfo ( aTabBrowser , aTabsInfo )
2012-07-28 22:11:41 -04:00
{
2012-09-23 02:43:49 -04:00
var tabs = this . getTabs ( aTabBrowser ) ;
2012-07-28 22:11:41 -04:00
var currentTabsInfo = this . getTabsInfo ( aTabBrowser ) ;
return tabs . filter ( function ( aTab , aIndex ) {
return aTabsInfo . indexOf ( currentTabsInfo [ aIndex ] ) < 0 ;
} ) ;
} ,
2013-03-05 12:56:29 -05:00
getTabsInfo : function TSTBase _getTabsInfo ( aTabBrowser )
2012-07-28 22:11:41 -04:00
{
2012-09-23 02:43:49 -04:00
var tabs = this . getTabs ( aTabBrowser ) ;
2012-07-28 22:11:41 -04:00
return tabs . map ( function ( aTab ) {
return aTab . getAttribute ( this . kID ) + '\n' +
aTab . getAttribute ( 'busy' ) + '\n' +
aTab . linkedBrowser . currentURI . spec ;
} , this ) ;
} ,
2009-12-25 12:55:55 -05:00
/* notify "ready to open child tab(s)" */
2013-03-05 12:56:29 -05:00
readyToOpenChildTab : function TSTBase _readyToOpenChildTab ( aFrameOrTabBrowser , aMultiple , aInsertBefore ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
2012-10-23 12:43:56 -04:00
if ( ! utils . getTreePref ( 'autoAttach' ) ) return false ;
2009-12-25 12:55:55 -05:00
var frame = this . getFrameFromTabBrowserElements ( aFrameOrTabBrowser ) ;
2010-09-13 09:58:30 -04:00
if ( ! frame )
2011-05-25 00:58:25 -04:00
return false ;
2009-12-25 12:55:55 -05:00
var ownerBrowser = this . getTabBrowserFromFrame ( frame ) ;
var parentTab = this . getTabFromFrame ( frame , ownerBrowser ) ;
2010-09-13 09:58:30 -04:00
if ( ! parentTab || parentTab . getAttribute ( 'pinned' ) == 'true' )
2011-05-25 00:58:25 -04:00
return false ;
2010-06-26 13:41:20 -04:00
2009-12-25 12:55:55 -05:00
ownerBrowser . treeStyleTab . ensureTabInitialized ( parentTab ) ;
var parentId = parentTab . getAttribute ( this . kID ) ;
var refId = null ;
if ( aInsertBefore ) {
ownerBrowser . treeStyleTab . ensureTabInitialized ( parentTab ) ;
refId = aInsertBefore . getAttribute ( this . kID ) ;
}
ownerBrowser . treeStyleTab . readiedToAttachNewTab = true ;
ownerBrowser . treeStyleTab . readiedToAttachMultiple = aMultiple || false ;
2010-12-07 11:28:23 -05:00
ownerBrowser . treeStyleTab . multipleCount = aMultiple ? 0 : - 1 ;
2009-12-25 12:55:55 -05:00
ownerBrowser . treeStyleTab . parentTab = parentId ;
ownerBrowser . treeStyleTab . insertBefore = refId ;
2011-05-25 00:58:25 -04:00
return true ;
} ,
/ * *
* Extended version . If you don ' t know whether a new tab will be actually
* opened or not ( by the command called after TST ' s API ) , then use this .
* This version automatically cancels the "ready" state with delay .
* /
2013-03-05 12:56:29 -05:00
readyToOpenChildTabNow : function TSTBase _readyToOpenChildTabNow ( aFrameOrTabBrowser , aMultiple ) /* PUBLIC API */
2011-05-25 00:58:25 -04:00
{
if ( this . readyToOpenChildTab . apply ( this , arguments ) ) {
let self = this ;
this . Deferred . next ( function ( ) {
self . stopToOpenChildTab ( aFrameOrTabBrowser ) ;
2012-02-06 12:13:46 -05:00
} ) . error ( this . defaultDeferredErrorHandler ) ;
2011-05-25 00:58:25 -04:00
return true ;
}
return false ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
readyToOpenNextSiblingTab : function TSTBase _readyToOpenNextSiblingTab ( aFrameOrTabBrowser ) /* PUBLIC API */
2011-05-04 15:14:38 -04:00
{
var frame = this . getFrameFromTabBrowserElements ( aFrameOrTabBrowser ) ;
if ( ! frame )
2011-05-25 00:58:25 -04:00
return false ;
2011-05-04 15:14:38 -04:00
var ownerBrowser = this . getTabBrowserFromFrame ( frame ) ;
var tab = this . getTabFromFrame ( frame , ownerBrowser ) ;
if ( ! tab || tab . getAttribute ( 'pinned' ) == 'true' )
2011-05-25 00:58:25 -04:00
return false ;
2011-05-04 15:14:38 -04:00
var parentTab = this . getParentTab ( tab ) ;
var nextTab = this . getNextSiblingTab ( tab ) ;
if ( parentTab ) {
/ * *
* If the base tab has a parent , open the new tab as a child of
* the parent tab .
* /
2011-05-25 00:58:25 -04:00
return this . readyToOpenChildTab ( parentTab , false , nextTab ) ;
2011-05-04 15:14:38 -04:00
}
else {
/ * *
* Otherwise , open the tab as a new root tab . If there is no
* tab next to the base tab ( in other words , if the tab is the
* last tab ) , then do nothing .
* /
if ( ! nextTab ) return ;
ownerBrowser . treeStyleTab . readiedToAttachNewTab = true ;
ownerBrowser . treeStyleTab . parentTab = null ;
ownerBrowser . treeStyleTab . insertBefore = nextTab . getAttribute ( this . kID ) ;
2011-05-25 00:58:25 -04:00
return true ;
2011-05-04 15:14:38 -04:00
}
} ,
2011-05-25 00:58:25 -04:00
/ * *
* Extended version . If you don ' t know whether a new tab will be actually
* opened or not ( by the command called after TST ' s API ) , then use this .
* This version automatically cancels the "ready" state with delay .
* /
2013-03-05 12:56:29 -05:00
readyToOpenNextSiblingTabNow : function TSTBase _readyToOpenNextSiblingTabNow ( aFrameOrTabBrowser ) /* PUBLIC API */
2011-05-25 00:58:25 -04:00
{
if ( this . readyToOpenNextSiblingTab . apply ( this , arguments ) ) {
let self = this ;
this . Deferred . next ( function ( ) {
self . stopToOpenChildTab ( aFrameOrTabBrowser ) ;
2012-02-06 12:13:46 -05:00
} ) . error ( this . defaultDeferredErrorHandler ) ;
2011-05-25 00:58:25 -04:00
return true ;
}
return false ;
} ,
2011-05-04 15:14:38 -04:00
2013-03-05 12:56:29 -05:00
readyToOpenNewTabGroup : function TSTBase _readyToOpenNewTabGroup ( aFrameOrTabBrowser , aTreeStructure , aExpandAllTree ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
2012-10-23 12:43:56 -04:00
if ( ! utils . getTreePref ( 'autoAttach' ) ) return false ;
2009-12-25 12:55:55 -05:00
var frame = this . getFrameFromTabBrowserElements ( aFrameOrTabBrowser ) ;
2011-05-25 00:58:25 -04:00
if ( ! frame ) return false ;
2009-12-25 12:55:55 -05:00
this . stopToOpenChildTab ( frame ) ;
var ownerBrowser = this . getTabBrowserFromFrame ( frame ) ;
ownerBrowser . treeStyleTab . readiedToAttachNewTabGroup = true ;
ownerBrowser . treeStyleTab . readiedToAttachMultiple = true ;
ownerBrowser . treeStyleTab . multipleCount = 0 ;
ownerBrowser . treeStyleTab . treeStructure = aTreeStructure ;
2011-01-22 13:32:04 -05:00
ownerBrowser . treeStyleTab . shouldExpandAllTree = ! ! aExpandAllTree ;
2011-05-25 00:58:25 -04:00
return true ;
} ,
/ * *
* Extended version . If you don ' t know whether new tabs will be actually
* opened or not ( by the command called after TST ' s API ) , then use this .
* This version automatically cancels the "ready" state with delay .
* /
2013-03-05 12:56:29 -05:00
readyToOpenNewTabGroupNow : function TSTBase _readyToOpenNewTabGroupNow ( aFrameOrTabBrowser ) /* PUBLIC API */
2011-05-25 00:58:25 -04:00
{
2011-12-05 03:21:19 -05:00
2011-05-25 00:58:25 -04:00
if ( this . readyToOpenNewTabGroup . apply ( this , arguments ) ) {
let self = this ;
this . Deferred . next ( function ( ) {
self . stopToOpenChildTab ( aFrameOrTabBrowser ) ;
2012-02-06 12:13:46 -05:00
} ) . error ( this . defaultDeferredErrorHandler ) ;
2011-05-25 00:58:25 -04:00
return true ;
}
return false ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
stopToOpenChildTab : function TSTBase _stopToOpenChildTab ( aFrameOrTabBrowser ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
var frame = this . getFrameFromTabBrowserElements ( aFrameOrTabBrowser ) ;
2011-05-25 00:58:25 -04:00
if ( ! frame ) return false ;
2009-12-25 12:55:55 -05:00
var ownerBrowser = this . getTabBrowserFromFrame ( frame ) ;
ownerBrowser . treeStyleTab . readiedToAttachNewTab = false ;
ownerBrowser . treeStyleTab . readiedToAttachNewTabGroup = false ;
ownerBrowser . treeStyleTab . readiedToAttachMultiple = false ;
2010-12-07 11:28:23 -05:00
ownerBrowser . treeStyleTab . multipleCount = - 1 ;
2009-12-25 12:55:55 -05:00
ownerBrowser . treeStyleTab . parentTab = null ;
ownerBrowser . treeStyleTab . insertBefore = null ;
ownerBrowser . treeStyleTab . treeStructure = null ;
2010-07-29 22:39:51 -04:00
ownerBrowser . treeStyleTab . shouldExpandAllTree = false ;
2011-05-25 00:58:25 -04:00
return true ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
checkToOpenChildTab : function TSTBase _checkToOpenChildTab ( aFrameOrTabBrowser ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
var frame = this . getFrameFromTabBrowserElements ( aFrameOrTabBrowser ) ;
if ( ! frame ) return false ;
var ownerBrowser = this . getTabBrowserFromFrame ( frame ) ;
2011-01-22 13:32:04 -05:00
return ! ! ( ownerBrowser . treeStyleTab . readiedToAttachNewTab || ownerBrowser . treeStyleTab . readiedToAttachNewTabGroup ) ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:40:18 -05:00
kNEWTAB _DO _NOTHING : - 1 ,
kNEWTAB _OPEN _AS _ORPHAN : 0 ,
kNEWTAB _OPEN _AS _CHILD : 1 ,
kNEWTAB _OPEN _AS _SIBLING : 2 ,
kNEWTAB _OPEN _AS _NEXT _SIBLING : 3 ,
2013-03-05 12:56:29 -05:00
readyToOpenRelatedTabAs : function TSTBase _readyToOpenRelatedTabAs ( aBaseTab , aBehavior )
2013-03-05 12:40:18 -05:00
{
2013-03-05 12:51:17 -05:00
var frame = this . getFrameFromTabBrowserElements ( aBaseTab ) ;
if ( ! frame )
return ;
aBaseTab = this . getTabFromFrame ( frame , this . getTabBrowserFromFrame ( frame ) ) ;
2013-03-05 12:40:18 -05:00
switch ( aBehavior )
{
case this . kNEWTAB _OPEN _AS _ORPHAN :
case this . kNEWTAB _DO _NOTHING :
default :
break ;
case this . kNEWTAB _OPEN _AS _CHILD :
this . readyToOpenChildTabNow ( aBaseTab ) ;
break ;
case this . kNEWTAB _OPEN _AS _SIBLING :
let ( parentTab = this . getParentTab ( aBaseTab ) ) {
if ( parentTab )
this . readyToOpenChildTabNow ( parentTab ) ;
}
break ;
case this . kNEWTAB _OPEN _AS _NEXT _SIBLING :
this . readyToOpenNextSiblingTabNow ( aBaseTab ) ;
break ;
}
} ,
2013-03-05 12:56:29 -05:00
handleNewTabFromCurrent : function TSTBase _handleNewTabFromCurrent ( aBaseTab )
2013-03-05 12:40:18 -05:00
{
2013-03-05 12:54:04 -05:00
this . readyToOpenRelatedTabAs ( aBaseTab , utils . getTreePref ( 'autoAttach.fromCurrent' ) ) ;
2013-03-05 12:40:18 -05:00
} ,
2009-12-25 12:55:55 -05:00
/* tree manipulations */
get treeViewEnabled ( ) /* PUBLIC API */
{
return this . _treeViewEnabled ;
} ,
set treeViewEnabled ( aValue )
{
2011-01-22 13:32:04 -05:00
this . _treeViewEnabled = ! ! aValue ;
2012-09-17 11:31:48 -04:00
Services . obs . notifyObservers (
2009-12-25 12:55:55 -05:00
window ,
2010-11-30 19:33:07 -05:00
this . kTOPIC _CHANGE _TREEVIEW _AVAILABILITY ,
2009-12-25 12:55:55 -05:00
this . _treeViewEnabled
) ;
return aValue ;
} ,
_treeViewEnabled : true ,
get rootTabs ( ) /* PUBLIC API */
{
2012-09-23 10:44:06 -04:00
return Array . slice ( this . browser . mTabContainer . querySelectorAll ( 'tab:not([' + this . kNEST + ']), tab[' + this . kNEST + '=""], tab[' + this . kNEST + '="0"]' ) ) ;
2009-12-25 12:55:55 -05:00
} ,
2010-12-08 06:34:42 -05:00
get allRootTabs ( ) /* PUBLIC API */
{
return this . rootTabs ;
} ,
get visibleRootTabs ( ) /* PUBLIC API */
{
return this . rootTabs . filter ( function ( aTab ) {
return ! aTab . hidden ;
} ) ;
} ,
2013-03-05 12:56:29 -05:00
canCollapseSubtree : function TSTBase _canCollapseSubtree ( aTabOrTabBrowser ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
2010-11-29 03:24:45 -05:00
if ( aTabOrTabBrowser &&
aTabOrTabBrowser . localName == 'tab' &&
aTabOrTabBrowser . getAttribute ( this . kALLOW _COLLAPSE ) != 'true' )
return false ;
var b = this . getTabBrowserFromChild ( aTabOrTabBrowser ) || this . browser ;
2011-06-15 22:54:13 -04:00
return b && b . getAttribute ( this . kALLOW _COLLAPSE ) == 'true' ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
isCollapsed : function TSTBase _isCollapsed ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
2011-03-28 13:14:27 -04:00
if ( ! aTab ||
! this . canCollapseSubtree ( this . getRootTab ( aTab ) ) )
2009-12-25 12:55:55 -05:00
return false ;
return aTab . getAttribute ( this . kCOLLAPSED ) == 'true' ;
} ,
2013-03-05 12:56:29 -05:00
isSubtreeCollapsed : function TSTBase _isSubtreeCollapsed ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab || ! this . canCollapseSubtree ( aTab ) || ! this . hasChildTabs ( aTab ) )
return false ;
return aTab . getAttribute ( this . kSUBTREE _COLLAPSED ) == 'true' ;
} ,
2013-03-05 12:56:29 -05:00
shouldCloseTabSubtreeOf : function TSTBase _shouldCloseTabSubtreeOf ( aTab )
2009-12-25 12:55:55 -05:00
{
return (
this . hasChildTabs ( aTab ) &&
(
2012-10-23 12:43:56 -04:00
utils . getTreePref ( 'closeParentBehavior' ) == this . kCLOSE _PARENT _BEHAVIOR _CLOSE _ALL _CHILDREN ||
2009-12-25 12:55:55 -05:00
this . isSubtreeCollapsed ( aTab )
)
) ;
} ,
2013-03-05 12:56:29 -05:00
shouldCloseTabSubTreeOf : function TSTBase _shouldCloseTabSubTreeOf ( ) { return this . shouldCloseTabSubtreeOf . apply ( this , arguments ) ; } , // obsolete, for backward compatibility
2009-12-25 12:55:55 -05:00
2013-03-05 12:56:29 -05:00
shouldCloseLastTabSubtreeOf : function TSTBase _shouldCloseLastTabSubtreeOf ( aTab )
2009-12-25 12:55:55 -05:00
{
var b = this . getTabBrowserFromChild ( aTab ) ;
return (
2011-06-15 22:54:13 -04:00
b &&
2009-12-25 12:55:55 -05:00
this . shouldCloseTabSubtreeOf ( aTab ) &&
2012-09-23 02:43:49 -04:00
this . getDescendantTabs ( aTab ) . length + 1 == this . getAllTabs ( b ) . length
2009-12-25 12:55:55 -05:00
) ;
} ,
2013-03-05 12:56:29 -05:00
shouldCloseLastTabSubTreeOf : function TSTBase _shouldCloseLastTabSubTreeOf ( ) { return this . shouldCloseLastTabSubtreeOf . apply ( this , arguments ) ; } , // obsolete, for backward compatibility
2009-12-25 12:55:55 -05:00
2013-03-05 12:56:29 -05:00
getParentTab : function TSTBase _getParentTab ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-24 11:38:08 -04:00
2011-12-12 13:54:43 -05:00
var parent ;
2012-08-04 16:04:26 -04:00
var id = aTab . getAttribute ( this . kPARENT ) ;
2010-03-24 11:38:08 -04:00
if ( this . tabsHash ) { // XPath-less implementation
2012-08-04 16:04:26 -04:00
parent = this . getTabById ( id ) ;
if ( parent && ! parent . parentNode && this . tabsHash ) {
delete this . tabsHash [ id ] ;
parent = null ;
}
2010-03-24 11:38:08 -04:00
}
2011-12-12 13:54:43 -05:00
else {
parent = this . evaluateXPath (
2012-08-04 16:04:26 -04:00
'preceding-sibling::xul:tab[@' + this . kID + '="' + id + '"][1]' ,
2011-12-12 13:54:43 -05:00
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
}
return ( parent && parent != aTab ) ? parent : null ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getAncestorTabs : function TSTBase _getAncestorTabs ( aTab ) /* PUBLIC API */
2010-12-01 03:40:18 -05:00
{
2011-12-12 13:54:43 -05:00
var tabs = [ aTab ] ;
2010-12-01 03:40:18 -05:00
var parentTab = aTab ;
while ( parentTab = this . getParentTab ( parentTab ) )
{
2011-12-12 13:54:43 -05:00
if ( tabs . indexOf ( parentTab ) > - 1 ) {
let message = 'recursive tree detected!\n' +
tabs . concat ( [ parentTab ] )
. reverse ( ) . map ( function ( aTab ) {
return ' ' + aTab . _tPos + ' : ' +
aTab . label + '\n ' +
aTab . getAttribute ( this . kID ) ;
} , this ) . join ( '\n' ) ;
dump ( message + '\n' ) ;
break ;
}
if ( aTab . _tPos < parentTab . _tPos ) {
let message = 'broken tree detected!\n' +
tabs . concat ( [ parentTab ] )
. reverse ( ) . map ( function ( aTab ) {
return ' ' + aTab . _tPos + ' : ' +
aTab . label + '\n ' +
aTab . getAttribute ( this . kID ) ;
} , this ) . join ( '\n' ) ;
dump ( message + '\n' ) ;
}
2010-12-01 03:40:18 -05:00
tabs . push ( parentTab ) ;
2011-12-12 13:54:43 -05:00
aTab = parentTab ;
2010-12-01 03:40:18 -05:00
}
2011-12-12 13:54:43 -05:00
return tabs . slice ( 1 ) ;
2010-12-01 03:40:18 -05:00
} ,
2013-03-05 12:56:29 -05:00
getRootTab : function TSTBase _getRootTab ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
2010-03-24 11:38:08 -04:00
if ( ! aTab ) return null ;
if ( this . tabsHash ) { // XPath-less implementation
2011-12-12 13:54:43 -05:00
let ancestors = this . getAncestorTabs ( aTab ) ;
return ancestors . length ? ancestors [ ancestors . length - 1 ] : aTab ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return this . evaluateXPath (
'(self::*[not(@' + this . kPARENT + ')] | preceding-sibling::xul:tab[not(@' + this . kPARENT + ')])[last()]' ,
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getNextSiblingTab : function TSTBase _getNextSiblingTab ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-24 11:38:08 -04:00
if ( this . tabsHash ) { // XPath-less implementation
let parentTab = this . getParentTab ( aTab ) ;
2009-12-25 12:55:55 -05:00
2010-03-24 11:38:08 -04:00
if ( ! parentTab ) {
let next = aTab ;
do {
next = next . nextSibling ;
}
while ( next &&
next . nodeType == Ci . nsIDOMNode . ELEMENT _NODE &&
this . getParentTab ( next ) ) ;
return next ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
let children = parentTab . getAttribute ( this . kCHILDREN ) ;
if ( children ) {
2011-12-05 03:21:19 -05:00
let list = ( '|' + children ) . split ( '|' + aTab . getAttribute ( this . kID ) ) ;
list = list . length > 1 ? list [ 1 ] . split ( '|' ) : [ ] ;
2010-03-24 11:38:08 -04:00
for ( let i = 0 , maxi = list . length ; i < maxi ; i ++ )
{
let firstChild = this . getTabById ( list [ i ] , aTab ) ;
if ( firstChild ) return firstChild ;
}
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return null ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
var parent = aTab . getAttribute ( this . kPARENT ) ;
return this . evaluateXPath (
'following-sibling::xul:tab[' +
( parent ? '@' + this . kPARENT + '="' + parent + '"' : 'not(@' + this . kPARENT + ')' ) +
'][1]' ,
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getPreviousSiblingTab : function TSTBase _getPreviousSiblingTab ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-24 11:38:08 -04:00
if ( this . tabsHash ) { // XPath-less implementation
let parentTab = this . getParentTab ( aTab ) ;
2009-12-25 12:55:55 -05:00
2010-03-24 11:38:08 -04:00
if ( ! parentTab ) {
let prev = aTab ;
do {
prev = prev . previousSibling ;
}
while ( prev &&
prev . nodeType == Ci . nsIDOMNode . ELEMENT _NODE &&
this . getParentTab ( prev ) ) ;
return prev ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
let children = parentTab . getAttribute ( this . kCHILDREN ) ;
if ( children ) {
let list = ( '|' + children ) . split ( '|' + aTab . getAttribute ( this . kID ) ) [ 0 ] . split ( '|' ) ;
for ( let i = list . length - 1 ; i > - 1 ; i -- )
{
let lastChild = this . getTabById ( list [ i ] , aTab ) ;
if ( lastChild ) return lastChild ;
}
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return null ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
var parent = aTab . getAttribute ( this . kPARENT ) ;
return this . evaluateXPath (
'preceding-sibling::xul:tab[' +
( parent ? '@' + this . kPARENT + '="' + parent + '"' : 'not(@' + this . kPARENT + ')' ) +
'][1]' ,
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getSiblingTabs : function TSTBase _getSiblingTabs ( aTab ) /* PUBLIC API */
2011-07-29 14:07:37 -04:00
{
var parent = this . getParentTab ( aTab ) ;
var siblings = parent && parent . parentNode ? this . getChildTabs ( parent ) : this . visibleRootTabs ;
return siblings . filter ( function ( aSiblingTab ) {
return aSiblingTab != aTab ;
} ) ;
} ,
2013-03-05 12:56:29 -05:00
getChildTabs : function TSTBase _getChildTabs ( aTab , aAllTabsArray ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
var tabs = [ ] ;
if ( ! aTab ) return tabs ;
var children = aTab . getAttribute ( this . kCHILDREN ) ;
if ( ! children ) return tabs ;
if ( aAllTabsArray ) tabs = aAllTabsArray ;
var list = children . split ( '|' ) ;
for ( let i = 0 , maxi = list . length ; i < maxi ; i ++ )
{
let tab = this . getTabById ( list [ i ] , aTab ) ;
2010-03-25 10:49:22 -04:00
if ( ! tab || tab == aTab ) continue ;
2012-08-08 16:02:24 -04:00
if ( tabs . indexOf ( tab ) > - 1 ) {
let message = 'broken (possible recursive) tree detected!\n' +
tabs . map ( function ( aTab ) {
return ' ' + aTab . _tPos + ' : ' +
aTab . label + '\n ' +
aTab . getAttribute ( this . kID ) ;
} , this ) . join ( '\n' ) ;
dump ( message + '\n' ) ;
continue ;
}
2009-12-25 12:55:55 -05:00
tabs . push ( tab ) ;
if ( aAllTabsArray )
this . getChildTabs ( tab , tabs ) ;
}
return tabs ;
} ,
2013-03-05 12:56:29 -05:00
hasChildTabs : function TSTBase _hasChildTabs ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return false ;
return aTab . hasAttribute ( this . kCHILDREN ) ;
} ,
2013-03-05 12:56:29 -05:00
getDescendantTabs : function TSTBase _getDescendantTabs ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
var tabs = [ ] ;
this . getChildTabs ( aTab , tabs ) ;
return tabs ;
} ,
2013-03-05 12:56:29 -05:00
getFirstChildTab : function TSTBase _getFirstChildTab ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-24 11:38:08 -04:00
if ( this . tabsHash ) { // XPath-less implementation
let children = aTab . getAttribute ( this . kCHILDREN ) ;
let firstChild = null ;
if ( children ) {
let list = children . split ( '|' ) ;
for ( let i = 0 , maxi = list . length ; i < maxi ; i ++ )
{
firstChild = this . getTabById ( list [ i ] , aTab ) ;
2010-03-25 10:49:22 -04:00
if ( firstChild && firstChild != aTab ) break ;
2010-03-24 11:38:08 -04:00
}
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return firstChild ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return this . evaluateXPath (
'following-sibling::xul:tab[@' + this . kPARENT + '="' + aTab . getAttribute ( this . kID ) + '"][1]' ,
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getLastChildTab : function TSTBase _getLastChildTab ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-24 11:38:08 -04:00
if ( this . tabsHash ) { // XPath-less implementation
let children = aTab . getAttribute ( this . kCHILDREN ) ;
let lastChild = null ;
if ( children ) {
let list = children . split ( '|' ) ;
for ( let i = list . length - 1 ; i > - 1 ; i -- )
{
lastChild = this . getTabById ( list [ i ] , aTab ) ;
2010-03-25 11:52:11 -04:00
if ( lastChild && lastChild != aTab ) break ;
2010-03-24 11:38:08 -04:00
}
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return lastChild ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return this . evaluateXPath (
'following-sibling::xul:tab[@' + this . kPARENT + '="' + aTab . getAttribute ( this . kID ) + '"][last()]' ,
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getLastDescendantTab : function TSTBase _getLastDescendantTab ( aTab ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
if ( ! aTab ) return null ;
2010-03-24 11:38:08 -04:00
if ( this . tabsHash ) { // XPath-less implementation
let tabs = this . getDescendantTabs ( aTab ) ;
return tabs . length ? tabs [ tabs . length - 1 ] : null ;
}
var parent = aTab . getAttribute ( this . kPARENT ) ;
return this . evaluateXPath (
'following-sibling::xul:tab[' +
( parent ? '@' + this . kPARENT + '="' + parent + '"' : 'not(@' + this . kPARENT + ')' ) +
'][1]/preceding-sibling::xul:tab[1][not(@' + this . kID + '="' + aTab . getAttribute ( this . kID ) + '")]' ,
aTab ,
Ci . nsIDOMXPathResult . FIRST _ORDERED _NODE _TYPE
) . singleNodeValue ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
collectRootTabs : function TSTBase _collectRootTabs ( aTabs ) /* PUBLIC API */
2011-06-15 00:32:39 -04:00
{
2011-06-15 04:38:14 -04:00
aTabs = Array . slice ( aTabs ) ;
return aTabs . filter ( function ( aTab ) {
var parent = this . getParentTab ( aTab ) ;
return ! parent || aTabs . indexOf ( parent ) < 0 ;
2011-06-15 00:32:39 -04:00
} , this ) ;
} ,
2013-03-05 12:56:29 -05:00
getChildIndex : function TSTBase _getChildIndex ( aTab , aParent ) /* PUBLIC API */
2009-12-25 12:55:55 -05:00
{
2011-12-14 23:32:17 -05:00
var parent = this . getParentTab ( aTab ) ;
if ( ! aParent || ! parent || aParent != parent ) {
let tabs = [ aTab ] . concat ( this . getAncestorTabs ( aTab ) ) ;
parent = aTab ;
for ( let i = 0 , maxi = tabs . length ; i < maxi && parent != aParent ; i ++ )
{
aTab = parent ;
parent = i < maxi ? tabs [ i + 1 ] : null ;
2009-12-25 12:55:55 -05:00
}
2011-12-14 23:32:17 -05:00
if ( parent != aParent )
2010-03-24 11:38:08 -04:00
return - 1 ;
2011-12-14 23:32:17 -05:00
aParent = parent ;
}
if ( aParent ) {
let children = aParent . getAttribute ( this . kCHILDREN ) ;
let list = children . split ( '|' ) ;
let id = aTab . getAttribute ( this . kID ) ;
for ( let i = 0 , maxi = list . length ; i < maxi ; i ++ )
{
if ( list [ i ] == id ) return i ;
2009-12-25 12:55:55 -05:00
}
2010-03-24 11:38:08 -04:00
return - 1 ;
2009-12-25 12:55:55 -05:00
}
2011-12-14 23:32:17 -05:00
else {
let tabs = this . rootTabs ;
for ( let i = 0 , maxi = tabs . length ; i < maxi ; i ++ )
{
if ( tabs [ i ] == aTab ) return i ;
}
}
return - 1 ;
2009-12-25 12:55:55 -05:00
} ,
2013-03-05 12:56:29 -05:00
getXOffsetOfTab : function TSTBase _getXOffsetOfTab ( aTab )
2009-12-25 12:55:55 -05:00
{
var extraCondition = this . canCollapseSubtree ( aTab ) ?
'[not(@' + this . kCOLLAPSED + '="true")]' :
'' ;
return this . evaluateXPath (
2010-08-13 13:14:46 -04:00
'sum((self::* | preceding-sibling::xul:tab[not(@hidden="true")]' + extraCondition + ')' +
'/attribute::' + this . kX _OFFSET + ')' ,
2009-12-25 12:55:55 -05:00
aTab ,
Ci . nsIDOMXPathResult . NUMBER _TYPE
) . numberValue ;
} ,
2013-03-05 12:56:29 -05:00
getYOffsetOfTab : function TSTBase _getYOffsetOfTab ( aTab )
2009-12-25 12:55:55 -05:00
{
var extraCondition = this . canCollapseSubtree ( aTab ) ?
'[not(@' + this . kCOLLAPSED + '="true")]' :
'' ;
return this . evaluateXPath (
2010-08-13 13:14:46 -04:00
'sum((self::* | preceding-sibling::xul:tab[not(@hidden="true")]' + extraCondition + ')' +
'/attribute::' + this . kY _OFFSET + ')' ,
2009-12-25 12:55:55 -05:00
aTab ,
Ci . nsIDOMXPathResult . NUMBER _TYPE
) . numberValue ;
} ,
2013-03-05 12:56:29 -05:00
getFutureBoxObject : function TSTBase _getFutureBoxObject ( aTab )
2012-01-28 16:43:43 -05:00
{
var tabBox = aTab . boxObject ;
var xOffset = this . getXOffsetOfTab ( aTab ) ;
var yOffset = this . getYOffsetOfTab ( aTab ) ;
return {
width : tabBox . width ,
height : tabBox . height ,
x : tabBox . x + xOffset ,
y : tabBox . y + yOffset ,
screenX : tabBox . screenX + xOffset ,
screenY : tabBox . screenY + yOffset
} ;
} ,
2013-03-05 12:56:29 -05:00
getTabActualScreenPosition : function TSTBase _getTabActualScreenPosition ( aTab )
2012-10-12 11:37:03 -04:00
{
return aTab . parentNode . orient == 'vertical' ?
this . getTabActualScreenY ( aTab ) :
this . getTabActualScreenX ( aTab ) ;
} ,
MATRIX _PATTERN : /matrix\((-?\d+),\s*(-?\d+),\s*(-?\d+),\s*(-?\d+),\s*(-?\d+),\s*(-?\d+)\)/ ,
2013-03-05 12:56:29 -05:00
getTabActualScreenX : function TSTBase _getTabActualScreenX ( aTab )
2012-10-12 11:37:03 -04:00
{
var x = aTab . boxObject . screenX ;
var w = aTab . ownerDocument . defaultView ;
var transform = w . getComputedStyle ( aTab , null ) . transform ;
2012-10-12 11:41:03 -04:00
var offset = transform && transform . match ( this . MATRIX _PATTERN ) ;
2012-10-12 11:37:03 -04:00
offset = offset ? parseFloat ( offset [ 5 ] ) : 0 ;
return x + offset ;
} ,
2013-03-05 12:56:29 -05:00
getTabActualScreenY : function TSTBase _getTabActualScreenY ( aTab )
2012-10-12 11:37:03 -04:00
{
var y = aTab . boxObject . screenY ;
var w = aTab . ownerDocument . defaultView ;
var transform = w . getComputedStyle ( aTab , null ) . transform ;
2012-10-12 11:41:03 -04:00
var offset = transform && transform . match ( this . MATRIX _PATTERN ) ;
2012-10-12 11:37:03 -04:00
offset = offset ? parseFloat ( offset [ 6 ] ) : 0 ;
return y + offset ;
} ,
2009-12-25 12:55:55 -05:00
2013-03-05 12:56:29 -05:00
isGroupTab : function TSTBase _isGroupTab ( aTab , aLazyCheck )
2009-12-25 12:55:55 -05:00
{
return (
( aLazyCheck || aTab . linkedBrowser . sessionHistory . count == 1 ) &&
2013-06-13 02:02:22 -04:00
aTab . linkedBrowser . currentURI . spec . indexOf ( 'about:treestyletab-group' ) == 0
2009-12-25 12:55:55 -05:00
) ;
} ,
2010-09-09 06:03:03 -04:00
get pinnedTabsCount ( )
{
2012-09-23 02:51:11 -04:00
return this . browser . mTabContainer . querySelectorAll ( 'tab[pinned="true"]' ) . length ;
2010-09-09 06:03:03 -04:00
} ,
2011-01-19 21:55:49 -05:00
2013-03-05 12:56:29 -05:00
forceExpandTabs : function TSTBase _forceExpandTabs ( aTabs )
2011-06-15 04:38:14 -04:00
{
var collapsedStates = aTabs . map ( function ( aTab ) {
return this . getTabValue ( aTab , this . kSUBTREE _COLLAPSED ) == 'true' ;
} , this ) ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = aTabs . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let tab = aTabs [ i ] ;
2012-02-04 13:15:38 -05:00
this . collapseExpandSubtree ( tab , false , true ) ;
this . collapseExpandTab ( tab , false , true ) ;
}
2011-06-15 04:38:14 -04:00
return collapsedStates ;
} ,
2013-03-05 12:56:29 -05:00
getTreeStructureFromTabs : function TSTBase _getTreeStructureFromTabs ( aTabs )
2011-01-19 21:55:49 -05:00
{
/ * t h i s r e t u r n s . . .
[ A ] => - 1 ( parent is not in this tree )
[ B ] => 0 ( parent is 1 st item in this tree )
[ C ] => 0 ( parent is 1 st item in this tree )
[ D ] => 2 ( parent is 2 nd in this tree )
[ E ] => - 1 ( parent is not in this tree , and this creates another tree )
[ F ] => 0 ( parent is 1 st item in this another tree )
* /
return this . cleanUpTreeStructureArray (
aTabs . map ( function ( aTab , aIndex ) {
let tab = this . getParentTab ( aTab ) ;
let index = tab ? aTabs . indexOf ( tab ) : - 1 ;
return index >= aIndex ? - 1 : index ;
} , this ) ,
- 1
) ;
} ,
2013-03-05 12:56:29 -05:00
cleanUpTreeStructureArray : function TSTBase _cleanUpTreeStructureArray ( aTreeStructure , aDefaultParent )
2011-01-19 21:55:49 -05:00
{
var offset = 0 ;
aTreeStructure = aTreeStructure
. map ( function ( aPosition , aIndex ) {
return ( aPosition == aIndex ) ? - 1 : aPosition ;
} )
. map ( function ( aPosition , aIndex ) {
if ( aPosition == - 1 ) {
offset = aIndex ;
return aPosition ;
}
return aPosition - offset ;
} ) ;
/ * T h e f i n a l s t e p , t h i s v a l i d a t e s a l l o f v a l u e s .
Smaller than - 1 is invalid , so it becomes to - 1. * /
aTreeStructure = aTreeStructure . map ( function ( aIndex ) {
return aIndex < - 1 ? aDefaultParent : aIndex ;
} , this ) ;
return aTreeStructure ;
} ,
2013-03-05 12:56:29 -05:00
applyTreeStructureToTabs : function TSTBase _applyTreeStructureToTabs ( aTabs , aTreeStructure , aExpandStates )
2011-01-19 21:55:49 -05:00
{
var b = this . getTabBrowserFromChild ( aTabs [ 0 ] ) ;
if ( ! b ) return ;
var sv = b . treeStyleTab ;
aTabs = aTabs . slice ( 0 , aTreeStructure . length ) ;
aTreeStructure = aTreeStructure . slice ( 0 , aTabs . length ) ;
2011-06-15 04:38:14 -04:00
aExpandStates = ( aExpandStates && typeof aExpandStates == 'object' ) ?
aExpandStates :
aTabs . map ( function ( aTab ) {
return ! ! aExpandStates ;
} ) ;
aExpandStates = aExpandStates . slice ( 0 , aTabs . length ) ;
while ( aExpandStates . length < aTabs . length ) aExpandStates . push ( - 1 ) ;
2011-01-19 21:55:49 -05:00
var parentTab = null ;
2012-02-04 16:31:03 -05:00
for ( let i = 0 , maxi = aTabs . length ; i < maxi ; i ++ )
2012-02-04 13:15:38 -05:00
{
2012-02-04 16:31:03 -05:00
let tab = aTabs [ i ] ;
2012-02-04 13:15:38 -05:00
if ( sv . isCollapsed ( tab ) ) sv . collapseExpandTab ( tab , false , true ) ;
sv . detachTab ( tab ) ;
2011-01-19 21:55:49 -05:00
2012-02-04 13:15:38 -05:00
let parentIndexInTree = aTreeStructure [ i ] ;
2011-06-15 04:38:14 -04:00
if ( parentIndexInTree < 0 ) // there is no parent, so this is a new parent!
2012-02-04 13:15:38 -05:00
parentTab = tab . getAttribute ( sv . kID ) ;
2011-01-19 21:55:49 -05:00
2012-02-04 13:15:38 -05:00
let parent = sv . getTabById ( parentTab ) ;
2011-01-19 21:55:49 -05:00
if ( parent ) {
let tabs = [ parent ] . concat ( sv . getDescendantTabs ( parent ) ) ;
2011-06-15 04:38:14 -04:00
parent = parentIndexInTree < tabs . length ? tabs [ parentIndexInTree ] : parent ;
2011-01-19 21:55:49 -05:00
}
if ( parent ) {
2012-02-04 13:15:38 -05:00
sv . attachTabTo ( tab , parent , {
2011-12-06 22:06:05 -05:00
forceExpand : true ,
dontMove : true
2011-01-19 21:55:49 -05:00
} ) ;
}
2012-02-04 13:15:38 -05:00
}
2011-06-15 04:38:14 -04:00
for ( let i = aTabs . length - 1 ; i > - 1 ; i -- )
{
2011-12-06 22:06:05 -05:00
sv . collapseExpandSubtree ( aTabs [ i ] , ! sv . hasChildTabs ( aTabs [ i ] ) || ! aExpandStates [ i ] , true ) ;
2011-06-15 04:38:14 -04:00
}
2011-01-19 21:55:49 -05:00
} ,
2013-03-05 12:56:29 -05:00
getTreeStructureFromTabBrowser : function TSTBase _getTreeStructureFromTabBrowser ( aTabBrowser )
2011-01-19 21:55:49 -05:00
{
2012-09-23 02:43:49 -04:00
return this . getTreeStructureFromTabs ( this . getAllTabs ( aTabBrowser ) ) ;
2011-01-19 21:55:49 -05:00
} ,
2013-03-05 12:56:29 -05:00
applyTreeStructureToTabBrowser : function TSTBase _applyTreeStructureToTabBrowser ( aTabBrowser , aTreeStructure , aExpandAllTree )
2011-01-19 21:55:49 -05:00
{
2012-09-23 02:43:49 -04:00
var tabs = this . getAllTabs ( aTabBrowser ) ;
2011-01-19 21:55:49 -05:00
return this . applyTreeStructureToTabs ( tabs , aTreeStructure , aExpandAllTree ) ;
} ,
2009-12-25 12:55:55 -05:00
2009-12-25 13:13:33 -05:00
/* tabbar position */
2009-12-25 11:51:24 -05:00
2011-01-22 10:46:29 -05:00
get position ( ) /* PUBLIC API */
2009-12-25 11:38:14 -05:00
{
2012-10-23 12:43:56 -04:00
return utils . getTreePref ( 'tabbar.position' ) || 'top' ;
2009-12-25 11:38:14 -05:00
} ,
2011-01-22 10:46:29 -05:00
set position ( aValue )
2009-12-25 11:38:14 -05:00
{
2010-05-08 04:30:39 -04:00
var position = String ( aValue ) . toLowerCase ( ) ;
if ( ! position || ! /^(top|bottom|left|right)$/ . test ( position ) )
2009-12-25 11:38:14 -05:00
position = 'top' ;
2012-10-23 12:43:56 -04:00
if ( position != utils . getTreePref ( 'tabbar.position' ) )
utils . setTreePref ( 'tabbar.position' , position ) ;
2009-12-25 11:38:14 -05:00
return aValue ;
} ,
2011-01-22 10:46:29 -05:00
get currentTabbarPosition ( ) /* for backward compatibility */
{
return this . position ;
} ,
set currentTabbarPosition ( aValue )
{
return this . position = aValue ;
} ,
2010-02-03 08:43:39 -05:00
2013-03-05 12:56:29 -05:00
getPositionFlag : function TSTBase _getPositionFlag ( aPosition )
2010-02-03 08:43:39 -05:00
{
aPosition = String ( aPosition ) . toLowerCase ( ) ;
return ( aPosition == 'left' ) ? this . kTABBAR _LEFT :
( aPosition == 'right' ) ? this . kTABBAR _RIGHT :
( aPosition == 'bottom' ) ? this . kTABBAR _BOTTOM :
this . kTABBAR _TOP ;
} ,
2009-12-25 11:51:24 -05:00
2009-12-25 13:13:33 -05:00
/* Pref Listener */
2009-12-25 11:56:45 -05:00
domains : [
2009-12-25 13:13:33 -05:00
'extensions.treestyletab.' ,
2012-11-27 13:34:57 -05:00
'browser.tabs.animate' ,
2009-12-25 13:13:33 -05:00
'browser.tabs.loadFolderAndReplace' ,
2010-03-31 06:34:30 -04:00
'browser.tabs.insertRelatedAfterCurrent' ,
'extensions.stm.tabBarMultiRows' // Super Tab Mode
2009-12-25 11:56:45 -05:00
] ,
2013-03-05 12:56:29 -05:00
observe : function TSTBase _observe ( aSubject , aTopic , aData )
2013-01-04 01:30:08 -05:00
{
switch ( aTopic )
{
case 'nsPref:changed' :
this . onPrefChange ( aData ) ;
return ;
}
} ,
2013-03-05 12:56:29 -05:00
onPrefChange : function TSTBase _onPrefChange ( aPrefName )
2009-12-25 11:56:45 -05:00
{
2013-01-05 21:47:50 -05:00
var value = prefs . getPref ( aPrefName ) ;
2009-12-25 11:56:45 -05:00
switch ( aPrefName )
{
2012-08-30 14:48:00 -04:00
case 'extensions.treestyletab.indent.vertical' :
2012-08-30 13:46:50 -04:00
this . baseIndentVertical = value ;
2012-09-17 11:31:48 -04:00
Services . obs . notifyObservers ( null , this . kTOPIC _INDENT _MODIFIED , value ) ;
2012-08-30 13:46:50 -04:00
return ;
case 'extensions.treestyletab.indent.horizontal' :
this . baseIndentHorizontal = value ;
2012-09-17 11:31:48 -04:00
Services . obs . notifyObservers ( null , this . kTOPIC _INDENT _MODIFIED , value ) ;
2011-03-24 22:42:50 -04:00
return ;
2009-12-25 13:13:33 -05:00
case 'extensions.treestyletab.tabbar.width' :
case 'extensions.treestyletab.tabbar.shrunkenWidth' :
2011-03-24 22:42:50 -04:00
return this . updateTabWidthPrefs ( aPrefName ) ;
2009-12-25 13:13:33 -05:00
2010-05-02 00:32:08 -04:00
case 'browser.tabs.insertRelatedAfterCurrent' :
2009-12-25 13:13:33 -05:00
case 'browser.tabs.loadFolderAndReplace' :
2010-03-31 06:34:30 -04:00
case 'extensions.stm.tabBarMultiRows' : // Super Tab Mode
2009-12-25 13:13:33 -05:00
if ( this . prefOverriding ) return ;
aPrefName += '.override' ;
2013-01-05 21:47:50 -05:00
prefs . setPref ( aPrefName , value ) ;
2010-05-02 00:32:08 -04:00
case 'browser.tabs.insertRelatedAfterCurrent.override' :
2009-12-25 13:13:33 -05:00
case 'browser.tabs.loadFolderAndReplace.override' :
2010-03-31 06:34:30 -04:00
case 'extensions.stm.tabBarMultiRows.override' : // Super Tab Mode
2013-01-05 21:47:50 -05:00
if ( prefs . getPref ( aPrefName + '.force' ) ) {
let defaultValue = prefs . getDefaultPref ( aPrefName ) ;
2010-05-02 00:51:19 -04:00
if ( value != defaultValue ) {
2013-01-05 21:47:50 -05:00
prefs . setPref ( aPrefName , defaultValue ) ;
2010-05-02 00:51:19 -04:00
return ;
}
2010-05-02 00:32:08 -04:00
}
2009-12-25 13:13:33 -05:00
this . prefOverriding = true ;
2010-05-02 00:51:19 -04:00
let ( target = aPrefName . replace ( '.override' , '' ) ) {
2013-01-05 21:47:50 -05:00
let originalValue = prefs . getPref ( target ) ;
2010-05-02 00:51:19 -04:00
if ( originalValue !== null && originalValue != value )
2013-01-05 21:47:50 -05:00
prefs . setPref ( target + '.backup' , originalValue ) ;
prefs . setPref ( target , prefs . getPref ( aPrefName ) ) ;
2010-05-02 00:51:19 -04:00
}
2009-12-25 13:13:33 -05:00
this . prefOverriding = false ;
2011-03-24 22:42:50 -04:00
return ;
2009-12-25 13:13:33 -05:00
case 'extensions.treestyletab.clickOnIndentSpaces.enabled' :
2013-01-05 21:47:50 -05:00
return this . shouldDetectClickOnIndentSpaces = prefs . getPref ( aPrefName ) ;
2009-12-25 13:13:33 -05:00
case 'extensions.treestyletab.tabbar.scroll.smooth' :
2011-03-24 22:42:50 -04:00
return this . smoothScrollEnabled = value ;
2009-12-25 13:13:33 -05:00
case 'extensions.treestyletab.tabbar.scroll.duration' :
2011-03-24 22:42:50 -04:00
return this . smoothScrollDuration = value ;
2009-12-25 13:13:33 -05:00
2010-07-25 12:13:19 -04:00
case 'extensions.treestyletab.tabbar.scrollToNewTab.mode' :
2011-03-24 22:42:50 -04:00
return this . scrollToNewTabMode = value ;
case 'extensions.treestyletab.tabbar.narrowScrollbar.size' :
return this . updateNarrowScrollbarStyle ( ) ;
2010-07-25 12:13:19 -04:00
2012-11-27 13:34:57 -05:00
case 'browser.tabs.animate' :
2011-03-24 22:42:50 -04:00
return this . animationEnabled = value ;
2009-12-25 13:13:33 -05:00
case 'extensions.treestyletab.animation.indent.duration' :
2011-03-24 22:42:50 -04:00
return this . indentDuration = value ;
2009-12-25 13:13:33 -05:00
case 'extensions.treestyletab.animation.collapse.duration' :
2011-03-24 22:42:50 -04:00
return this . collapseDuration = value ;
2009-12-25 13:13:33 -05:00
case 'extensions.treestyletab.twisty.expandSensitiveArea' :
2011-03-24 22:42:50 -04:00
return this . shouldExpandTwistyArea = value ;
2009-12-25 13:13:33 -05:00
2012-01-13 11:45:51 -05:00
case 'extensions.treestyletab.counter.role.horizontal' :
return this . counterRoleHorizontal = value ;
case 'extensions.treestyletab.counter.role.vertical' :
return this . counterRoleVertical = value ;
2009-12-25 11:56:45 -05:00
default :
2011-03-24 22:42:50 -04:00
return ;
2009-12-25 11:56:45 -05:00
}
} ,
2009-12-25 13:13:33 -05:00
2013-03-05 12:56:29 -05:00
updateTabWidthPrefs : function TSTBase _updateTabWidthPrefs ( aPrefName )
2009-12-25 13:13:33 -05:00
{
2012-10-23 12:43:56 -04:00
var expanded = utils . getTreePref ( 'tabbar.width' ) ;
var shrunken = utils . getTreePref ( 'tabbar.shrunkenWidth' ) ;
2010-04-22 05:24:21 -04:00
var originalExpanded = expanded ;
var originalShrunken = shrunken ;
if ( aPrefName == 'extensions.treestyletab.tabbar.shrunkenWidth' ) {
if ( expanded <= shrunken )
expanded = parseInt ( shrunken / this . DEFAULT _SHRUNKEN _WIDTH _RATIO )
let w = this . browserWindow ;
if ( w && expanded > w . gBrowser . boxObject . width ) {
expanded = w . gBrowser . boxObject . width * this . MAX _TABBAR _SIZE _RATIO ;
if ( expanded <= shrunken )
shrunken = parseInt ( expanded * this . DEFAULT _SHRUNKEN _WIDTH _RATIO )
}
}
else {
if ( expanded <= shrunken )
shrunken = parseInt ( expanded * this . DEFAULT _SHRUNKEN _WIDTH _RATIO ) ;
}
if ( expanded != originalExpanded ||
shrunken != originalShrunken ) {
2012-10-23 12:43:56 -04:00
utils . setTreePref ( 'tabbar.width' , Math . max ( 0 , expanded ) ) ;
utils . setTreePref ( 'tabbar.shrunkenWidth' , Math . max ( 0 , shrunken ) ) ;
2009-12-25 13:13:33 -05:00
}
} ,
2012-10-19 08:38:35 -04:00
2013-01-04 01:30:08 -05:00
get shouldApplyNewPref ( )
2011-04-06 08:05:59 -04:00
{
return (
! this . applyOnlyForActiveWindow ||
this . window == this . topBrowserWindow
) &&
! this . inWindowDestoructionProcess ;
} ,
2011-05-04 04:10:02 -04:00
applyOnlyForActiveWindow : false ,
2013-03-05 12:56:29 -05:00
setPrefForActiveWindow : function TSTBase _setPrefForActiveWindow ( aTask ) {
2012-09-27 02:40:14 -04:00
TreeStyleTabBase . applyOnlyForActiveWindow = true ;
2011-04-06 08:05:59 -04:00
try {
aTask . call ( this ) ;
}
finally {
2012-09-27 02:40:14 -04:00
TreeStyleTabBase . applyOnlyForActiveWindow = false ;
2011-04-06 08:05:59 -04:00
}
2009-12-25 11:51:24 -05:00
}
2013-01-04 01:30:08 -05:00
2009-12-25 11:51:24 -05:00
} ;
2013-01-04 01:30:08 -05:00
TreeStyleTabBase . init ( ) ;