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

Commit

Permalink
fix(mdToolbar): Allow md-scroll-shrink usage with ng-if.
Browse files Browse the repository at this point in the history
Previously, the toolbar would fail to enable scroll shrinking
if the developer used an `ng-if` statement on the `md-toolbar`.

This commit allows usage of `ng-if` as well as watching the
`md-scroll-shrink` for changes so they can enable/disable
scroll shrinking.

Fixes #2751.
  • Loading branch information
topherfangio committed Aug 31, 2015
1 parent 303ab0d commit 9e5432e
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 15 deletions.
68 changes: 56 additions & 12 deletions src/components/toolbar/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,17 @@ angular.module('material.components.toolbar', [
* at one fourth the rate at which the user scrolls down. Default 0.5.
*/

function mdToolbarDirective($$rAF, $mdConstant, $mdUtil, $mdTheming, $animate ) {
var translateY = angular.bind(null, $mdUtil.supplant, 'translate3d(0,{0}px,0)' );
function mdToolbarDirective($$rAF, $mdConstant, $mdUtil, $mdTheming, $animate) {
var translateY = angular.bind(null, $mdUtil.supplant, 'translate3d(0,{0}px,0)');

return {
restrict: 'E',
template: '<div ng-transclude></div>',
transclude: true,
controller: angular.noop,
scope: {
scrollShrink: '=?mdScrollShrink'
},
link: function(scope, element, attr) {

$mdTheming(element);
Expand Down Expand Up @@ -89,6 +94,48 @@ function mdToolbarDirective($$rAF, $mdConstant, $mdUtil, $mdTheming, $animate )
// to scroll events.
scope.$on('$mdContentLoaded', onMdContentLoad);

// If the toolbar is used inside an ng-if statement, we may miss the
// $mdContentLoaded event, so we attempt to fake it if we have a
// md-content close enough.
scope.$watch('scrollShrink', function(scrollShrink) {
var closestContent = element.parent().find('md-content');

// If we have a content element, fake the call; this might still fail
// if the content element isn't a sibling of the toolbar
if (!contentElement && closestContent.length) {
onMdContentLoad(null, closestContent);
}

if (contentElement) {
// Disable only if the attribute's expression evaluates to false
if (scrollShrink === false) {
disableScrollShrink();
} else {
enableScrollShrink();
}
}
});

// If the scope is destroyed (which could happen with ng-if), make sure
// to disable scroll shrinking again
scope.$on('$destroy', function() {
disableScrollShrink();
});

function enableScrollShrink() {
contentElement.on('scroll', debouncedContentScroll);
contentElement.attr('scroll-shrink', 'true');

$$rAF(updateToolbarHeight);
}

function disableScrollShrink() {
contentElement.off('scroll', debouncedContentScroll);
contentElement.attr('scroll-shrink', 'false');

$$rAF(updateToolbarHeight);
}

function onMdContentLoad($event, newContentEl) {
// Toolbar and content must be siblings
if (element.parent()[0] === newContentEl.parent()[0]) {
Expand All @@ -97,11 +144,8 @@ function mdToolbarDirective($$rAF, $mdConstant, $mdUtil, $mdTheming, $animate )
contentElement.off('scroll', debouncedContentScroll);
}

newContentEl.on('scroll', debouncedContentScroll);
newContentEl.attr('scroll-shrink', 'true');

contentElement = newContentEl;
$$rAF(updateToolbarHeight);
enableScrollShrink();
}
}

Expand All @@ -113,7 +157,7 @@ function mdToolbarDirective($$rAF, $mdConstant, $mdUtil, $mdTheming, $animate )
//
// As the user scrolls down, the content will be transformed up slowly
// to put the content underneath where the toolbar was.
var margin = (-toolbarHeight * shrinkSpeedFactor) + 'px';
var margin = (-toolbarHeight * shrinkSpeedFactor) + 'px';
contentElement.css('margin-top', margin);
contentElement.css('margin-bottom', margin);

Expand All @@ -130,17 +174,17 @@ function mdToolbarDirective($$rAF, $mdConstant, $mdUtil, $mdTheming, $animate )
Math.max(0, y + scrollTop - prevScrollTop)
);

element.css( $mdConstant.CSS.TRANSFORM, translateY([-y * shrinkSpeedFactor]) );
contentElement.css( $mdConstant.CSS.TRANSFORM, translateY([(toolbarHeight - y) * shrinkSpeedFactor]) );
element.css($mdConstant.CSS.TRANSFORM, translateY([-y * shrinkSpeedFactor]));
contentElement.css($mdConstant.CSS.TRANSFORM, translateY([(toolbarHeight - y) * shrinkSpeedFactor]));

prevScrollTop = scrollTop;

$mdUtil.nextTick(function () {
$mdUtil.nextTick(function() {
var hasWhiteFrame = element.hasClass('md-whiteframe-z1');

if ( hasWhiteFrame && !y) {
if (hasWhiteFrame && !y) {
$animate.removeClass(element, 'md-whiteframe-z1');
} else if ( !hasWhiteFrame && y ) {
} else if (!hasWhiteFrame && y) {
$animate.addClass(element, 'md-whiteframe-z1');
}
});
Expand Down
87 changes: 84 additions & 3 deletions src/components/toolbar/toolbar.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
describe('<md-toolbar>', function() {

var pageScope, element, controller;
var $rootScope, $timeout;

beforeEach(module('material.components.toolbar'));
beforeEach(inject(function(_$rootScope_, _$timeout_) {
$rootScope = _$rootScope_;
$timeout = _$timeout_;
}));

it('with scrollShrink, it should shrink scrollbar when going to bottom', inject(function($compile, $rootScope, $mdConstant, mdToolbarDirective, $$rAF) {

Expand Down Expand Up @@ -28,7 +35,7 @@ describe('<md-toolbar>', function() {
});

// Manually link so we can give our own elements with spies on them
mdToolbarDirective[0].link($rootScope, toolbar, {
mdToolbarDirective[0].link($rootScope, toolbar, {
mdScrollShrink: true,
mdShrinkSpeedFactor: 1
});
Expand All @@ -47,7 +54,7 @@ describe('<md-toolbar>', function() {
// Fake scroll to the bottom
contentEl.triggerHandler({
type: 'scroll',
target: { scrollTop: 500 }
target: {scrollTop: 500}
});
$$rAF.flush();

Expand All @@ -57,12 +64,86 @@ describe('<md-toolbar>', function() {
// Fake scroll back to the top
contentEl.triggerHandler({
type: 'scroll',
target: { scrollTop: 0 }
target: {scrollTop: 0}
});
$$rAF.flush();

expect(toolbarCss[$mdConstant.CSS.TRANSFORM]).toEqual('translate3d(0,0px,0)');
expect(contentCss[$mdConstant.CSS.TRANSFORM]).toEqual('translate3d(0,100px,0)');

}));

it('works without ng-if', inject(function() {
build(
'<div>' +
' <md-toolbar md-scroll-shrink="true"></md-toolbar>' +
' <md-content></md-content>' +
'</div>'
);

expect(element.find('md-content').attr('scroll-shrink')).toEqual('true');
}));

it('works with ng-if', inject(function() {
build(
'<div>' +
' <md-toolbar md-scroll-shrink="true" ng-if="shouldShowToolbar"></md-toolbar>' +
' <md-content></md-content>' +
'</div>'
);

// It starts out undefined
expect(element.find('md-content').attr('scroll-shrink')).toEqual(undefined);

// Change the ng-if to add the toolbar
pageScope.$apply('shouldShowToolbar = true');
expect(element.find('md-content').attr('scroll-shrink')).toEqual('true');

// Change the ng-if to remove the toolbar
pageScope.$apply('shouldShowToolbar = false');
expect(element.find('md-content').attr('scroll-shrink')).toEqual('false');
}));

it('enables scroll shrink when the attribute has no value', function() {
build(
'<div>' +
' <md-toolbar md-scroll-shrink></md-toolbar>' +
' <md-content></md-content>' +
'</div>'
);

expect(element.find('md-content').attr('scroll-shrink')).toEqual('true');
});

it('watches the value of scroll shrink', function() {
build(
'<div>' +
' <md-toolbar md-scroll-shrink="shouldShrink"></md-toolbar>' +
' <md-content></md-content>' +
'</div>'
);

// It starts out undefined which SHOULD add the scroll shrink because it acts as if no value
// was specified
expect(element.find('md-content').attr('scroll-shrink')).toEqual('true');

// Change the scrollShink to false
pageScope.$apply('shouldShrink = false');
expect(element.find('md-content').attr('scroll-shrink')).toEqual('false');

// Change the scrollShink to true
pageScope.$apply('shouldShrink = true');
expect(element.find('md-content').attr('scroll-shrink')).toEqual('true');
});

function build(template) {
inject(function($compile) {
pageScope = $rootScope.$new();
element = $compile(template)(pageScope);
controller = element.controller('mdToolbar');

pageScope.$apply();
$timeout.flush();
});
}
});

0 comments on commit 9e5432e

Please sign in to comment.