55
66const VERTICAL_TABS_POSITION = 'pulse.tabs.vertical'
77const VERTICAL_TABS_COLLAPSE = 'pulse.tabs.vertical.collapse'
8+ const VERTICAL_TABS_WIDTH = 'pulse.tabs.vertical.width'
9+
10+ /**
11+ * @param {HTMLElement } toInsertAfter This is the element that I want to insert content after
12+ * @param {HTMLElement } toInsert The element to insert
13+ *
14+ * @throws {Error } If the element you want me to base insertions on has no parent
15+ */
16+ function insertAfter ( toInsertAfter , toInsert ) {
17+ const parent = toInsertAfter . parentNode
18+
19+ if ( ! parent ) {
20+ throw new Error (
21+ 'The element you want me to base insertions on has no parent'
22+ )
23+ }
24+
25+ if ( toInsertAfter . nextSibling ) {
26+ parent . insertBefore ( toInsert , toInsertAfter . nextSibling )
27+ } else {
28+ parent . appendChild ( toInsert )
29+ }
30+ }
31+
32+ /**
33+ * Replace a tag with another tag with a different name
34+ * @param {string } tagName The new tag name
35+ * @param {HTMLElement? } initialTag The tag to be changed
36+ */
37+ function changeXULTagName ( tagName , initialTag ) {
38+ if ( ! initialTag ) return
39+ if ( initialTag . tagName == tagName ) return
40+
41+ const newParent = document . createXULElement ( tagName )
42+
43+ for ( const attr of initialTag . attributes )
44+ newParent . setAttribute ( attr . name , attr . value )
45+ while ( initialTag . firstChild ) newParent . appendChild ( initialTag . firstChild )
46+
47+ initialTag . replaceWith ( newParent )
48+ }
849
950var VerticalTabs = {
1051 /**
@@ -35,6 +76,13 @@ var VerticalTabs = {
3576 return document . getElementById ( 'browser' )
3677 } ,
3778
79+ /**
80+ * @return {HTMLElement? }
81+ */
82+ get splitter ( ) {
83+ return document . getElementById ( 'verticaltabs-splitter' )
84+ } ,
85+
3886 /**
3987 * @return {Boolean }
4088 */
@@ -48,6 +96,8 @@ var VerticalTabs = {
4896 tabBrowserTabs : null ,
4997
5098 _initialized : false ,
99+ /** @type {MutationObserver? } */
100+ _widthObserver : null ,
51101
52102 init ( ) {
53103 if ( this . _initialized ) {
@@ -79,9 +129,40 @@ var VerticalTabs = {
79129 . querySelector ( '#TabsToolbar .toolbar-items' )
80130 ?. setAttribute ( 'align' , 'start' )
81131
82- document
83- . getElementById ( 'TabsToolbar' )
84- ?. setAttribute ( 'collapse' , this . browserCollapseTabs ? 'true' : 'false' )
132+ this . tabsToolbar ?. setAttribute (
133+ 'collapse' ,
134+ this . browserCollapseTabs ? 'true' : 'false'
135+ )
136+ this . tabsToolbar ?. removeAttribute ( 'flex' )
137+ changeXULTagName ( 'vbox' , this . tabsToolbar )
138+
139+ this . _widthObserver = new MutationObserver ( this . _mutationObserverCallback )
140+ if ( this . tabsToolbar )
141+ this . _widthObserver . observe ( this . tabsToolbar , { attributes : true } )
142+
143+ this . tabsToolbar ?. setAttribute (
144+ 'width' ,
145+ Services . prefs . getIntPref ( VERTICAL_TABS_WIDTH , 200 )
146+ )
147+ if ( this . tabsToolbar )
148+ this . tabsToolbar . style . width = `${ Services . prefs . getIntPref (
149+ VERTICAL_TABS_WIDTH ,
150+ 200
151+ ) } px`
152+
153+ if ( ! this . splitter ) {
154+ const separator = document . createXULElement ( 'splitter' )
155+ separator . setAttribute ( 'id' , 'verticaltabs-splitter' )
156+ separator . setAttribute (
157+ 'class' ,
158+ 'chromeclass-extrachrome verticaltabs-splitter'
159+ )
160+ separator . setAttribute ( 'resizebefore' , 'none' )
161+ separator . setAttribute ( 'resizeafter' , 'sibling' )
162+
163+ const tabs = this . tabsToolbar
164+ if ( tabs ) tabs . parentElement ?. insertBefore ( separator , tabs )
165+ }
85166 } ,
86167
87168 disableVerticalTabs ( ) {
@@ -96,6 +177,39 @@ var VerticalTabs = {
96177 document
97178 . querySelector ( '#TabsToolbar .toolbar-items' )
98179 ?. setAttribute ( 'align' , 'end' )
180+
181+ if ( this . tabsToolbar ) {
182+ changeXULTagName ( 'toolbar' , this . tabsToolbar )
183+ this . tabsToolbar . setAttribute ( 'flex' , '1' )
184+ // Reset the resize value, or else the tabs will end up squished
185+ this . tabsToolbar . style . width = ''
186+ }
187+
188+ if ( this . splitter ) {
189+ this . splitter . remove ( )
190+ }
191+
192+ if ( this . _widthObserver ) {
193+ this . _widthObserver . disconnect ( )
194+ this . _widthObserver = null
195+ }
196+ } ,
197+
198+ /**
199+ * @param {MutationRecord[] } mutationsList
200+ * @param {MutationObserver } _observer
201+ */
202+ _mutationObserverCallback ( mutationsList , _observer ) {
203+ for ( const mutation of mutationsList ) {
204+ if ( mutation . type === 'attributes' && mutation . attributeName == 'width' ) {
205+ const tabsToolbar = document . getElementById ( 'TabsToolbar' )
206+
207+ Services . prefs . setIntPref (
208+ VERTICAL_TABS_WIDTH ,
209+ parseInt ( tabsToolbar ?. getAttribute ( 'width' ) || '100' )
210+ )
211+ }
212+ }
99213 } ,
100214
101215 /**
0 commit comments