/*! * Angular Material Design * https://github.com/angular/material * @license MIT * v1.1.1 */ (function( window, angular, undefined ){ "use strict"; (function() { 'use strict'; /** * @ngdoc module * @name material.components.fabToolbar */ angular // Declare our module .module('material.components.fabToolbar', [ 'material.core', 'material.components.fabShared', 'material.components.fabActions' ]) // Register our directive .directive('mdFabToolbar', MdFabToolbarDirective) // Register our custom animations .animation('.md-fab-toolbar', MdFabToolbarAnimation) // Register a service for the animation so that we can easily inject it into unit tests .service('mdFabToolbarAnimation', MdFabToolbarAnimation); /** * @ngdoc directive * @name mdFabToolbar * @module material.components.fabToolbar * * @restrict E * * @description * * The `` directive is used present a toolbar of elements (usually ``s) * for quick access to common actions when a floating action button is activated (via click or * keyboard navigation). * * You may also easily position the trigger by applying one one of the following classes to the * `` element: * - `md-fab-top-left` * - `md-fab-top-right` * - `md-fab-bottom-left` * - `md-fab-bottom-right` * * These CSS classes use `position: absolute`, so you need to ensure that the container element * also uses `position: absolute` or `position: relative` in order for them to work. * * @usage * * * * * * * * * * * * * * * * * * * * * * @param {string} md-direction From which direction you would like the toolbar items to appear * relative to the trigger element. Supports `left` and `right` directions. * @param {expression=} md-open Programmatically control whether or not the toolbar is visible. */ function MdFabToolbarDirective() { return { restrict: 'E', transclude: true, template: '
' + '
' + '
', scope: { direction: '@?mdDirection', isOpen: '=?mdOpen' }, bindToController: true, controller: 'MdFabController', controllerAs: 'vm', link: link }; function link(scope, element, attributes) { // Add the base class for animations element.addClass('md-fab-toolbar'); // Prepend the background element to the trigger's button element.find('md-fab-trigger').find('button') .prepend('
'); } } function MdFabToolbarAnimation() { function runAnimation(element, className, done) { // If no className was specified, don't do anything if (!className) { return; } var el = element[0]; var ctrl = element.controller('mdFabToolbar'); // Grab the relevant child elements var backgroundElement = el.querySelector('.md-fab-toolbar-background'); var triggerElement = el.querySelector('md-fab-trigger button'); var toolbarElement = el.querySelector('md-toolbar'); var iconElement = el.querySelector('md-fab-trigger button md-icon'); var actions = element.find('md-fab-actions').children(); // If we have both elements, use them to position the new background if (triggerElement && backgroundElement) { // Get our variables var color = window.getComputedStyle(triggerElement).getPropertyValue('background-color'); var width = el.offsetWidth; var height = el.offsetHeight; // Make it twice as big as it should be since we scale from the center var scale = 2 * (width / triggerElement.offsetWidth); // Set some basic styles no matter what animation we're doing backgroundElement.style.backgroundColor = color; backgroundElement.style.borderRadius = width + 'px'; // If we're open if (ctrl.isOpen) { // Turn on toolbar pointer events when closed toolbarElement.style.pointerEvents = 'inherit'; backgroundElement.style.width = triggerElement.offsetWidth + 'px'; backgroundElement.style.height = triggerElement.offsetHeight + 'px'; backgroundElement.style.transform = 'scale(' + scale + ')'; // Set the next close animation to have the proper delays backgroundElement.style.transitionDelay = '0ms'; iconElement && (iconElement.style.transitionDelay = '.3s'); // Apply a transition delay to actions angular.forEach(actions, function(action, index) { action.style.transitionDelay = (actions.length - index) * 25 + 'ms'; }); } else { // Turn off toolbar pointer events when closed toolbarElement.style.pointerEvents = 'none'; // Scale it back down to the trigger's size backgroundElement.style.transform = 'scale(1)'; // Reset the position backgroundElement.style.top = '0'; if (element.hasClass('md-right')) { backgroundElement.style.left = '0'; backgroundElement.style.right = null; } if (element.hasClass('md-left')) { backgroundElement.style.right = '0'; backgroundElement.style.left = null; } // Set the next open animation to have the proper delays backgroundElement.style.transitionDelay = '200ms'; iconElement && (iconElement.style.transitionDelay = '0ms'); // Apply a transition delay to actions angular.forEach(actions, function(action, index) { action.style.transitionDelay = 200 + (index * 25) + 'ms'; }); } } } return { addClass: function(element, className, done) { runAnimation(element, className, done); done(); }, removeClass: function(element, className, done) { runAnimation(element, className, done); done(); } } } })(); })(window, window.angular);