Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
fix(tabs): avoid width calculation deviations.
Browse files Browse the repository at this point in the history
* Currently when using centered tabs, the `updateInkBarStyles` method is getting executed infinitely (even without $$rAF, sync)
 This is impacting the performance significant, because we're calculating the styles on each function call.

The problem is, that the pagination wrapper uses another rounding process than the `updateInkBarStyle` method.
Now both calculations are using the same rounding process / logic and the width's are now correct.

Fixes #8289.

Closes #8293
  • Loading branch information
devversion authored and ThomasBurleson committed Jun 3, 2016
1 parent e5dcbab commit efbbd37
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions src/components/tabs/js/tabsController.js
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,11 @@ function MdTabsController ($scope, $element, $window, $mdConstant, $mdTabInkRipp
function shouldPaginate () {
if (ctrl.noPagination || !loaded) return false;
var canvasWidth = $element.prop('clientWidth');
angular.forEach(getElements().dummies, function (tab) { canvasWidth -= tab.offsetWidth; });

angular.forEach(getElements().dummies, function (tab) {
canvasWidth -= tab.offsetWidth;
});

return canvasWidth < 0;
}

Expand Down Expand Up @@ -570,17 +574,22 @@ function MdTabsController ($scope, $element, $window, $mdConstant, $mdTabInkRipp
}

/**
* Calculates the width of the pagination wrapper by summing the widths of the dummy tabs.
* @returns {number}
*/
function calcPagingWidth () {
var width = 1;
return calcTabsWidth(getElements().dummies);
}

function calcTabsWidth(tabs) {
var width = 0;

angular.forEach(getElements().dummies, function (element) {
angular.forEach(tabs, function (tab) {
//-- Uses the larger value between `getBoundingClientRect().width` and `offsetWidth`. This
// prevents `offsetWidth` value from being rounded down and causing wrapping issues, but
// also handles scenarios where `getBoundingClientRect()` is inaccurate (ie. tabs inside
// of a dialog)
width += Math.max(element.offsetWidth, element.getBoundingClientRect().width);
width += Math.max(tab.offsetWidth, tab.getBoundingClientRect().width);
});

return Math.ceil(width);
Expand Down Expand Up @@ -746,21 +755,25 @@ function MdTabsController ($scope, $element, $window, $mdConstant, $mdTabInkRipp
angular.element(elements.inkBar).css({ left: 'auto', right: 'auto' });
return;
}

if (!ctrl.tabs.length) return queue.push(ctrl.updateInkBarStyles);
// if the element is not visible, we will not be able to calculate sizes until it is
// we should treat that as a resize event rather than just updating the ink bar
if (!$element.prop('offsetParent')) return handleResizeWhenVisible();

var index = ctrl.selectedIndex,
totalWidth = elements.paging.offsetWidth,
tab = elements.tabs[ index ],
left = tab.offsetLeft,
right = totalWidth - left - tab.offsetWidth,
tabWidth;
right = totalWidth - left - tab.offsetWidth;

if (ctrl.shouldCenterTabs) {
tabWidth = Array.prototype.slice.call(elements.tabs).reduce(function (value, element) {
return value + element.offsetWidth;
}, 0);
if (totalWidth > tabWidth) $mdUtil.nextTick(updateInkBarStyles, false);
// We need to use the same calculate process as in the pagination wrapper, to avoid rounding deviations.
var tabWidth = calcTabsWidth(elements.tabs);

if (totalWidth > tabWidth) {
$mdUtil.nextTick(updateInkBarStyles, false);
}
}
updateInkBarClassName();
angular.element(elements.inkBar).css({ left: left + 'px', right: right + 'px' });
Expand Down

0 comments on commit efbbd37

Please sign in to comment.