2 * Angular Material Design
3 * https://github.com/angular/material
7 (function( window, angular, undefined ){
15 * @name material.components.fabToolbar
19 .module('material.components.fabToolbar', [
21 'material.components.fabShared',
22 'material.components.fabActions'
25 // Register our directive
26 .directive('mdFabToolbar', MdFabToolbarDirective)
28 // Register our custom animations
29 .animation('.md-fab-toolbar', MdFabToolbarAnimation)
31 // Register a service for the animation so that we can easily inject it into unit tests
32 .service('mdFabToolbarAnimation', MdFabToolbarAnimation);
37 * @module material.components.fabToolbar
43 * The `<md-fab-toolbar>` directive is used to present a toolbar of elements (usually `<md-button>`s)
44 * for quick access to common actions when a floating action button is activated (via click or
45 * keyboard navigation).
47 * You may also easily position the trigger by applying one one of the following classes to the
48 * `<md-fab-toolbar>` element:
50 * - `md-fab-top-right`
51 * - `md-fab-bottom-left`
52 * - `md-fab-bottom-right`
54 * These CSS classes use `position: absolute`, so you need to ensure that the container element
55 * also uses `position: absolute` or `position: relative` in order for them to work.
60 * <md-fab-toolbar md-direction='left'>
62 * <md-button aria-label="Add..."><md-icon md-svg-src="/img/icons/plus.svg"></md-icon></md-button>
67 * <md-button aria-label="Add User">
68 * <md-icon md-svg-src="/img/icons/user.svg"></md-icon>
71 * <md-button aria-label="Add Group">
72 * <md-icon md-svg-src="/img/icons/group.svg"></md-icon>
79 * @param {string} md-direction From which direction you would like the toolbar items to appear
80 * relative to the trigger element. Supports `left` and `right` directions.
81 * @param {expression=} md-open Programmatically control whether or not the toolbar is visible.
83 function MdFabToolbarDirective() {
87 template: '<div class="md-fab-toolbar-wrapper">' +
88 ' <div class="md-fab-toolbar-content" ng-transclude></div>' +
92 direction: '@?mdDirection',
96 bindToController: true,
97 controller: 'MdFabController',
103 function link(scope, element, attributes) {
104 // Add the base class for animations
105 element.addClass('md-fab-toolbar');
107 // Prepend the background element to the trigger's button
108 element.find('md-fab-trigger').find('button')
109 .prepend('<div class="md-fab-toolbar-background"></div>');
113 function MdFabToolbarAnimation() {
115 function runAnimation(element, className, done) {
116 // If no className was specified, don't do anything
122 var ctrl = element.controller('mdFabToolbar');
124 // Grab the relevant child elements
125 var backgroundElement = el.querySelector('.md-fab-toolbar-background');
126 var triggerElement = el.querySelector('md-fab-trigger button');
127 var toolbarElement = el.querySelector('md-toolbar');
128 var iconElement = el.querySelector('md-fab-trigger button md-icon');
129 var actions = element.find('md-fab-actions').children();
131 // If we have both elements, use them to position the new background
132 if (triggerElement && backgroundElement) {
134 var color = window.getComputedStyle(triggerElement).getPropertyValue('background-color');
135 var width = el.offsetWidth;
136 var height = el.offsetHeight;
138 // Make it twice as big as it should be since we scale from the center
139 var scale = 2 * (width / triggerElement.offsetWidth);
141 // Set some basic styles no matter what animation we're doing
142 backgroundElement.style.backgroundColor = color;
143 backgroundElement.style.borderRadius = width + 'px';
147 // Turn on toolbar pointer events when closed
148 toolbarElement.style.pointerEvents = 'inherit';
150 backgroundElement.style.width = triggerElement.offsetWidth + 'px';
151 backgroundElement.style.height = triggerElement.offsetHeight + 'px';
152 backgroundElement.style.transform = 'scale(' + scale + ')';
154 // Set the next close animation to have the proper delays
155 backgroundElement.style.transitionDelay = '0ms';
156 iconElement && (iconElement.style.transitionDelay = '.3s');
158 // Apply a transition delay to actions
159 angular.forEach(actions, function(action, index) {
160 action.style.transitionDelay = (actions.length - index) * 25 + 'ms';
163 // Turn off toolbar pointer events when closed
164 toolbarElement.style.pointerEvents = 'none';
166 // Scale it back down to the trigger's size
167 backgroundElement.style.transform = 'scale(1)';
169 // Reset the position
170 backgroundElement.style.top = '0';
172 if (element.hasClass('md-right')) {
173 backgroundElement.style.left = '0';
174 backgroundElement.style.right = null;
177 if (element.hasClass('md-left')) {
178 backgroundElement.style.right = '0';
179 backgroundElement.style.left = null;
182 // Set the next open animation to have the proper delays
183 backgroundElement.style.transitionDelay = '200ms';
184 iconElement && (iconElement.style.transitionDelay = '0ms');
186 // Apply a transition delay to actions
187 angular.forEach(actions, function(action, index) {
188 action.style.transitionDelay = 200 + (index * 25) + 'ms';
195 addClass: function(element, className, done) {
196 runAnimation(element, className, done);
200 removeClass: function(element, className, done) {
201 runAnimation(element, className, done);
208 })(window, window.angular);