Vector: Fix conflicts of "Actions" dropdown with collapsibleTabs
authorBartosz Dziewoński <matma.rex@gmail.com>
Sat, 31 May 2014 20:55:40 +0000 (22:55 +0200)
committerOri.livneh <ori@wikimedia.org>
Sun, 1 Jun 2014 05:05:51 +0000 (05:05 +0000)
Follow-up to I09c8031c.

* Don't override the width of the "Actions" dropdown when collapsing
  tabs. The width was hardcoded to 24px, using the actual width now.
  This only matters when the "Actions" dropdown disappears completely
  (it has no items inside), and then something gets moved inside it
  causing it to reappear.
* Use the same collapsing speed for the dropdown and the tabs.
* Account for the width of the "Actions" dropdown if the expansion
  would hide it. This issue was there before, but was not that
  noticeable because the width of the dropdown was negligible.
  (This required making the calculateTabDistance() function in
  collapsibleTabs part of the public API.)
* Do not collapse if the width of the dropdown would exceed the width
  of the tab we're collapsing. This issue was there before as well,
  but in practice the dropdown was always smaller; this is not
  necessarily the case now, for example in Lithuanian (lt).

Bug: 44591
Change-Id: Id4548ea388fd9f4341dd78bb132c716feb14b137

skins/vector/collapsibleTabs.js
skins/vector/vector.js

index 9344433..e24bea9 100644 (file)
                $.collapsibleTabs.handleResize();
                return this;
        };
-       /**
-        * Returns the amount of horizontal distance between the two tabs groups
-        * (#left-navigation and #right-navigation), in pixels. If negative, this
-        * means that the tabs overlap, and the value is the width of overlapping
-        * parts.
-        *
-        * Used in default expandCondition and collapseCondition.
-        *
-        * @return {Numeric} distance/overlap in pixels
-        */
-       function calculateTabDistance() {
-               var $leftTab, $rightTab, leftEnd, rightStart;
-
-               // In RTL, #right-navigation is actually on the left and vice versa.
-               // Hooray for descriptive naming.
-               if ( !rtl ) {
-                       $leftTab = $( '#left-navigation' );
-                       $rightTab = $( '#right-navigation' );
-               } else {
-                       $leftTab = $( '#right-navigation' );
-                       $rightTab = $( '#left-navigation' );
-               }
-
-               leftEnd = $leftTab.offset().left + $leftTab.width();
-               rightStart = $rightTab.offset().left;
-
-               return rightStart - leftEnd;
-       }
        $.collapsibleTabs = {
                instances: [],
                boundEvent: null,
                        shifting: false,
                        expandCondition: function ( eleWidth ) {
                                // If there are at least eleWidth + 1 pixels of free space, expand.
-                               // We add 1 because .width() will truncate fractional values
-                               // but .offset() will not.
-                               return calculateTabDistance() >= (eleWidth + 1);
+                               // We add 1 because .width() will truncate fractional values but .offset() will not.
+                               return $.collapsibleTabs.calculateTabDistance() >= eleWidth + 1;
                        },
                        collapseCondition: function () {
                                // If there's an overlap, collapse.
-                               return calculateTabDistance() < 0;
+                               return $.collapsibleTabs.calculateTabDistance() < 0;
                        }
                },
                addData: function ( $collapsible ) {
                                        }
                                } )
                        );
+               },
+               /**
+                * Returns the amount of horizontal distance between the two tabs groups
+                * (#left-navigation and #right-navigation), in pixels. If negative, this
+                * means that the tabs overlap, and the value is the width of overlapping
+                * parts.
+                *
+                * Used in default expandCondition and collapseCondition.
+                *
+                * @return {Numeric} distance/overlap in pixels
+                */
+               calculateTabDistance: function () {
+                       var $leftTab, $rightTab, leftEnd, rightStart;
+
+                       // In RTL, #right-navigation is actually on the left and vice versa.
+                       // Hooray for descriptive naming.
+                       if ( !rtl ) {
+                               $leftTab = $( '#left-navigation' );
+                               $rightTab = $( '#right-navigation' );
+                       } else {
+                               $leftTab = $( '#right-navigation' );
+                               $rightTab = $( '#left-navigation' );
+                       }
+
+                       leftEnd = $leftTab.offset().left + $leftTab.width();
+                       rightStart = $rightTab.offset().left;
+
+                       return rightStart - leftEnd;
                }
        };
 
index 58ba2af..c603615 100644 (file)
@@ -35,28 +35,67 @@ jQuery( function ( $ ) {
        /**
         * Collapsible tabs for Vector
         */
-       var $cactions = $( '#p-cactions' );
+       var $cactions = $( '#p-cactions' ),
+               $tabContainer = $( '#p-views ul' ),
+               originalDropdownWidth = $cactions.width();
 
        // Bind callback functions to animate our drop down menu in and out
        // and then call the collapsibleTabs function on the menu
-       $( '#p-views ul' )
+       $tabContainer
                .bind( 'beforeTabCollapse', function () {
                        // If the dropdown was hidden, show it
                        if ( $cactions.hasClass( 'emptyPortlet' ) ) {
                                $cactions
                                        .removeClass( 'emptyPortlet' )
                                        .find( 'h3' )
-                                               .css( 'width', '1px' ).animate( { 'width': '24px' }, 390 );
+                                               .css( 'width', '1px' ).animate( { 'width': originalDropdownWidth }, 'normal' );
                        }
                } )
                .bind( 'beforeTabExpand', function () {
                        // If we're removing the last child node right now, hide the dropdown
                        if ( $cactions.find( 'li' ).length === 1 ) {
-                               $cactions.find( 'h3' ).animate( { 'width': '1px' }, 390, function () {
+                               $cactions.find( 'h3' ).animate( { 'width': '1px' }, 'normal', function () {
                                        $( this ).attr( 'style', '' )
                                                .parent().addClass( 'emptyPortlet' );
                                });
                        }
                } )
-               .collapsibleTabs();
+               .collapsibleTabs( {
+                       expandCondition: function ( eleWidth ) {
+                               // (This looks a bit awkward because we're doing expensive queries as late as possible.)
+
+                               var distance = $.collapsibleTabs.calculateTabDistance();
+                               // If there are at least eleWidth + 1 pixels of free space, expand.
+                               // We add 1 because .width() will truncate fractional values but .offset() will not.
+                               if ( distance >= eleWidth + 1 ) {
+                                       return true;
+                               } else {
+                                       // Maybe we can still expand? Account for the width of the "Actions" dropdown if the
+                                       // expansion would hide it.
+                                       if ( $cactions.find( 'li' ).length === 1 ) {
+                                               return distance >= eleWidth + 1 - originalDropdownWidth;
+                                       } else {
+                                               return false;
+                                       }
+                               }
+                       },
+                       collapseCondition: function () {
+                               // (This looks a bit awkward because we're doing expensive queries as late as possible.)
+                               // TODO The dropdown itself should probably "fold" to just the down-arrow (hiding the text)
+                               // if it can't fit on the line?
+
+                               // If there's an overlap, collapse.
+                               if ( $.collapsibleTabs.calculateTabDistance() < 0 ) {
+                                       // But only if the width of the tab to collapse is smaller than the width of the dropdown
+                                       // we would have to insert. An example language where this happens is Lithuanian (lt).
+                                       if ( $cactions.hasClass( 'emptyPortlet' ) ) {
+                                               return $tabContainer.children( 'li.collapsible:last' ).width() > originalDropdownWidth;
+                                       } else {
+                                               return true;
+                                       }
+                               } else {
+                                       return false;
+                               }
+                       }
+               } );
 } );