123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /*!
- * Angular Material Design
- * https://github.com/angular/material
- * @license MIT
- * v0.11.4
- */
- goog.provide('ng.material.components.toolbar');
- goog.require('ng.material.components.content');
- goog.require('ng.material.core');
- /**
- * @ngdoc module
- * @name material.components.toolbar
- */
- angular.module('material.components.toolbar', [
- 'material.core',
- 'material.components.content'
- ])
- .directive('mdToolbar', mdToolbarDirective);
- /**
- * @ngdoc directive
- * @name mdToolbar
- * @module material.components.toolbar
- * @restrict E
- * @description
- * `md-toolbar` is used to place a toolbar in your app.
- *
- * Toolbars are usually used above a content area to display the title of the
- * current page, and show relevant action buttons for that page.
- *
- * You can change the height of the toolbar by adding either the
- * `md-medium-tall` or `md-tall` class to the toolbar.
- *
- * @usage
- * <hljs lang="html">
- * <div layout="column" layout-fill>
- * <md-toolbar>
- *
- * <div class="md-toolbar-tools">
- * <span>My App's Title</span>
- *
- * <!-- fill up the space between left and right area -->
- * <span flex></span>
- *
- * <md-button>
- * Right Bar Button
- * </md-button>
- * </div>
- *
- * </md-toolbar>
- * <md-content>
- * Hello!
- * </md-content>
- * </div>
- * </hljs>
- *
- * @param {boolean=} md-scroll-shrink Whether the header should shrink away as
- * the user scrolls down, and reveal itself as the user scrolls up.
- *
- * _**Note (1):** for scrollShrink to work, the toolbar must be a sibling of a
- * `md-content` element, placed before it. See the scroll shrink demo._
- *
- * _**Note (2):** The `md-scroll-shrink` attribute is only parsed on component
- * initialization, it does not watch for scope changes._
- *
- *
- * @param {number=} md-shrink-speed-factor How much to change the speed of the toolbar's
- * shrinking by. For example, if 0.25 is given then the toolbar will shrink
- * 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)');
- return {
- restrict: 'E',
- link: function(scope, element, attr) {
- $mdTheming(element);
- if (angular.isDefined(attr.mdScrollShrink)) {
- setupScrollShrink();
- }
- function setupScrollShrink() {
- var toolbarHeight;
- var contentElement;
- var disableScrollShrink = angular.noop;
- // Current "y" position of scroll
- // Store the last scroll top position
- var y = 0;
- var prevScrollTop = 0;
- var shrinkSpeedFactor = attr.mdShrinkSpeedFactor || 0.5;
- var debouncedContentScroll = $$rAF.throttle(onContentScroll);
- var debouncedUpdateHeight = $mdUtil.debounce(updateToolbarHeight, 5 * 1000);
- // Wait for $mdContentLoaded event from mdContent directive.
- // If the mdContent element is a sibling of our toolbar, hook it up
- // 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.
- attr.$observe('mdScrollShrink', onChangeScrollShrink);
- // If the scope is destroyed (which could happen with ng-if), make sure
- // to disable scroll shrinking again
- scope.$on('$destroy', disableScrollShrink);
- /**
- *
- */
- function onChangeScrollShrink(shrinkWithScroll) {
- 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);
- }
- // Evaluate the expression
- shrinkWithScroll = scope.$eval(shrinkWithScroll);
- // Disable only if the attribute's expression evaluates to false
- if (shrinkWithScroll === false) {
- disableScrollShrink();
- } else {
- disableScrollShrink = enableScrollShrink();
- }
- }
- /**
- *
- */
- function onMdContentLoad($event, newContentEl) {
- // Toolbar and content must be siblings
- if (newContentEl && element.parent()[0] === newContentEl.parent()[0]) {
- // unhook old content event listener if exists
- if (contentElement) {
- contentElement.off('scroll', debouncedContentScroll);
- }
- contentElement = newContentEl;
- disableScrollShrink = enableScrollShrink();
- }
- }
- /**
- *
- */
- function onContentScroll(e) {
- var scrollTop = e ? e.target.scrollTop : prevScrollTop;
- debouncedUpdateHeight();
- y = Math.min(
- toolbarHeight / shrinkSpeedFactor,
- Math.max(0, y + scrollTop - prevScrollTop)
- );
- element.css($mdConstant.CSS.TRANSFORM, translateY([-y * shrinkSpeedFactor]));
- contentElement.css($mdConstant.CSS.TRANSFORM, translateY([(toolbarHeight - y) * shrinkSpeedFactor]));
- prevScrollTop = scrollTop;
- $mdUtil.nextTick(function() {
- var hasWhiteFrame = element.hasClass('md-whiteframe-z1');
- if (hasWhiteFrame && !y) {
- $animate.removeClass(element, 'md-whiteframe-z1');
- } else if (!hasWhiteFrame && y) {
- $animate.addClass(element, 'md-whiteframe-z1');
- }
- });
- }
- /**
- *
- */
- function enableScrollShrink() {
- if (!contentElement) return angular.noop; // no md-content
- contentElement.on('scroll', debouncedContentScroll);
- contentElement.attr('scroll-shrink', 'true');
- $$rAF(updateToolbarHeight);
- return function disableScrollShrink() {
- contentElement.off('scroll', debouncedContentScroll);
- contentElement.attr('scroll-shrink', 'false');
- $$rAF(updateToolbarHeight);
- }
- }
- /**
- *
- */
- function updateToolbarHeight() {
- toolbarHeight = element.prop('offsetHeight');
- // Add a negative margin-top the size of the toolbar to the content el.
- // The content will start transformed down the toolbarHeight amount,
- // so everything looks normal.
- //
- // 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';
- contentElement.css({
- "margin-top": margin,
- "margin-bottom": margin
- });
- onContentScroll();
- }
- }
- }
- };
- }
- mdToolbarDirective.$inject = ["$$rAF", "$mdConstant", "$mdUtil", "$mdTheming", "$animate"];
- ng.material.components.toolbar = angular.module("material.components.toolbar");
|