material_design_lite-sass 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +108 -0
- data/Rakefile +4 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/material_design_lite-sass.rb +46 -0
- data/lib/material_design_lite/sass/engine.rb +13 -0
- data/lib/material_design_lite/sass/version.rb +5 -0
- data/material_design_lite-sass.gemspec +28 -0
- data/vendor/assets/javascripts/material.js +3919 -0
- data/vendor/assets/javascripts/material/button.js +132 -0
- data/vendor/assets/javascripts/material/checkbox.js +265 -0
- data/vendor/assets/javascripts/material/data-table.js +149 -0
- data/vendor/assets/javascripts/material/icon-toggle.js +248 -0
- data/vendor/assets/javascripts/material/layout.js +434 -0
- data/vendor/assets/javascripts/material/mdlComponentHandler.js +346 -0
- data/vendor/assets/javascripts/material/menu.js +468 -0
- data/vendor/assets/javascripts/material/progress.js +116 -0
- data/vendor/assets/javascripts/material/rAF.js +38 -0
- data/vendor/assets/javascripts/material/radio.js +257 -0
- data/vendor/assets/javascripts/material/ripple.js +244 -0
- data/vendor/assets/javascripts/material/slider.js +252 -0
- data/vendor/assets/javascripts/material/spinner.js +140 -0
- data/vendor/assets/javascripts/material/switch.js +269 -0
- data/vendor/assets/javascripts/material/tabs.js +152 -0
- data/vendor/assets/javascripts/material/textfield.js +247 -0
- data/vendor/assets/javascripts/material/tooltip.js +146 -0
- data/vendor/assets/stylesheets/_material.scss +50 -0
- data/vendor/assets/stylesheets/material/_animation.scss +34 -0
- data/vendor/assets/stylesheets/material/_badge.scss +66 -0
- data/vendor/assets/stylesheets/material/_button.scss +298 -0
- data/vendor/assets/stylesheets/material/_card.scss +111 -0
- data/vendor/assets/stylesheets/material/_checkbox.scss +175 -0
- data/vendor/assets/stylesheets/material/_color-definitions.scss +599 -0
- data/vendor/assets/stylesheets/material/_data-table.scss +105 -0
- data/vendor/assets/stylesheets/material/_functions.scss +3 -0
- data/vendor/assets/stylesheets/material/_grid.scss +180 -0
- data/vendor/assets/stylesheets/material/_icon-toggle.scss +121 -0
- data/vendor/assets/stylesheets/material/_layout.scss +580 -0
- data/vendor/assets/stylesheets/material/_mega_footer.scss +309 -0
- data/vendor/assets/stylesheets/material/_menu.scss +193 -0
- data/vendor/assets/stylesheets/material/_mini_footer.scss +88 -0
- data/vendor/assets/stylesheets/material/_mixins.scss +268 -0
- data/vendor/assets/stylesheets/material/_palette.scss +2303 -0
- data/vendor/assets/stylesheets/material/_progress.scss +115 -0
- data/vendor/assets/stylesheets/material/_radio.scss +155 -0
- data/vendor/assets/stylesheets/material/_resets.scss +55 -0
- data/vendor/assets/stylesheets/material/_ripple.scss +42 -0
- data/vendor/assets/stylesheets/material/_shadow.scss +42 -0
- data/vendor/assets/stylesheets/material/_slider.scss +396 -0
- data/vendor/assets/stylesheets/material/_spinner.scss +248 -0
- data/vendor/assets/stylesheets/material/_switch.scss +199 -0
- data/vendor/assets/stylesheets/material/_tabs.scss +115 -0
- data/vendor/assets/stylesheets/material/_textfield.scss +190 -0
- data/vendor/assets/stylesheets/material/_tooltip.scss +66 -0
- data/vendor/assets/stylesheets/material/_typography.scss +297 -0
- data/vendor/assets/stylesheets/material/_variables.scss +572 -0
- data/vendor/assets/stylesheets/material/resets/_h5bp.scss +284 -0
- data/vendor/assets/stylesheets/material/resets/_mobile.scss +25 -0
- metadata +151 -0
@@ -0,0 +1,248 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2015 Google Inc. All Rights Reserved.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Class constructor for icon toggle MDL component.
|
20
|
+
* Implements MDL component design pattern defined at:
|
21
|
+
* https://github.com/jasonmayes/mdl-component-design-pattern
|
22
|
+
* @param {HTMLElement} element The element that will be upgraded.
|
23
|
+
*/
|
24
|
+
function MaterialIconToggle(element) {
|
25
|
+
'use strict';
|
26
|
+
|
27
|
+
this.element_ = element;
|
28
|
+
|
29
|
+
// Initialize instance.
|
30
|
+
this.init();
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Store constants in one place so they can be updated easily.
|
35
|
+
* @enum {string | number}
|
36
|
+
* @private
|
37
|
+
*/
|
38
|
+
MaterialIconToggle.prototype.Constant_ = {
|
39
|
+
TINY_TIMEOUT: 0.001
|
40
|
+
};
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Store strings for class names defined by this component that are used in
|
44
|
+
* JavaScript. This allows us to simply change it in one place should we
|
45
|
+
* decide to modify at a later date.
|
46
|
+
* @enum {string}
|
47
|
+
* @private
|
48
|
+
*/
|
49
|
+
MaterialIconToggle.prototype.CssClasses_ = {
|
50
|
+
INPUT: 'mdl-icon-toggle__input',
|
51
|
+
JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
52
|
+
RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
53
|
+
RIPPLE_CONTAINER: 'mdl-icon-toggle__ripple-container',
|
54
|
+
RIPPLE_CENTER: 'mdl-ripple--center',
|
55
|
+
RIPPLE: 'mdl-ripple',
|
56
|
+
IS_FOCUSED: 'is-focused',
|
57
|
+
IS_DISABLED: 'is-disabled',
|
58
|
+
IS_CHECKED: 'is-checked'
|
59
|
+
};
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Handle change of state.
|
63
|
+
* @param {Event} event The event that fired.
|
64
|
+
* @private
|
65
|
+
*/
|
66
|
+
MaterialIconToggle.prototype.onChange_ = function(event) {
|
67
|
+
'use strict';
|
68
|
+
|
69
|
+
this.updateClasses_();
|
70
|
+
};
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Handle focus of element.
|
74
|
+
* @param {Event} event The event that fired.
|
75
|
+
* @private
|
76
|
+
*/
|
77
|
+
MaterialIconToggle.prototype.onFocus_ = function(event) {
|
78
|
+
'use strict';
|
79
|
+
|
80
|
+
this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
81
|
+
};
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Handle lost focus of element.
|
85
|
+
* @param {Event} event The event that fired.
|
86
|
+
* @private
|
87
|
+
*/
|
88
|
+
MaterialIconToggle.prototype.onBlur_ = function(event) {
|
89
|
+
'use strict';
|
90
|
+
|
91
|
+
this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
92
|
+
};
|
93
|
+
|
94
|
+
/**
|
95
|
+
* Handle mouseup.
|
96
|
+
* @param {Event} event The event that fired.
|
97
|
+
* @private
|
98
|
+
*/
|
99
|
+
MaterialIconToggle.prototype.onMouseUp_ = function(event) {
|
100
|
+
'use strict';
|
101
|
+
|
102
|
+
this.blur_();
|
103
|
+
};
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Handle class updates.
|
107
|
+
* @param {HTMLElement} button The button whose classes we should update.
|
108
|
+
* @param {HTMLElement} label The label whose classes we should update.
|
109
|
+
* @private
|
110
|
+
*/
|
111
|
+
MaterialIconToggle.prototype.updateClasses_ = function() {
|
112
|
+
'use strict';
|
113
|
+
|
114
|
+
if (this.inputElement_.disabled) {
|
115
|
+
this.element_.classList.add(this.CssClasses_.IS_DISABLED);
|
116
|
+
} else {
|
117
|
+
this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
|
118
|
+
}
|
119
|
+
|
120
|
+
if (this.inputElement_.checked) {
|
121
|
+
this.element_.classList.add(this.CssClasses_.IS_CHECKED);
|
122
|
+
} else {
|
123
|
+
this.element_.classList.remove(this.CssClasses_.IS_CHECKED);
|
124
|
+
}
|
125
|
+
};
|
126
|
+
|
127
|
+
/**
|
128
|
+
* Add blur.
|
129
|
+
* @private
|
130
|
+
*/
|
131
|
+
MaterialIconToggle.prototype.blur_ = function(event) {
|
132
|
+
'use strict';
|
133
|
+
|
134
|
+
// TODO: figure out why there's a focus event being fired after our blur,
|
135
|
+
// so that we can avoid this hack.
|
136
|
+
window.setTimeout(function() {
|
137
|
+
this.inputElement_.blur();
|
138
|
+
}.bind(this), this.Constant_.TINY_TIMEOUT);
|
139
|
+
};
|
140
|
+
|
141
|
+
// Public methods.
|
142
|
+
|
143
|
+
/**
|
144
|
+
* Disable icon toggle.
|
145
|
+
* @public
|
146
|
+
*/
|
147
|
+
MaterialIconToggle.prototype.disable = function() {
|
148
|
+
'use strict';
|
149
|
+
|
150
|
+
this.inputElement_.disabled = true;
|
151
|
+
this.updateClasses_();
|
152
|
+
};
|
153
|
+
|
154
|
+
/**
|
155
|
+
* Enable icon toggle.
|
156
|
+
* @public
|
157
|
+
*/
|
158
|
+
MaterialIconToggle.prototype.enable = function() {
|
159
|
+
'use strict';
|
160
|
+
|
161
|
+
this.inputElement_.disabled = false;
|
162
|
+
this.updateClasses_();
|
163
|
+
};
|
164
|
+
|
165
|
+
/**
|
166
|
+
* Check icon toggle.
|
167
|
+
* @public
|
168
|
+
*/
|
169
|
+
MaterialIconToggle.prototype.check = function() {
|
170
|
+
'use strict';
|
171
|
+
|
172
|
+
this.inputElement_.checked = true;
|
173
|
+
this.updateClasses_();
|
174
|
+
};
|
175
|
+
|
176
|
+
/**
|
177
|
+
* Uncheck icon toggle.
|
178
|
+
* @public
|
179
|
+
*/
|
180
|
+
MaterialIconToggle.prototype.uncheck = function() {
|
181
|
+
'use strict';
|
182
|
+
|
183
|
+
this.inputElement_.checked = false;
|
184
|
+
this.updateClasses_();
|
185
|
+
};
|
186
|
+
|
187
|
+
/**
|
188
|
+
* Initialize element.
|
189
|
+
*/
|
190
|
+
MaterialIconToggle.prototype.init = function() {
|
191
|
+
'use strict';
|
192
|
+
|
193
|
+
if (this.element_) {
|
194
|
+
this.inputElement_ =
|
195
|
+
this.element_.querySelector('.' + this.CssClasses_.INPUT);
|
196
|
+
|
197
|
+
if (this.element_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) {
|
198
|
+
this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
199
|
+
this.rippleContainerElement_ = document.createElement('span');
|
200
|
+
this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER);
|
201
|
+
this.rippleContainerElement_.classList.add(this.CssClasses_.JS_RIPPLE_EFFECT);
|
202
|
+
this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER);
|
203
|
+
this.boundRippleMouseUp = this.onMouseUp_.bind(this);
|
204
|
+
this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp);
|
205
|
+
|
206
|
+
var ripple = document.createElement('span');
|
207
|
+
ripple.classList.add(this.CssClasses_.RIPPLE);
|
208
|
+
|
209
|
+
this.rippleContainerElement_.appendChild(ripple);
|
210
|
+
this.element_.appendChild(this.rippleContainerElement_);
|
211
|
+
}
|
212
|
+
|
213
|
+
this.boundInputOnChange = this.onChange_.bind(this);
|
214
|
+
this.boundInputOnFocus = this.onFocus_.bind(this);
|
215
|
+
this.boundInputOnBlur = this.onBlur_.bind(this);
|
216
|
+
this.boundElementOnMouseUp = this.onMouseUp_.bind(this);
|
217
|
+
this.inputElement_.addEventListener('change', this.boundInputOnChange);
|
218
|
+
this.inputElement_.addEventListener('focus', this.boundInputOnFocus);
|
219
|
+
this.inputElement_.addEventListener('blur', this.boundInputOnBlur);
|
220
|
+
this.element_.addEventListener('mouseup', this.boundElementOnMouseUp);
|
221
|
+
|
222
|
+
this.updateClasses_();
|
223
|
+
this.element_.classList.add('is-upgraded');
|
224
|
+
}
|
225
|
+
};
|
226
|
+
|
227
|
+
/*
|
228
|
+
* Downgrade the component
|
229
|
+
*/
|
230
|
+
MaterialIconToggle.prototype.mdlDowngrade_ = function() {
|
231
|
+
'use strict';
|
232
|
+
if (this.rippleContainerElement_) {
|
233
|
+
this.rippleContainerElement_.removeEventListener('mouseup', this.boundRippleMouseUp);
|
234
|
+
}
|
235
|
+
this.inputElement_.removeEventListener('change', this.boundInputOnChange);
|
236
|
+
this.inputElement_.removeEventListener('focus', this.boundInputOnFocus);
|
237
|
+
this.inputElement_.removeEventListener('blur', this.boundInputOnBlur);
|
238
|
+
this.element_.removeEventListener('mouseup', this.boundElementOnMouseUp);
|
239
|
+
};
|
240
|
+
|
241
|
+
// The component registers itself. It can assume componentHandler is available
|
242
|
+
// in the global scope.
|
243
|
+
componentHandler.register({
|
244
|
+
constructor: MaterialIconToggle,
|
245
|
+
classAsString: 'MaterialIconToggle',
|
246
|
+
cssClass: 'mdl-js-icon-toggle',
|
247
|
+
widget: true
|
248
|
+
});
|
@@ -0,0 +1,434 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2015 Google Inc. All Rights Reserved.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Class constructor for Layout MDL component.
|
20
|
+
* Implements MDL component design pattern defined at:
|
21
|
+
* https://github.com/jasonmayes/mdl-component-design-pattern
|
22
|
+
* @param {HTMLElement} element The element that will be upgraded.
|
23
|
+
*/
|
24
|
+
function MaterialLayout(element) {
|
25
|
+
'use strict';
|
26
|
+
|
27
|
+
this.element_ = element;
|
28
|
+
|
29
|
+
// Initialize instance.
|
30
|
+
this.init();
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Store constants in one place so they can be updated easily.
|
35
|
+
* @enum {string | number}
|
36
|
+
* @private
|
37
|
+
*/
|
38
|
+
MaterialLayout.prototype.Constant_ = {
|
39
|
+
MAX_WIDTH: '(max-width: 850px)',
|
40
|
+
TAB_SCROLL_PIXELS: 100,
|
41
|
+
|
42
|
+
MENU_ICON: 'menu',
|
43
|
+
CHEVRON_LEFT: 'chevron_left',
|
44
|
+
CHEVRON_RIGHT: 'chevron_right'
|
45
|
+
};
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Modes.
|
49
|
+
* @enum {number}
|
50
|
+
* @private
|
51
|
+
*/
|
52
|
+
MaterialLayout.prototype.Mode_ = {
|
53
|
+
STANDARD: 0,
|
54
|
+
SEAMED: 1,
|
55
|
+
WATERFALL: 2,
|
56
|
+
SCROLL: 3
|
57
|
+
};
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Store strings for class names defined by this component that are used in
|
61
|
+
* JavaScript. This allows us to simply change it in one place should we
|
62
|
+
* decide to modify at a later date.
|
63
|
+
* @enum {string}
|
64
|
+
* @private
|
65
|
+
*/
|
66
|
+
MaterialLayout.prototype.CssClasses_ = {
|
67
|
+
CONTAINER: 'mdl-layout__container',
|
68
|
+
HEADER: 'mdl-layout__header',
|
69
|
+
DRAWER: 'mdl-layout__drawer',
|
70
|
+
CONTENT: 'mdl-layout__content',
|
71
|
+
DRAWER_BTN: 'mdl-layout__drawer-button',
|
72
|
+
|
73
|
+
ICON: 'material-icons',
|
74
|
+
|
75
|
+
JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
76
|
+
RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container',
|
77
|
+
RIPPLE: 'mdl-ripple',
|
78
|
+
RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
79
|
+
|
80
|
+
HEADER_SEAMED: 'mdl-layout__header--seamed',
|
81
|
+
HEADER_WATERFALL: 'mdl-layout__header--waterfall',
|
82
|
+
HEADER_SCROLL: 'mdl-layout__header--scroll',
|
83
|
+
|
84
|
+
FIXED_HEADER: 'mdl-layout--fixed-header',
|
85
|
+
OBFUSCATOR: 'mdl-layout__obfuscator',
|
86
|
+
|
87
|
+
TAB_BAR: 'mdl-layout__tab-bar',
|
88
|
+
TAB_CONTAINER: 'mdl-layout__tab-bar-container',
|
89
|
+
TAB: 'mdl-layout__tab',
|
90
|
+
TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button',
|
91
|
+
TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button',
|
92
|
+
TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button',
|
93
|
+
PANEL: 'mdl-layout__tab-panel',
|
94
|
+
|
95
|
+
HAS_DRAWER: 'has-drawer',
|
96
|
+
HAS_TABS: 'has-tabs',
|
97
|
+
HAS_SCROLLING_HEADER: 'has-scrolling-header',
|
98
|
+
CASTING_SHADOW: 'is-casting-shadow',
|
99
|
+
IS_COMPACT: 'is-compact',
|
100
|
+
IS_SMALL_SCREEN: 'is-small-screen',
|
101
|
+
IS_DRAWER_OPEN: 'is-visible',
|
102
|
+
IS_ACTIVE: 'is-active',
|
103
|
+
IS_UPGRADED: 'is-upgraded',
|
104
|
+
IS_ANIMATING: 'is-animating',
|
105
|
+
|
106
|
+
ON_LARGE_SCREEN : 'mdl-layout--large-screen-only',
|
107
|
+
ON_SMALL_SCREEN : 'mdl-layout--small-screen-only'
|
108
|
+
|
109
|
+
};
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Handles scrolling on the content.
|
113
|
+
* @private
|
114
|
+
*/
|
115
|
+
MaterialLayout.prototype.contentScrollHandler_ = function() {
|
116
|
+
'use strict';
|
117
|
+
|
118
|
+
if (this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)) {
|
119
|
+
return;
|
120
|
+
}
|
121
|
+
|
122
|
+
if (this.content_.scrollTop > 0 &&
|
123
|
+
!this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
|
124
|
+
this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
|
125
|
+
this.header_.classList.add(this.CssClasses_.IS_COMPACT);
|
126
|
+
this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
|
127
|
+
} else if (this.content_.scrollTop <= 0 &&
|
128
|
+
this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
|
129
|
+
this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
|
130
|
+
this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
|
131
|
+
this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
|
132
|
+
}
|
133
|
+
};
|
134
|
+
|
135
|
+
/**
|
136
|
+
* Handles changes in screen size.
|
137
|
+
* @private
|
138
|
+
*/
|
139
|
+
MaterialLayout.prototype.screenSizeHandler_ = function() {
|
140
|
+
'use strict';
|
141
|
+
|
142
|
+
if (this.screenSizeMediaQuery_.matches) {
|
143
|
+
this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN);
|
144
|
+
} else {
|
145
|
+
this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN);
|
146
|
+
// Collapse drawer (if any) when moving to a large screen size.
|
147
|
+
if (this.drawer_) {
|
148
|
+
this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
};
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Handles toggling of the drawer.
|
155
|
+
* @param {Element} drawer The drawer container element.
|
156
|
+
* @private
|
157
|
+
*/
|
158
|
+
MaterialLayout.prototype.drawerToggleHandler_ = function() {
|
159
|
+
'use strict';
|
160
|
+
|
161
|
+
this.drawer_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN);
|
162
|
+
};
|
163
|
+
|
164
|
+
/**
|
165
|
+
* Handles (un)setting the `is-animating` class
|
166
|
+
*/
|
167
|
+
MaterialLayout.prototype.headerTransitionEndHandler = function() {
|
168
|
+
'use strict';
|
169
|
+
|
170
|
+
this.header_.classList.remove(this.CssClasses_.IS_ANIMATING);
|
171
|
+
};
|
172
|
+
|
173
|
+
/**
|
174
|
+
* Handles expanding the header on click
|
175
|
+
*/
|
176
|
+
MaterialLayout.prototype.headerClickHandler = function() {
|
177
|
+
'use strict';
|
178
|
+
|
179
|
+
if (this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
|
180
|
+
this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
|
181
|
+
this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
|
182
|
+
}
|
183
|
+
};
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Reset tab state, dropping active classes
|
187
|
+
* @private
|
188
|
+
*/
|
189
|
+
MaterialLayout.prototype.resetTabState_ = function(tabBar) {
|
190
|
+
'use strict';
|
191
|
+
|
192
|
+
for (var k = 0; k < tabBar.length; k++) {
|
193
|
+
tabBar[k].classList.remove(this.CssClasses_.IS_ACTIVE);
|
194
|
+
}
|
195
|
+
};
|
196
|
+
|
197
|
+
/**
|
198
|
+
* Reset panel state, droping active classes
|
199
|
+
* @private
|
200
|
+
*/
|
201
|
+
MaterialLayout.prototype.resetPanelState_ = function(panels) {
|
202
|
+
'use strict';
|
203
|
+
|
204
|
+
for (var j = 0; j < panels.length; j++) {
|
205
|
+
panels[j].classList.remove(this.CssClasses_.IS_ACTIVE);
|
206
|
+
}
|
207
|
+
};
|
208
|
+
|
209
|
+
/**
|
210
|
+
* Initialize element.
|
211
|
+
*/
|
212
|
+
MaterialLayout.prototype.init = function() {
|
213
|
+
'use strict';
|
214
|
+
|
215
|
+
if (this.element_) {
|
216
|
+
var container = document.createElement('div');
|
217
|
+
container.classList.add(this.CssClasses_.CONTAINER);
|
218
|
+
this.element_.parentElement.insertBefore(container, this.element_);
|
219
|
+
this.element_.parentElement.removeChild(this.element_);
|
220
|
+
container.appendChild(this.element_);
|
221
|
+
|
222
|
+
var directChildren = this.element_.childNodes;
|
223
|
+
for (var c = 0; c < directChildren.length; c++) {
|
224
|
+
var child = directChildren[c];
|
225
|
+
if (child.classList &&
|
226
|
+
child.classList.contains(this.CssClasses_.HEADER)) {
|
227
|
+
this.header_ = child;
|
228
|
+
}
|
229
|
+
|
230
|
+
if (child.classList &&
|
231
|
+
child.classList.contains(this.CssClasses_.DRAWER)) {
|
232
|
+
this.drawer_ = child;
|
233
|
+
}
|
234
|
+
|
235
|
+
if (child.classList &&
|
236
|
+
child.classList.contains(this.CssClasses_.CONTENT)) {
|
237
|
+
this.content_ = child;
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
if (this.header_) {
|
242
|
+
this.tabBar_ = this.header_.querySelector('.' + this.CssClasses_.TAB_BAR);
|
243
|
+
}
|
244
|
+
|
245
|
+
var mode = this.Mode_.STANDARD;
|
246
|
+
|
247
|
+
// Keep an eye on screen size, and add/remove auxiliary class for styling
|
248
|
+
// of small screens.
|
249
|
+
this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH);
|
250
|
+
this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this));
|
251
|
+
this.screenSizeHandler_();
|
252
|
+
|
253
|
+
if (this.header_) {
|
254
|
+
if (this.header_.classList.contains(this.CssClasses_.HEADER_SEAMED)) {
|
255
|
+
mode = this.Mode_.SEAMED;
|
256
|
+
} else if (this.header_.classList.contains(
|
257
|
+
this.CssClasses_.HEADER_WATERFALL)) {
|
258
|
+
mode = this.Mode_.WATERFALL;
|
259
|
+
this.header_.addEventListener('transitionend',
|
260
|
+
this.headerTransitionEndHandler.bind(this));
|
261
|
+
this.header_.addEventListener('click',
|
262
|
+
this.headerClickHandler.bind(this));
|
263
|
+
} else if (this.header_.classList.contains(
|
264
|
+
this.CssClasses_.HEADER_SCROLL)) {
|
265
|
+
mode = this.Mode_.SCROLL;
|
266
|
+
container.classList.add(this.CssClasses_.HAS_SCROLLING_HEADER);
|
267
|
+
}
|
268
|
+
|
269
|
+
if (mode === this.Mode_.STANDARD) {
|
270
|
+
this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
|
271
|
+
if (this.tabBar_) {
|
272
|
+
this.tabBar_.classList.add(this.CssClasses_.CASTING_SHADOW);
|
273
|
+
}
|
274
|
+
} else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) {
|
275
|
+
this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
|
276
|
+
if (this.tabBar_) {
|
277
|
+
this.tabBar_.classList.remove(this.CssClasses_.CASTING_SHADOW);
|
278
|
+
}
|
279
|
+
} else if (mode === this.Mode_.WATERFALL) {
|
280
|
+
// Add and remove shadows depending on scroll position.
|
281
|
+
// Also add/remove auxiliary class for styling of the compact version of
|
282
|
+
// the header.
|
283
|
+
this.content_.addEventListener('scroll',
|
284
|
+
this.contentScrollHandler_.bind(this));
|
285
|
+
this.contentScrollHandler_();
|
286
|
+
}
|
287
|
+
}
|
288
|
+
|
289
|
+
// Add drawer toggling button to our layout, if we have an openable drawer.
|
290
|
+
if (this.drawer_) {
|
291
|
+
var drawerButton = document.createElement('div');
|
292
|
+
drawerButton.classList.add(this.CssClasses_.DRAWER_BTN);
|
293
|
+
|
294
|
+
if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) {
|
295
|
+
//If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well.
|
296
|
+
drawerButton.classList.add(this.CssClasses_.ON_LARGE_SCREEN);
|
297
|
+
} else if (this.drawer_.classList.contains(this.CssClasses_.ON_SMALL_SCREEN)) {
|
298
|
+
//If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well.
|
299
|
+
drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN);
|
300
|
+
}
|
301
|
+
var drawerButtonIcon = document.createElement('i');
|
302
|
+
drawerButtonIcon.classList.add(this.CssClasses_.ICON);
|
303
|
+
drawerButtonIcon.textContent = this.Constant_.MENU_ICON;
|
304
|
+
drawerButton.appendChild(drawerButtonIcon);
|
305
|
+
drawerButton.addEventListener('click',
|
306
|
+
this.drawerToggleHandler_.bind(this));
|
307
|
+
|
308
|
+
// Add a class if the layout has a drawer, for altering the left padding.
|
309
|
+
// Adds the HAS_DRAWER to the elements since this.header_ may or may
|
310
|
+
// not be present.
|
311
|
+
this.element_.classList.add(this.CssClasses_.HAS_DRAWER);
|
312
|
+
|
313
|
+
// If we have a fixed header, add the button to the header rather than
|
314
|
+
// the layout.
|
315
|
+
if (this.element_.classList.contains(this.CssClasses_.FIXED_HEADER)) {
|
316
|
+
this.header_.insertBefore(drawerButton, this.header_.firstChild);
|
317
|
+
} else {
|
318
|
+
this.element_.insertBefore(drawerButton, this.content_);
|
319
|
+
}
|
320
|
+
|
321
|
+
var obfuscator = document.createElement('div');
|
322
|
+
obfuscator.classList.add(this.CssClasses_.OBFUSCATOR);
|
323
|
+
this.element_.appendChild(obfuscator);
|
324
|
+
obfuscator.addEventListener('click',
|
325
|
+
this.drawerToggleHandler_.bind(this));
|
326
|
+
}
|
327
|
+
|
328
|
+
// Initialize tabs, if any.
|
329
|
+
if (this.header_ && this.tabBar_) {
|
330
|
+
this.element_.classList.add(this.CssClasses_.HAS_TABS);
|
331
|
+
|
332
|
+
var tabContainer = document.createElement('div');
|
333
|
+
tabContainer.classList.add(this.CssClasses_.TAB_CONTAINER);
|
334
|
+
this.header_.insertBefore(tabContainer, this.tabBar_);
|
335
|
+
this.header_.removeChild(this.tabBar_);
|
336
|
+
|
337
|
+
var leftButton = document.createElement('div');
|
338
|
+
leftButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
|
339
|
+
leftButton.classList.add(this.CssClasses_.TAB_BAR_LEFT_BUTTON);
|
340
|
+
var leftButtonIcon = document.createElement('i');
|
341
|
+
leftButtonIcon.classList.add(this.CssClasses_.ICON);
|
342
|
+
leftButtonIcon.textContent = this.Constant_.CHEVRON_LEFT;
|
343
|
+
leftButton.appendChild(leftButtonIcon);
|
344
|
+
leftButton.addEventListener('click', function() {
|
345
|
+
this.tabBar_.scrollLeft -= this.Constant_.TAB_SCROLL_PIXELS;
|
346
|
+
}.bind(this));
|
347
|
+
|
348
|
+
var rightButton = document.createElement('div');
|
349
|
+
rightButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
|
350
|
+
rightButton.classList.add(this.CssClasses_.TAB_BAR_RIGHT_BUTTON);
|
351
|
+
var rightButtonIcon = document.createElement('i');
|
352
|
+
rightButtonIcon.classList.add(this.CssClasses_.ICON);
|
353
|
+
rightButtonIcon.textContent = this.Constant_.CHEVRON_RIGHT;
|
354
|
+
rightButton.appendChild(rightButtonIcon);
|
355
|
+
rightButton.addEventListener('click', function() {
|
356
|
+
this.tabBar_.scrollLeft += this.Constant_.TAB_SCROLL_PIXELS;
|
357
|
+
}.bind(this));
|
358
|
+
|
359
|
+
tabContainer.appendChild(leftButton);
|
360
|
+
tabContainer.appendChild(this.tabBar_);
|
361
|
+
tabContainer.appendChild(rightButton);
|
362
|
+
|
363
|
+
// Add and remove buttons depending on scroll position.
|
364
|
+
var tabScrollHandler = function() {
|
365
|
+
if (this.tabBar_.scrollLeft > 0) {
|
366
|
+
leftButton.classList.add(this.CssClasses_.IS_ACTIVE);
|
367
|
+
} else {
|
368
|
+
leftButton.classList.remove(this.CssClasses_.IS_ACTIVE);
|
369
|
+
}
|
370
|
+
|
371
|
+
if (this.tabBar_.scrollLeft <
|
372
|
+
this.tabBar_.scrollWidth - this.tabBar_.offsetWidth) {
|
373
|
+
rightButton.classList.add(this.CssClasses_.IS_ACTIVE);
|
374
|
+
} else {
|
375
|
+
rightButton.classList.remove(this.CssClasses_.IS_ACTIVE);
|
376
|
+
}
|
377
|
+
}.bind(this);
|
378
|
+
|
379
|
+
this.tabBar_.addEventListener('scroll', tabScrollHandler);
|
380
|
+
tabScrollHandler();
|
381
|
+
|
382
|
+
if (this.tabBar_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) {
|
383
|
+
this.tabBar_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
384
|
+
}
|
385
|
+
|
386
|
+
// Select element tabs, document panels
|
387
|
+
var tabs = this.tabBar_.querySelectorAll('.' + this.CssClasses_.TAB);
|
388
|
+
var panels = this.content_.querySelectorAll('.' + this.CssClasses_.PANEL);
|
389
|
+
|
390
|
+
// Create new tabs for each tab element
|
391
|
+
for (var i = 0; i < tabs.length; i++) {
|
392
|
+
new MaterialLayoutTab(tabs[i], tabs, panels, this);
|
393
|
+
}
|
394
|
+
}
|
395
|
+
|
396
|
+
this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
|
397
|
+
}
|
398
|
+
};
|
399
|
+
|
400
|
+
function MaterialLayoutTab(tab, tabs, panels, layout) {
|
401
|
+
'use strict';
|
402
|
+
|
403
|
+
if (tab) {
|
404
|
+
if (layout.tabBar_.classList.contains(
|
405
|
+
layout.CssClasses_.JS_RIPPLE_EFFECT)) {
|
406
|
+
var rippleContainer = document.createElement('span');
|
407
|
+
rippleContainer.classList.add(layout.CssClasses_.RIPPLE_CONTAINER);
|
408
|
+
rippleContainer.classList.add(layout.CssClasses_.JS_RIPPLE_EFFECT);
|
409
|
+
var ripple = document.createElement('span');
|
410
|
+
ripple.classList.add(layout.CssClasses_.RIPPLE);
|
411
|
+
rippleContainer.appendChild(ripple);
|
412
|
+
tab.appendChild(rippleContainer);
|
413
|
+
}
|
414
|
+
|
415
|
+
tab.addEventListener('click', function(e) {
|
416
|
+
e.preventDefault();
|
417
|
+
var href = tab.href.split('#')[1];
|
418
|
+
var panel = layout.content_.querySelector('#' + href);
|
419
|
+
layout.resetTabState_(tabs);
|
420
|
+
layout.resetPanelState_(panels);
|
421
|
+
tab.classList.add(layout.CssClasses_.IS_ACTIVE);
|
422
|
+
panel.classList.add(layout.CssClasses_.IS_ACTIVE);
|
423
|
+
});
|
424
|
+
|
425
|
+
}
|
426
|
+
}
|
427
|
+
|
428
|
+
// The component registers itself. It can assume componentHandler is available
|
429
|
+
// in the global scope.
|
430
|
+
componentHandler.register({
|
431
|
+
constructor: MaterialLayout,
|
432
|
+
classAsString: 'MaterialLayout',
|
433
|
+
cssClass: 'mdl-js-layout'
|
434
|
+
});
|