1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
|
/**
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v1.1.3
*/
goog.provide('ngmaterial.components.fabToolbar');
goog.require('ngmaterial.components.fabActions');
goog.require('ngmaterial.components.fabShared');
goog.require('ngmaterial.core');
(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 `<md-fab-toolbar>` directive is used to present a toolbar of elements (usually `<md-button>`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
* `<md-fab-toolbar>` 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
*
* <hljs lang="html">
* <md-fab-toolbar md-direction='left'>
* <md-fab-trigger>
* <md-button aria-label="Add..."><md-icon md-svg-src="/img/icons/plus.svg"></md-icon></md-button>
* </md-fab-trigger>
*
* <md-toolbar>
* <md-fab-actions>
* <md-button aria-label="Add User">
* <md-icon md-svg-src="/img/icons/user.svg"></md-icon>
* </md-button>
*
* <md-button aria-label="Add Group">
* <md-icon md-svg-src="/img/icons/group.svg"></md-icon>
* </md-button>
* </md-fab-actions>
* </md-toolbar>
* </md-fab-toolbar>
* </hljs>
*
* @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: '<div class="md-fab-toolbar-wrapper">' +
' <div class="md-fab-toolbar-content" ng-transclude></div>' +
'</div>',
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('<div class="md-fab-toolbar-background"></div>');
}
}
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();
}
};
}
})();
ngmaterial.components.fabToolbar = angular.module("material.components.fabToolbar");
|