2 * Angular Material Design
3 * https://github.com/angular/material
7 goog.provide('ngmaterial.components.fabToolbar');
8 goog.require('ngmaterial.components.fabActions');
9 goog.require('ngmaterial.components.fabShared');
10 goog.require('ngmaterial.core');
16 * @name material.components.fabToolbar
20 .module('material.components.fabToolbar', [
22 'material.components.fabShared',
23 'material.components.fabActions'
26 // Register our directive
27 .directive('mdFabToolbar', MdFabToolbarDirective)
29 // Register our custom animations
30 .animation('.md-fab-toolbar', MdFabToolbarAnimation)
32 // Register a service for the animation so that we can easily inject it into unit tests
33 .service('mdFabToolbarAnimation', MdFabToolbarAnimation);
38 * @module material.components.fabToolbar
44 * The `<md-fab-toolbar>` directive is used to present a toolbar of elements (usually `<md-button>`s)
45 * for quick access to common actions when a floating action button is activated (via click or
46 * keyboard navigation).
48 * You may also easily position the trigger by applying one one of the following classes to the
49 * `<md-fab-toolbar>` element:
51 * - `md-fab-top-right`
52 * - `md-fab-bottom-left`
53 * - `md-fab-bottom-right`
55 * These CSS classes use `position: absolute`, so you need to ensure that the container element
56 * also uses `position: absolute` or `position: relative` in order for them to work.
61 * <md-fab-toolbar md-direction='left'>
63 * <md-button aria-label="Add..."><md-icon md-svg-src="/img/icons/plus.svg"></md-icon></md-button>
68 * <md-button aria-label="Add User">
69 * <md-icon md-svg-src="/img/icons/user.svg"></md-icon>
72 * <md-button aria-label="Add Group">
73 * <md-icon md-svg-src="/img/icons/group.svg"></md-icon>
80 * @param {string} md-direction From which direction you would like the toolbar items to appear
81 * relative to the trigger element. Supports `left` and `right` directions.
82 * @param {expression=} md-open Programmatically control whether or not the toolbar is visible.
84 function MdFabToolbarDirective() {
88 template: '<div class="md-fab-toolbar-wrapper">' +
89 ' <div class="md-fab-toolbar-content" ng-transclude></div>' +
93 direction: '@?mdDirection',
97 bindToController: true,
98 controller: 'MdFabController',
104 function link(scope, element, attributes) {
105 // Add the base class for animations
106 element.addClass('md-fab-toolbar');
108 // Prepend the background element to the trigger's button
109 element.find('md-fab-trigger').find('button')
110 .prepend('<div class="md-fab-toolbar-background"></div>');
114 function MdFabToolbarAnimation() {
116 function runAnimation(element, className, done) {
117 // If no className was specified, don't do anything
123 var ctrl = element.controller('mdFabToolbar');
125 // Grab the relevant child elements
126 var backgroundElement = el.querySelector('.md-fab-toolbar-background');
127 var triggerElement = el.querySelector('md-fab-trigger button');
128 var toolbarElement = el.querySelector('md-toolbar');
129 var iconElement = el.querySelector('md-fab-trigger button md-icon');
130 var actions = element.find('md-fab-actions').children();
132 // If we have both elements, use them to position the new background
133 if (triggerElement && backgroundElement) {
135 var color = window.getComputedStyle(triggerElement).getPropertyValue('background-color');
136 var width = el.offsetWidth;
137 var height = el.offsetHeight;
139 // Make it twice as big as it should be since we scale from the center
140 var scale = 2 * (width / triggerElement.offsetWidth);
142 // Set some basic styles no matter what animation we're doing
143 backgroundElement.style.backgroundColor = color;
144 backgroundElement.style.borderRadius = width + 'px';
148 // Turn on toolbar pointer events when closed
149 toolbarElement.style.pointerEvents = 'inherit';
151 backgroundElement.style.width = triggerElement.offsetWidth + 'px';
152 backgroundElement.style.height = triggerElement.offsetHeight + 'px';
153 backgroundElement.style.transform = 'scale(' + scale + ')';
155 // Set the next close animation to have the proper delays
156 backgroundElement.style.transitionDelay = '0ms';
157 iconElement && (iconElement.style.transitionDelay = '.3s');
159 // Apply a transition delay to actions
160 angular.forEach(actions, function(action, index) {
161 action.style.transitionDelay = (actions.length - index) * 25 + 'ms';
164 // Turn off toolbar pointer events when closed
165 toolbarElement.style.pointerEvents = 'none';
167 // Scale it back down to the trigger's size
168 backgroundElement.style.transform = 'scale(1)';
170 // Reset the position
171 backgroundElement.style.top = '0';
173 if (element.hasClass('md-right')) {
174 backgroundElement.style.left = '0';
175 backgroundElement.style.right = null;
178 if (element.hasClass('md-left')) {
179 backgroundElement.style.right = '0';
180 backgroundElement.style.left = null;
183 // Set the next open animation to have the proper delays
184 backgroundElement.style.transitionDelay = '200ms';
185 iconElement && (iconElement.style.transitionDelay = '0ms');
187 // Apply a transition delay to actions
188 angular.forEach(actions, function(action, index) {
189 action.style.transitionDelay = 200 + (index * 25) + 'ms';
196 addClass: function(element, className, done) {
197 runAnimation(element, className, done);
201 removeClass: function(element, className, done) {
202 runAnimation(element, className, done);
209 ngmaterial.components.fabToolbar = angular.module("material.components.fabToolbar");