2 * Collapsible tabs jQuery Plugin
5 var rtl
= $( 'html' ).attr( 'dir' ) === 'rtl';
6 $.fn
.collapsibleTabs = function ( options
) {
7 // return if the function is called on an empty jquery object
11 // Merge options into the defaults
12 var settings
= $.extend( {}, $.collapsibleTabs
.defaults
, options
);
14 this.each( function () {
16 // add the element to our array of collapsible managers
17 $.collapsibleTabs
.instances
= ( $.collapsibleTabs
.instances
.length
=== 0 ?
18 $el
: $.collapsibleTabs
.instances
.add( $el
) );
19 // attach the settings to the elements
20 $el
.data( 'collapsibleTabsSettings', settings
);
21 // attach data to our collapsible elements
22 $el
.children( settings
.collapsible
).each( function () {
23 $.collapsibleTabs
.addData( $( this ) );
27 // if we haven't already bound our resize handler, bind it now
28 if ( !$.collapsibleTabs
.boundEvent
) {
29 $( window
).on( 'resize', $.debounce( 500, function () {
30 $.collapsibleTabs
.handleResize();
32 $.collapsibleTabs
.boundEvent
= true;
35 // call our resize handler to setup the page
36 $.collapsibleTabs
.handleResize();
43 expandedContainer
: '#p-views ul',
44 collapsedContainer
: '#p-cactions ul',
45 collapsible
: 'li.collapsible',
47 expandCondition: function ( eleWidth
) {
48 // If there are at least eleWidth + 1 pixels of free space, expand.
49 // We add 1 because .width() will truncate fractional values but .offset() will not.
50 return $.collapsibleTabs
.calculateTabDistance() >= eleWidth
+ 1;
52 collapseCondition: function () {
53 // If there's an overlap, collapse.
54 return $.collapsibleTabs
.calculateTabDistance() < 0;
57 addData: function ( $collapsible
) {
58 var settings
= $collapsible
.parent().data( 'collapsibleTabsSettings' );
60 $collapsible
.data( 'collapsibleTabsSettings', {
61 expandedContainer
: settings
.expandedContainer
,
62 collapsedContainer
: settings
.collapsedContainer
,
63 expandedWidth
: $collapsible
.width(),
64 prevElement
: $collapsible
.prev()
68 getSettings: function ( $collapsible
) {
69 var settings
= $collapsible
.data( 'collapsibleTabsSettings' );
71 $.collapsibleTabs
.addData( $collapsible
);
72 settings
= $collapsible
.data( 'collapsibleTabsSettings' );
76 handleResize: function () {
77 $.collapsibleTabs
.instances
.each( function () {
79 data
= $.collapsibleTabs
.getSettings( $el
);
81 if ( data
.shifting
) {
85 // if the two navigations are colliding
86 if ( $el
.children( data
.collapsible
).length
> 0 && data
.collapseCondition() ) {
88 $el
.trigger( 'beforeTabCollapse' );
89 // move the element to the dropdown menu
90 $.collapsibleTabs
.moveToCollapsed( $el
.children( data
.collapsible
+ ':last' ) );
93 // if there are still moveable items in the dropdown menu,
94 // and there is sufficient space to place them in the tab container
95 if ( $( data
.collapsedContainer
+ ' ' + data
.collapsible
).length
> 0 &&
96 data
.expandCondition( $.collapsibleTabs
.getSettings( $( data
.collapsedContainer
).children(
97 data
.collapsible
+ ':first' ) ).expandedWidth
) ) {
98 //move the element from the dropdown to the tab
99 $el
.trigger( 'beforeTabExpand' );
101 .moveToExpanded( data
.collapsedContainer
+ ' ' + data
.collapsible
+ ':first' );
105 moveToCollapsed: function ( ele
) {
106 var outerData
, expContainerSettings
, target
,
109 outerData
= $.collapsibleTabs
.getSettings( $moving
);
113 expContainerSettings
= $.collapsibleTabs
.getSettings( $( outerData
.expandedContainer
) );
114 if ( !expContainerSettings
) {
117 expContainerSettings
.shifting
= true;
119 // Remove the element from where it's at and put it in the dropdown menu
120 target
= outerData
.collapsedContainer
;
121 $moving
.css( 'position', 'relative' )
122 .css( ( rtl
? 'left' : 'right' ), 0 )
123 .animate( { width
: '1px' }, 'normal', function () {
124 var data
, expContainerSettings
;
126 // add the placeholder
127 $( '<span class="placeholder" style="display: none;"></span>' ).insertAfter( this );
128 $( this ).detach().prependTo( target
).data( 'collapsibleTabsSettings', outerData
);
129 $( this ).attr( 'style', 'display: list-item;' );
130 data
= $.collapsibleTabs
.getSettings( $( ele
) );
132 expContainerSettings
= $.collapsibleTabs
.getSettings( $( data
.expandedContainer
) );
133 if ( expContainerSettings
) {
134 expContainerSettings
.shifting
= false;
135 $.collapsibleTabs
.handleResize();
140 moveToExpanded: function ( ele
) {
141 var data
, expContainerSettings
, $target
, expandedWidth
,
144 data
= $.collapsibleTabs
.getSettings( $moving
);
148 expContainerSettings
= $.collapsibleTabs
.getSettings( $( data
.expandedContainer
) );
149 if ( !expContainerSettings
) {
152 expContainerSettings
.shifting
= true;
154 // grab the next appearing placeholder so we can use it for replacing
155 $target
= $( data
.expandedContainer
).find( 'span.placeholder:first' );
156 expandedWidth
= data
.expandedWidth
;
157 $moving
.css( 'position', 'relative' ).css( ( rtl
? 'right' : 'left' ), 0 ).css( 'width', '1px' );
161 .css( 'width', '1px' )
162 .data( 'collapsibleTabsSettings', data
)
163 .animate( { width
: expandedWidth
+ 'px' }, 'normal', function () {
164 $( this ).attr( 'style', 'display: block;' );
165 var data
, expContainerSettings
;
166 data
= $.collapsibleTabs
.getSettings( $( this ) );
168 expContainerSettings
= $.collapsibleTabs
.getSettings( $( data
.expandedContainer
) );
169 if ( expContainerSettings
) {
170 expContainerSettings
.shifting
= false;
171 $.collapsibleTabs
.handleResize();
178 * Returns the amount of horizontal distance between the two tabs groups
179 * (#left-navigation and #right-navigation), in pixels. If negative, this
180 * means that the tabs overlap, and the value is the width of overlapping
183 * Used in default expandCondition and collapseCondition.
185 * @return {Numeric} distance/overlap in pixels
187 calculateTabDistance: function () {
188 var $leftTab
, $rightTab
, leftEnd
, rightStart
;
190 // In RTL, #right-navigation is actually on the left and vice versa.
191 // Hooray for descriptive naming.
193 $leftTab
= $( '#left-navigation' );
194 $rightTab
= $( '#right-navigation' );
196 $leftTab
= $( '#right-navigation' );
197 $rightTab
= $( '#left-navigation' );
200 leftEnd
= $leftTab
.offset().left
+ $leftTab
.width();
201 rightStart
= $rightTab
.offset().left
;
203 return rightStart
- leftEnd
;