rev |
line source |
bsw/jbe@1309
|
1 ;(function() {
|
bsw/jbe@1309
|
2 "use strict";
|
bsw/jbe@1309
|
3
|
bsw/jbe@1309
|
4 /**
|
bsw/jbe@1309
|
5 * @license
|
bsw/jbe@1309
|
6 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
7 *
|
bsw/jbe@1309
|
8 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
9 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
10 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
11 *
|
bsw/jbe@1309
|
12 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
13 *
|
bsw/jbe@1309
|
14 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
15 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
17 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
18 * limitations under the License.
|
bsw/jbe@1309
|
19 */
|
bsw/jbe@1309
|
20
|
bsw/jbe@1309
|
21 /**
|
bsw/jbe@1309
|
22 * A component handler interface using the revealing module design pattern.
|
bsw/jbe@1309
|
23 * More details on this design pattern here:
|
bsw/jbe@1309
|
24 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
25 *
|
bsw/jbe@1309
|
26 * @author Jason Mayes.
|
bsw/jbe@1309
|
27 */
|
bsw/jbe@1309
|
28 /* exported componentHandler */
|
bsw/jbe@1309
|
29
|
bsw/jbe@1309
|
30 // Pre-defining the componentHandler interface, for closure documentation and
|
bsw/jbe@1309
|
31 // static verification.
|
bsw/jbe@1309
|
32 var componentHandler = {
|
bsw/jbe@1309
|
33 /**
|
bsw/jbe@1309
|
34 * Searches existing DOM for elements of our component type and upgrades them
|
bsw/jbe@1309
|
35 * if they have not already been upgraded.
|
bsw/jbe@1309
|
36 *
|
bsw/jbe@1309
|
37 * @param {string=} optJsClass the programatic name of the element class we
|
bsw/jbe@1309
|
38 * need to create a new instance of.
|
bsw/jbe@1309
|
39 * @param {string=} optCssClass the name of the CSS class elements of this
|
bsw/jbe@1309
|
40 * type will have.
|
bsw/jbe@1309
|
41 */
|
bsw/jbe@1309
|
42 upgradeDom: function(optJsClass, optCssClass) {},
|
bsw/jbe@1309
|
43 /**
|
bsw/jbe@1309
|
44 * Upgrades a specific element rather than all in the DOM.
|
bsw/jbe@1309
|
45 *
|
bsw/jbe@1309
|
46 * @param {!Element} element The element we wish to upgrade.
|
bsw/jbe@1309
|
47 * @param {string=} optJsClass Optional name of the class we want to upgrade
|
bsw/jbe@1309
|
48 * the element to.
|
bsw/jbe@1309
|
49 */
|
bsw/jbe@1309
|
50 upgradeElement: function(element, optJsClass) {},
|
bsw/jbe@1309
|
51 /**
|
bsw/jbe@1309
|
52 * Upgrades a specific list of elements rather than all in the DOM.
|
bsw/jbe@1309
|
53 *
|
bsw/jbe@1309
|
54 * @param {!Element|!Array<!Element>|!NodeList|!HTMLCollection} elements
|
bsw/jbe@1309
|
55 * The elements we wish to upgrade.
|
bsw/jbe@1309
|
56 */
|
bsw/jbe@1309
|
57 upgradeElements: function(elements) {},
|
bsw/jbe@1309
|
58 /**
|
bsw/jbe@1309
|
59 * Upgrades all registered components found in the current DOM. This is
|
bsw/jbe@1309
|
60 * automatically called on window load.
|
bsw/jbe@1309
|
61 */
|
bsw/jbe@1309
|
62 upgradeAllRegistered: function() {},
|
bsw/jbe@1309
|
63 /**
|
bsw/jbe@1309
|
64 * Allows user to be alerted to any upgrades that are performed for a given
|
bsw/jbe@1309
|
65 * component type
|
bsw/jbe@1309
|
66 *
|
bsw/jbe@1309
|
67 * @param {string} jsClass The class name of the MDL component we wish
|
bsw/jbe@1309
|
68 * to hook into for any upgrades performed.
|
bsw/jbe@1309
|
69 * @param {function(!HTMLElement)} callback The function to call upon an
|
bsw/jbe@1309
|
70 * upgrade. This function should expect 1 parameter - the HTMLElement which
|
bsw/jbe@1309
|
71 * got upgraded.
|
bsw/jbe@1309
|
72 */
|
bsw/jbe@1309
|
73 registerUpgradedCallback: function(jsClass, callback) {},
|
bsw/jbe@1309
|
74 /**
|
bsw/jbe@1309
|
75 * Registers a class for future use and attempts to upgrade existing DOM.
|
bsw/jbe@1309
|
76 *
|
bsw/jbe@1309
|
77 * @param {componentHandler.ComponentConfigPublic} config the registration configuration
|
bsw/jbe@1309
|
78 */
|
bsw/jbe@1309
|
79 register: function(config) {},
|
bsw/jbe@1309
|
80 /**
|
bsw/jbe@1309
|
81 * Downgrade either a given node, an array of nodes, or a NodeList.
|
bsw/jbe@1309
|
82 *
|
bsw/jbe@1309
|
83 * @param {!Node|!Array<!Node>|!NodeList} nodes
|
bsw/jbe@1309
|
84 */
|
bsw/jbe@1309
|
85 downgradeElements: function(nodes) {}
|
bsw/jbe@1309
|
86 };
|
bsw/jbe@1309
|
87
|
bsw/jbe@1309
|
88 componentHandler = (function() {
|
bsw/jbe@1309
|
89 'use strict';
|
bsw/jbe@1309
|
90
|
bsw/jbe@1309
|
91 /** @type {!Array<componentHandler.ComponentConfig>} */
|
bsw/jbe@1309
|
92 var registeredComponents_ = [];
|
bsw/jbe@1309
|
93
|
bsw/jbe@1309
|
94 /** @type {!Array<componentHandler.Component>} */
|
bsw/jbe@1309
|
95 var createdComponents_ = [];
|
bsw/jbe@1309
|
96
|
bsw/jbe@1309
|
97 var componentConfigProperty_ = 'mdlComponentConfigInternal_';
|
bsw/jbe@1309
|
98
|
bsw/jbe@1309
|
99 /**
|
bsw/jbe@1309
|
100 * Searches registered components for a class we are interested in using.
|
bsw/jbe@1309
|
101 * Optionally replaces a match with passed object if specified.
|
bsw/jbe@1309
|
102 *
|
bsw/jbe@1309
|
103 * @param {string} name The name of a class we want to use.
|
bsw/jbe@1309
|
104 * @param {componentHandler.ComponentConfig=} optReplace Optional object to replace match with.
|
bsw/jbe@1309
|
105 * @return {!Object|boolean}
|
bsw/jbe@1309
|
106 * @private
|
bsw/jbe@1309
|
107 */
|
bsw/jbe@1309
|
108 function findRegisteredClass_(name, optReplace) {
|
bsw/jbe@1309
|
109 for (var i = 0; i < registeredComponents_.length; i++) {
|
bsw/jbe@1309
|
110 if (registeredComponents_[i].className === name) {
|
bsw/jbe@1309
|
111 if (typeof optReplace !== 'undefined') {
|
bsw/jbe@1309
|
112 registeredComponents_[i] = optReplace;
|
bsw/jbe@1309
|
113 }
|
bsw/jbe@1309
|
114 return registeredComponents_[i];
|
bsw/jbe@1309
|
115 }
|
bsw/jbe@1309
|
116 }
|
bsw/jbe@1309
|
117 return false;
|
bsw/jbe@1309
|
118 }
|
bsw/jbe@1309
|
119
|
bsw/jbe@1309
|
120 /**
|
bsw/jbe@1309
|
121 * Returns an array of the classNames of the upgraded classes on the element.
|
bsw/jbe@1309
|
122 *
|
bsw/jbe@1309
|
123 * @param {!Element} element The element to fetch data from.
|
bsw/jbe@1309
|
124 * @return {!Array<string>}
|
bsw/jbe@1309
|
125 * @private
|
bsw/jbe@1309
|
126 */
|
bsw/jbe@1309
|
127 function getUpgradedListOfElement_(element) {
|
bsw/jbe@1309
|
128 var dataUpgraded = element.getAttribute('data-upgraded');
|
bsw/jbe@1309
|
129 // Use `['']` as default value to conform the `,name,name...` style.
|
bsw/jbe@1309
|
130 return dataUpgraded === null ? [''] : dataUpgraded.split(',');
|
bsw/jbe@1309
|
131 }
|
bsw/jbe@1309
|
132
|
bsw/jbe@1309
|
133 /**
|
bsw/jbe@1309
|
134 * Returns true if the given element has already been upgraded for the given
|
bsw/jbe@1309
|
135 * class.
|
bsw/jbe@1309
|
136 *
|
bsw/jbe@1309
|
137 * @param {!Element} element The element we want to check.
|
bsw/jbe@1309
|
138 * @param {string} jsClass The class to check for.
|
bsw/jbe@1309
|
139 * @returns {boolean}
|
bsw/jbe@1309
|
140 * @private
|
bsw/jbe@1309
|
141 */
|
bsw/jbe@1309
|
142 function isElementUpgraded_(element, jsClass) {
|
bsw/jbe@1309
|
143 var upgradedList = getUpgradedListOfElement_(element);
|
bsw/jbe@1309
|
144 return upgradedList.indexOf(jsClass) !== -1;
|
bsw/jbe@1309
|
145 }
|
bsw/jbe@1309
|
146
|
bsw/jbe@1309
|
147 /**
|
bsw/jbe@1309
|
148 * Searches existing DOM for elements of our component type and upgrades them
|
bsw/jbe@1309
|
149 * if they have not already been upgraded.
|
bsw/jbe@1309
|
150 *
|
bsw/jbe@1309
|
151 * @param {string=} optJsClass the programatic name of the element class we
|
bsw/jbe@1309
|
152 * need to create a new instance of.
|
bsw/jbe@1309
|
153 * @param {string=} optCssClass the name of the CSS class elements of this
|
bsw/jbe@1309
|
154 * type will have.
|
bsw/jbe@1309
|
155 */
|
bsw/jbe@1309
|
156 function upgradeDomInternal(optJsClass, optCssClass) {
|
bsw/jbe@1309
|
157 if (typeof optJsClass === 'undefined' &&
|
bsw/jbe@1309
|
158 typeof optCssClass === 'undefined') {
|
bsw/jbe@1309
|
159 for (var i = 0; i < registeredComponents_.length; i++) {
|
bsw/jbe@1309
|
160 upgradeDomInternal(registeredComponents_[i].className,
|
bsw/jbe@1309
|
161 registeredComponents_[i].cssClass);
|
bsw/jbe@1309
|
162 }
|
bsw/jbe@1309
|
163 } else {
|
bsw/jbe@1309
|
164 var jsClass = /** @type {string} */ (optJsClass);
|
bsw/jbe@1309
|
165 if (typeof optCssClass === 'undefined') {
|
bsw/jbe@1309
|
166 var registeredClass = findRegisteredClass_(jsClass);
|
bsw/jbe@1309
|
167 if (registeredClass) {
|
bsw/jbe@1309
|
168 optCssClass = registeredClass.cssClass;
|
bsw/jbe@1309
|
169 }
|
bsw/jbe@1309
|
170 }
|
bsw/jbe@1309
|
171
|
bsw/jbe@1309
|
172 var elements = document.querySelectorAll('.' + optCssClass);
|
bsw/jbe@1309
|
173 for (var n = 0; n < elements.length; n++) {
|
bsw/jbe@1309
|
174 upgradeElementInternal(elements[n], jsClass);
|
bsw/jbe@1309
|
175 }
|
bsw/jbe@1309
|
176 }
|
bsw/jbe@1309
|
177 }
|
bsw/jbe@1309
|
178
|
bsw/jbe@1309
|
179 /**
|
bsw/jbe@1309
|
180 * Upgrades a specific element rather than all in the DOM.
|
bsw/jbe@1309
|
181 *
|
bsw/jbe@1309
|
182 * @param {!Element} element The element we wish to upgrade.
|
bsw/jbe@1309
|
183 * @param {string=} optJsClass Optional name of the class we want to upgrade
|
bsw/jbe@1309
|
184 * the element to.
|
bsw/jbe@1309
|
185 */
|
bsw/jbe@1309
|
186 function upgradeElementInternal(element, optJsClass) {
|
bsw/jbe@1309
|
187 // Verify argument type.
|
bsw/jbe@1309
|
188 if (!(typeof element === 'object' && element instanceof Element)) {
|
bsw/jbe@1309
|
189 throw new Error('Invalid argument provided to upgrade MDL element.');
|
bsw/jbe@1309
|
190 }
|
bsw/jbe@1309
|
191 var upgradedList = getUpgradedListOfElement_(element);
|
bsw/jbe@1309
|
192 var classesToUpgrade = [];
|
bsw/jbe@1309
|
193 // If jsClass is not provided scan the registered components to find the
|
bsw/jbe@1309
|
194 // ones matching the element's CSS classList.
|
bsw/jbe@1309
|
195 if (!optJsClass) {
|
bsw/jbe@1309
|
196 var classList = element.classList;
|
bsw/jbe@1309
|
197 registeredComponents_.forEach(function(component) {
|
bsw/jbe@1309
|
198 // Match CSS & Not to be upgraded & Not upgraded.
|
bsw/jbe@1309
|
199 if (classList.contains(component.cssClass) &&
|
bsw/jbe@1309
|
200 classesToUpgrade.indexOf(component) === -1 &&
|
bsw/jbe@1309
|
201 !isElementUpgraded_(element, component.className)) {
|
bsw/jbe@1309
|
202 classesToUpgrade.push(component);
|
bsw/jbe@1309
|
203 }
|
bsw/jbe@1309
|
204 });
|
bsw/jbe@1309
|
205 } else if (!isElementUpgraded_(element, optJsClass)) {
|
bsw/jbe@1309
|
206 classesToUpgrade.push(findRegisteredClass_(optJsClass));
|
bsw/jbe@1309
|
207 }
|
bsw/jbe@1309
|
208
|
bsw/jbe@1309
|
209 // Upgrade the element for each classes.
|
bsw/jbe@1309
|
210 for (var i = 0, n = classesToUpgrade.length, registeredClass; i < n; i++) {
|
bsw/jbe@1309
|
211 registeredClass = classesToUpgrade[i];
|
bsw/jbe@1309
|
212 if (registeredClass) {
|
bsw/jbe@1309
|
213 // Mark element as upgraded.
|
bsw/jbe@1309
|
214 upgradedList.push(registeredClass.className);
|
bsw/jbe@1309
|
215 element.setAttribute('data-upgraded', upgradedList.join(','));
|
bsw/jbe@1309
|
216 var instance = new registeredClass.classConstructor(element);
|
bsw/jbe@1309
|
217 instance[componentConfigProperty_] = registeredClass;
|
bsw/jbe@1309
|
218 createdComponents_.push(instance);
|
bsw/jbe@1309
|
219 // Call any callbacks the user has registered with this component type.
|
bsw/jbe@1309
|
220 for (var j = 0, m = registeredClass.callbacks.length; j < m; j++) {
|
bsw/jbe@1309
|
221 registeredClass.callbacks[j](element);
|
bsw/jbe@1309
|
222 }
|
bsw/jbe@1309
|
223
|
bsw/jbe@1309
|
224 if (registeredClass.widget) {
|
bsw/jbe@1309
|
225 // Assign per element instance for control over API
|
bsw/jbe@1309
|
226 element[registeredClass.className] = instance;
|
bsw/jbe@1309
|
227 }
|
bsw/jbe@1309
|
228 } else {
|
bsw/jbe@1309
|
229 throw new Error(
|
bsw/jbe@1309
|
230 'Unable to find a registered component for the given class.');
|
bsw/jbe@1309
|
231 }
|
bsw/jbe@1309
|
232
|
bsw/jbe@1309
|
233 var ev;
|
bsw/jbe@1309
|
234 if ('CustomEvent' in window && typeof window.CustomEvent === 'function') {
|
bsw/jbe@1309
|
235 ev = new CustomEvent('mdl-componentupgraded', {
|
bsw/jbe@1309
|
236 bubbles: true, cancelable: false
|
bsw/jbe@1309
|
237 });
|
bsw/jbe@1309
|
238 } else {
|
bsw/jbe@1309
|
239 ev = document.createEvent('Events');
|
bsw/jbe@1309
|
240 ev.initEvent('mdl-componentupgraded', true, true);
|
bsw/jbe@1309
|
241 }
|
bsw/jbe@1309
|
242 element.dispatchEvent(ev);
|
bsw/jbe@1309
|
243 }
|
bsw/jbe@1309
|
244 }
|
bsw/jbe@1309
|
245
|
bsw/jbe@1309
|
246 /**
|
bsw/jbe@1309
|
247 * Upgrades a specific list of elements rather than all in the DOM.
|
bsw/jbe@1309
|
248 *
|
bsw/jbe@1309
|
249 * @param {!Element|!Array<!Element>|!NodeList|!HTMLCollection} elements
|
bsw/jbe@1309
|
250 * The elements we wish to upgrade.
|
bsw/jbe@1309
|
251 */
|
bsw/jbe@1309
|
252 function upgradeElementsInternal(elements) {
|
bsw/jbe@1309
|
253 if (!Array.isArray(elements)) {
|
bsw/jbe@1309
|
254 if (elements instanceof Element) {
|
bsw/jbe@1309
|
255 elements = [elements];
|
bsw/jbe@1309
|
256 } else {
|
bsw/jbe@1309
|
257 elements = Array.prototype.slice.call(elements);
|
bsw/jbe@1309
|
258 }
|
bsw/jbe@1309
|
259 }
|
bsw/jbe@1309
|
260 for (var i = 0, n = elements.length, element; i < n; i++) {
|
bsw/jbe@1309
|
261 element = elements[i];
|
bsw/jbe@1309
|
262 if (element instanceof HTMLElement) {
|
bsw/jbe@1309
|
263 upgradeElementInternal(element);
|
bsw/jbe@1309
|
264 if (element.children.length > 0) {
|
bsw/jbe@1309
|
265 upgradeElementsInternal(element.children);
|
bsw/jbe@1309
|
266 }
|
bsw/jbe@1309
|
267 }
|
bsw/jbe@1309
|
268 }
|
bsw/jbe@1309
|
269 }
|
bsw/jbe@1309
|
270
|
bsw/jbe@1309
|
271 /**
|
bsw/jbe@1309
|
272 * Registers a class for future use and attempts to upgrade existing DOM.
|
bsw/jbe@1309
|
273 *
|
bsw/jbe@1309
|
274 * @param {componentHandler.ComponentConfigPublic} config
|
bsw/jbe@1309
|
275 */
|
bsw/jbe@1309
|
276 function registerInternal(config) {
|
bsw/jbe@1309
|
277 // In order to support both Closure-compiled and uncompiled code accessing
|
bsw/jbe@1309
|
278 // this method, we need to allow for both the dot and array syntax for
|
bsw/jbe@1309
|
279 // property access. You'll therefore see the `foo.bar || foo['bar']`
|
bsw/jbe@1309
|
280 // pattern repeated across this method.
|
bsw/jbe@1309
|
281 var widgetMissing = (typeof config.widget === 'undefined' &&
|
bsw/jbe@1309
|
282 typeof config['widget'] === 'undefined');
|
bsw/jbe@1309
|
283 var widget = true;
|
bsw/jbe@1309
|
284
|
bsw/jbe@1309
|
285 if (!widgetMissing) {
|
bsw/jbe@1309
|
286 widget = config.widget || config['widget'];
|
bsw/jbe@1309
|
287 }
|
bsw/jbe@1309
|
288
|
bsw/jbe@1309
|
289 var newConfig = /** @type {componentHandler.ComponentConfig} */ ({
|
bsw/jbe@1309
|
290 classConstructor: config.constructor || config['constructor'],
|
bsw/jbe@1309
|
291 className: config.classAsString || config['classAsString'],
|
bsw/jbe@1309
|
292 cssClass: config.cssClass || config['cssClass'],
|
bsw/jbe@1309
|
293 widget: widget,
|
bsw/jbe@1309
|
294 callbacks: []
|
bsw/jbe@1309
|
295 });
|
bsw/jbe@1309
|
296
|
bsw/jbe@1309
|
297 registeredComponents_.forEach(function(item) {
|
bsw/jbe@1309
|
298 if (item.cssClass === newConfig.cssClass) {
|
bsw/jbe@1309
|
299 throw new Error('The provided cssClass has already been registered: ' + item.cssClass);
|
bsw/jbe@1309
|
300 }
|
bsw/jbe@1309
|
301 if (item.className === newConfig.className) {
|
bsw/jbe@1309
|
302 throw new Error('The provided className has already been registered');
|
bsw/jbe@1309
|
303 }
|
bsw/jbe@1309
|
304 });
|
bsw/jbe@1309
|
305
|
bsw/jbe@1309
|
306 if (config.constructor.prototype
|
bsw/jbe@1309
|
307 .hasOwnProperty(componentConfigProperty_)) {
|
bsw/jbe@1309
|
308 throw new Error(
|
bsw/jbe@1309
|
309 'MDL component classes must not have ' + componentConfigProperty_ +
|
bsw/jbe@1309
|
310 ' defined as a property.');
|
bsw/jbe@1309
|
311 }
|
bsw/jbe@1309
|
312
|
bsw/jbe@1309
|
313 var found = findRegisteredClass_(config.classAsString, newConfig);
|
bsw/jbe@1309
|
314
|
bsw/jbe@1309
|
315 if (!found) {
|
bsw/jbe@1309
|
316 registeredComponents_.push(newConfig);
|
bsw/jbe@1309
|
317 }
|
bsw/jbe@1309
|
318 }
|
bsw/jbe@1309
|
319
|
bsw/jbe@1309
|
320 /**
|
bsw/jbe@1309
|
321 * Allows user to be alerted to any upgrades that are performed for a given
|
bsw/jbe@1309
|
322 * component type
|
bsw/jbe@1309
|
323 *
|
bsw/jbe@1309
|
324 * @param {string} jsClass The class name of the MDL component we wish
|
bsw/jbe@1309
|
325 * to hook into for any upgrades performed.
|
bsw/jbe@1309
|
326 * @param {function(!HTMLElement)} callback The function to call upon an
|
bsw/jbe@1309
|
327 * upgrade. This function should expect 1 parameter - the HTMLElement which
|
bsw/jbe@1309
|
328 * got upgraded.
|
bsw/jbe@1309
|
329 */
|
bsw/jbe@1309
|
330 function registerUpgradedCallbackInternal(jsClass, callback) {
|
bsw/jbe@1309
|
331 var regClass = findRegisteredClass_(jsClass);
|
bsw/jbe@1309
|
332 if (regClass) {
|
bsw/jbe@1309
|
333 regClass.callbacks.push(callback);
|
bsw/jbe@1309
|
334 }
|
bsw/jbe@1309
|
335 }
|
bsw/jbe@1309
|
336
|
bsw/jbe@1309
|
337 /**
|
bsw/jbe@1309
|
338 * Upgrades all registered components found in the current DOM. This is
|
bsw/jbe@1309
|
339 * automatically called on window load.
|
bsw/jbe@1309
|
340 */
|
bsw/jbe@1309
|
341 function upgradeAllRegisteredInternal() {
|
bsw/jbe@1309
|
342 for (var n = 0; n < registeredComponents_.length; n++) {
|
bsw/jbe@1309
|
343 upgradeDomInternal(registeredComponents_[n].className);
|
bsw/jbe@1309
|
344 }
|
bsw/jbe@1309
|
345 }
|
bsw/jbe@1309
|
346
|
bsw/jbe@1309
|
347 /**
|
bsw/jbe@1309
|
348 * Check the component for the downgrade method.
|
bsw/jbe@1309
|
349 * Execute if found.
|
bsw/jbe@1309
|
350 * Remove component from createdComponents list.
|
bsw/jbe@1309
|
351 *
|
bsw/jbe@1309
|
352 * @param {?componentHandler.Component} component
|
bsw/jbe@1309
|
353 */
|
bsw/jbe@1309
|
354 function deconstructComponentInternal(component) {
|
bsw/jbe@1309
|
355 if (component) {
|
bsw/jbe@1309
|
356 var componentIndex = createdComponents_.indexOf(component);
|
bsw/jbe@1309
|
357 createdComponents_.splice(componentIndex, 1);
|
bsw/jbe@1309
|
358
|
bsw/jbe@1309
|
359 var upgrades = component.element_.getAttribute('data-upgraded').split(',');
|
bsw/jbe@1309
|
360 var componentPlace = upgrades.indexOf(component[componentConfigProperty_].classAsString);
|
bsw/jbe@1309
|
361 upgrades.splice(componentPlace, 1);
|
bsw/jbe@1309
|
362 component.element_.setAttribute('data-upgraded', upgrades.join(','));
|
bsw/jbe@1309
|
363
|
bsw/jbe@1309
|
364 var ev;
|
bsw/jbe@1309
|
365 if ('CustomEvent' in window && typeof window.CustomEvent === 'function') {
|
bsw/jbe@1309
|
366 ev = new CustomEvent('mdl-componentdowngraded', {
|
bsw/jbe@1309
|
367 bubbles: true, cancelable: false
|
bsw/jbe@1309
|
368 });
|
bsw/jbe@1309
|
369 } else {
|
bsw/jbe@1309
|
370 ev = document.createEvent('Events');
|
bsw/jbe@1309
|
371 ev.initEvent('mdl-componentdowngraded', true, true);
|
bsw/jbe@1309
|
372 }
|
bsw/jbe@1309
|
373 component.element_.dispatchEvent(ev);
|
bsw/jbe@1309
|
374 }
|
bsw/jbe@1309
|
375 }
|
bsw/jbe@1309
|
376
|
bsw/jbe@1309
|
377 /**
|
bsw/jbe@1309
|
378 * Downgrade either a given node, an array of nodes, or a NodeList.
|
bsw/jbe@1309
|
379 *
|
bsw/jbe@1309
|
380 * @param {!Node|!Array<!Node>|!NodeList} nodes
|
bsw/jbe@1309
|
381 */
|
bsw/jbe@1309
|
382 function downgradeNodesInternal(nodes) {
|
bsw/jbe@1309
|
383 /**
|
bsw/jbe@1309
|
384 * Auxiliary function to downgrade a single node.
|
bsw/jbe@1309
|
385 * @param {!Node} node the node to be downgraded
|
bsw/jbe@1309
|
386 */
|
bsw/jbe@1309
|
387 var downgradeNode = function(node) {
|
bsw/jbe@1309
|
388 createdComponents_.filter(function(item) {
|
bsw/jbe@1309
|
389 return item.element_ === node;
|
bsw/jbe@1309
|
390 }).forEach(deconstructComponentInternal);
|
bsw/jbe@1309
|
391 };
|
bsw/jbe@1309
|
392 if (nodes instanceof Array || nodes instanceof NodeList) {
|
bsw/jbe@1309
|
393 for (var n = 0; n < nodes.length; n++) {
|
bsw/jbe@1309
|
394 downgradeNode(nodes[n]);
|
bsw/jbe@1309
|
395 }
|
bsw/jbe@1309
|
396 } else if (nodes instanceof Node) {
|
bsw/jbe@1309
|
397 downgradeNode(nodes);
|
bsw/jbe@1309
|
398 } else {
|
bsw/jbe@1309
|
399 throw new Error('Invalid argument provided to downgrade MDL nodes.');
|
bsw/jbe@1309
|
400 }
|
bsw/jbe@1309
|
401 }
|
bsw/jbe@1309
|
402
|
bsw/jbe@1309
|
403 // Now return the functions that should be made public with their publicly
|
bsw/jbe@1309
|
404 // facing names...
|
bsw/jbe@1309
|
405 return {
|
bsw/jbe@1309
|
406 upgradeDom: upgradeDomInternal,
|
bsw/jbe@1309
|
407 upgradeElement: upgradeElementInternal,
|
bsw/jbe@1309
|
408 upgradeElements: upgradeElementsInternal,
|
bsw/jbe@1309
|
409 upgradeAllRegistered: upgradeAllRegisteredInternal,
|
bsw/jbe@1309
|
410 registerUpgradedCallback: registerUpgradedCallbackInternal,
|
bsw/jbe@1309
|
411 register: registerInternal,
|
bsw/jbe@1309
|
412 downgradeElements: downgradeNodesInternal
|
bsw/jbe@1309
|
413 };
|
bsw/jbe@1309
|
414 })();
|
bsw/jbe@1309
|
415
|
bsw/jbe@1309
|
416 /**
|
bsw/jbe@1309
|
417 * Describes the type of a registered component type managed by
|
bsw/jbe@1309
|
418 * componentHandler. Provided for benefit of the Closure compiler.
|
bsw/jbe@1309
|
419 *
|
bsw/jbe@1309
|
420 * @typedef {{
|
bsw/jbe@1309
|
421 * constructor: Function,
|
bsw/jbe@1309
|
422 * classAsString: string,
|
bsw/jbe@1309
|
423 * cssClass: string,
|
bsw/jbe@1309
|
424 * widget: (string|boolean|undefined)
|
bsw/jbe@1309
|
425 * }}
|
bsw/jbe@1309
|
426 */
|
bsw/jbe@1309
|
427 componentHandler.ComponentConfigPublic; // jshint ignore:line
|
bsw/jbe@1309
|
428
|
bsw/jbe@1309
|
429 /**
|
bsw/jbe@1309
|
430 * Describes the type of a registered component type managed by
|
bsw/jbe@1309
|
431 * componentHandler. Provided for benefit of the Closure compiler.
|
bsw/jbe@1309
|
432 *
|
bsw/jbe@1309
|
433 * @typedef {{
|
bsw/jbe@1309
|
434 * constructor: !Function,
|
bsw/jbe@1309
|
435 * className: string,
|
bsw/jbe@1309
|
436 * cssClass: string,
|
bsw/jbe@1309
|
437 * widget: (string|boolean),
|
bsw/jbe@1309
|
438 * callbacks: !Array<function(!HTMLElement)>
|
bsw/jbe@1309
|
439 * }}
|
bsw/jbe@1309
|
440 */
|
bsw/jbe@1309
|
441 componentHandler.ComponentConfig; // jshint ignore:line
|
bsw/jbe@1309
|
442
|
bsw/jbe@1309
|
443 /**
|
bsw/jbe@1309
|
444 * Created component (i.e., upgraded element) type as managed by
|
bsw/jbe@1309
|
445 * componentHandler. Provided for benefit of the Closure compiler.
|
bsw/jbe@1309
|
446 *
|
bsw/jbe@1309
|
447 * @typedef {{
|
bsw/jbe@1309
|
448 * element_: !HTMLElement,
|
bsw/jbe@1309
|
449 * className: string,
|
bsw/jbe@1309
|
450 * classAsString: string,
|
bsw/jbe@1309
|
451 * cssClass: string,
|
bsw/jbe@1309
|
452 * widget: string
|
bsw/jbe@1309
|
453 * }}
|
bsw/jbe@1309
|
454 */
|
bsw/jbe@1309
|
455 componentHandler.Component; // jshint ignore:line
|
bsw/jbe@1309
|
456
|
bsw/jbe@1309
|
457 // Export all symbols, for the benefit of Closure compiler.
|
bsw/jbe@1309
|
458 // No effect on uncompiled code.
|
bsw/jbe@1309
|
459 componentHandler['upgradeDom'] = componentHandler.upgradeDom;
|
bsw/jbe@1309
|
460 componentHandler['upgradeElement'] = componentHandler.upgradeElement;
|
bsw/jbe@1309
|
461 componentHandler['upgradeElements'] = componentHandler.upgradeElements;
|
bsw/jbe@1309
|
462 componentHandler['upgradeAllRegistered'] =
|
bsw/jbe@1309
|
463 componentHandler.upgradeAllRegistered;
|
bsw/jbe@1309
|
464 componentHandler['registerUpgradedCallback'] =
|
bsw/jbe@1309
|
465 componentHandler.registerUpgradedCallback;
|
bsw/jbe@1309
|
466 componentHandler['register'] = componentHandler.register;
|
bsw/jbe@1309
|
467 componentHandler['downgradeElements'] = componentHandler.downgradeElements;
|
bsw/jbe@1309
|
468 window.componentHandler = componentHandler;
|
bsw/jbe@1309
|
469 window['componentHandler'] = componentHandler;
|
bsw/jbe@1309
|
470
|
bsw/jbe@1309
|
471 window.addEventListener('load', function() {
|
bsw/jbe@1309
|
472 'use strict';
|
bsw/jbe@1309
|
473
|
bsw/jbe@1309
|
474 /**
|
bsw/jbe@1309
|
475 * Performs a "Cutting the mustard" test. If the browser supports the features
|
bsw/jbe@1309
|
476 * tested, adds a mdl-js class to the <html> element. It then upgrades all MDL
|
bsw/jbe@1309
|
477 * components requiring JavaScript.
|
bsw/jbe@1309
|
478 */
|
bsw/jbe@1309
|
479 if ('classList' in document.createElement('div') &&
|
bsw/jbe@1309
|
480 'querySelector' in document &&
|
bsw/jbe@1309
|
481 'addEventListener' in window && Array.prototype.forEach) {
|
bsw/jbe@1309
|
482 document.documentElement.classList.add('mdl-js');
|
bsw/jbe@1309
|
483 componentHandler.upgradeAllRegistered();
|
bsw/jbe@1309
|
484 } else {
|
bsw/jbe@1309
|
485 /**
|
bsw/jbe@1309
|
486 * Dummy function to avoid JS errors.
|
bsw/jbe@1309
|
487 */
|
bsw/jbe@1309
|
488 componentHandler.upgradeElement = function() {};
|
bsw/jbe@1309
|
489 /**
|
bsw/jbe@1309
|
490 * Dummy function to avoid JS errors.
|
bsw/jbe@1309
|
491 */
|
bsw/jbe@1309
|
492 componentHandler.register = function() {};
|
bsw/jbe@1309
|
493 }
|
bsw/jbe@1309
|
494 });
|
bsw/jbe@1309
|
495
|
bsw/jbe@1309
|
496 // Source: https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js
|
bsw/jbe@1309
|
497 // Adapted from https://gist.github.com/paulirish/1579671 which derived from
|
bsw/jbe@1309
|
498 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
bsw/jbe@1309
|
499 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
|
bsw/jbe@1309
|
500 // requestAnimationFrame polyfill by Erik Möller.
|
bsw/jbe@1309
|
501 // Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon
|
bsw/jbe@1309
|
502 // MIT license
|
bsw/jbe@1309
|
503 if (!Date.now) {
|
bsw/jbe@1309
|
504 /**
|
bsw/jbe@1309
|
505 * Date.now polyfill.
|
bsw/jbe@1309
|
506 * @return {number} the current Date
|
bsw/jbe@1309
|
507 */
|
bsw/jbe@1309
|
508 Date.now = function () {
|
bsw/jbe@1309
|
509 return new Date().getTime();
|
bsw/jbe@1309
|
510 };
|
bsw/jbe@1309
|
511 Date['now'] = Date.now;
|
bsw/jbe@1309
|
512 }
|
bsw/jbe@1309
|
513 var vendors = [
|
bsw/jbe@1309
|
514 'webkit',
|
bsw/jbe@1309
|
515 'moz'
|
bsw/jbe@1309
|
516 ];
|
bsw/jbe@1309
|
517 for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
|
bsw/jbe@1309
|
518 var vp = vendors[i];
|
bsw/jbe@1309
|
519 window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
|
bsw/jbe@1309
|
520 window.cancelAnimationFrame = window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame'];
|
bsw/jbe@1309
|
521 window['requestAnimationFrame'] = window.requestAnimationFrame;
|
bsw/jbe@1309
|
522 window['cancelAnimationFrame'] = window.cancelAnimationFrame;
|
bsw/jbe@1309
|
523 }
|
bsw/jbe@1309
|
524 if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
|
bsw/jbe@1309
|
525 var lastTime = 0;
|
bsw/jbe@1309
|
526 /**
|
bsw/jbe@1309
|
527 * requestAnimationFrame polyfill.
|
bsw/jbe@1309
|
528 * @param {!Function} callback the callback function.
|
bsw/jbe@1309
|
529 */
|
bsw/jbe@1309
|
530 window.requestAnimationFrame = function (callback) {
|
bsw/jbe@1309
|
531 var now = Date.now();
|
bsw/jbe@1309
|
532 var nextTime = Math.max(lastTime + 16, now);
|
bsw/jbe@1309
|
533 return setTimeout(function () {
|
bsw/jbe@1309
|
534 callback(lastTime = nextTime);
|
bsw/jbe@1309
|
535 }, nextTime - now);
|
bsw/jbe@1309
|
536 };
|
bsw/jbe@1309
|
537 window.cancelAnimationFrame = clearTimeout;
|
bsw/jbe@1309
|
538 window['requestAnimationFrame'] = window.requestAnimationFrame;
|
bsw/jbe@1309
|
539 window['cancelAnimationFrame'] = window.cancelAnimationFrame;
|
bsw/jbe@1309
|
540 }
|
bsw/jbe@1309
|
541 /**
|
bsw/jbe@1309
|
542 * @license
|
bsw/jbe@1309
|
543 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
544 *
|
bsw/jbe@1309
|
545 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
546 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
547 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
548 *
|
bsw/jbe@1309
|
549 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
550 *
|
bsw/jbe@1309
|
551 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
552 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
553 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
554 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
555 * limitations under the License.
|
bsw/jbe@1309
|
556 */
|
bsw/jbe@1309
|
557 /**
|
bsw/jbe@1309
|
558 * Class constructor for Button MDL component.
|
bsw/jbe@1309
|
559 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
560 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
561 *
|
bsw/jbe@1309
|
562 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
563 */
|
bsw/jbe@1309
|
564 var MaterialButton = function MaterialButton(element) {
|
bsw/jbe@1309
|
565 this.element_ = element;
|
bsw/jbe@1309
|
566 // Initialize instance.
|
bsw/jbe@1309
|
567 this.init();
|
bsw/jbe@1309
|
568 };
|
bsw/jbe@1309
|
569 window['MaterialButton'] = MaterialButton;
|
bsw/jbe@1309
|
570 /**
|
bsw/jbe@1309
|
571 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
572 *
|
bsw/jbe@1309
|
573 * @enum {string | number}
|
bsw/jbe@1309
|
574 * @private
|
bsw/jbe@1309
|
575 */
|
bsw/jbe@1309
|
576 MaterialButton.prototype.Constant_ = {};
|
bsw/jbe@1309
|
577 /**
|
bsw/jbe@1309
|
578 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
579 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
580 * decide to modify at a later date.
|
bsw/jbe@1309
|
581 *
|
bsw/jbe@1309
|
582 * @enum {string}
|
bsw/jbe@1309
|
583 * @private
|
bsw/jbe@1309
|
584 */
|
bsw/jbe@1309
|
585 MaterialButton.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
586 RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
587 RIPPLE_CONTAINER: 'mdl-button__ripple-container',
|
bsw/jbe@1309
|
588 RIPPLE: 'mdl-ripple'
|
bsw/jbe@1309
|
589 };
|
bsw/jbe@1309
|
590 /**
|
bsw/jbe@1309
|
591 * Handle blur of element.
|
bsw/jbe@1309
|
592 *
|
bsw/jbe@1309
|
593 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
594 * @private
|
bsw/jbe@1309
|
595 */
|
bsw/jbe@1309
|
596 MaterialButton.prototype.blurHandler_ = function (event) {
|
bsw/jbe@1309
|
597 if (event) {
|
bsw/jbe@1309
|
598 this.element_.blur();
|
bsw/jbe@1309
|
599 }
|
bsw/jbe@1309
|
600 };
|
bsw/jbe@1309
|
601 // Public methods.
|
bsw/jbe@1309
|
602 /**
|
bsw/jbe@1309
|
603 * Disable button.
|
bsw/jbe@1309
|
604 *
|
bsw/jbe@1309
|
605 * @public
|
bsw/jbe@1309
|
606 */
|
bsw/jbe@1309
|
607 MaterialButton.prototype.disable = function () {
|
bsw/jbe@1309
|
608 this.element_.disabled = true;
|
bsw/jbe@1309
|
609 };
|
bsw/jbe@1309
|
610 MaterialButton.prototype['disable'] = MaterialButton.prototype.disable;
|
bsw/jbe@1309
|
611 /**
|
bsw/jbe@1309
|
612 * Enable button.
|
bsw/jbe@1309
|
613 *
|
bsw/jbe@1309
|
614 * @public
|
bsw/jbe@1309
|
615 */
|
bsw/jbe@1309
|
616 MaterialButton.prototype.enable = function () {
|
bsw/jbe@1309
|
617 this.element_.disabled = false;
|
bsw/jbe@1309
|
618 };
|
bsw/jbe@1309
|
619 MaterialButton.prototype['enable'] = MaterialButton.prototype.enable;
|
bsw/jbe@1309
|
620 /**
|
bsw/jbe@1309
|
621 * Initialize element.
|
bsw/jbe@1309
|
622 */
|
bsw/jbe@1309
|
623 MaterialButton.prototype.init = function () {
|
bsw/jbe@1309
|
624 if (this.element_) {
|
bsw/jbe@1309
|
625 if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
626 var rippleContainer = document.createElement('span');
|
bsw/jbe@1309
|
627 rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
628 this.rippleElement_ = document.createElement('span');
|
bsw/jbe@1309
|
629 this.rippleElement_.classList.add(this.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
630 rippleContainer.appendChild(this.rippleElement_);
|
bsw/jbe@1309
|
631 this.boundRippleBlurHandler = this.blurHandler_.bind(this);
|
bsw/jbe@1309
|
632 this.rippleElement_.addEventListener('mouseup', this.boundRippleBlurHandler);
|
bsw/jbe@1309
|
633 this.element_.appendChild(rippleContainer);
|
bsw/jbe@1309
|
634 }
|
bsw/jbe@1309
|
635 this.boundButtonBlurHandler = this.blurHandler_.bind(this);
|
bsw/jbe@1309
|
636 this.element_.addEventListener('mouseup', this.boundButtonBlurHandler);
|
bsw/jbe@1309
|
637 this.element_.addEventListener('mouseleave', this.boundButtonBlurHandler);
|
bsw/jbe@1309
|
638 }
|
bsw/jbe@1309
|
639 };
|
bsw/jbe@1309
|
640 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
641 // in the global scope.
|
bsw/jbe@1309
|
642 componentHandler.register({
|
bsw/jbe@1309
|
643 constructor: MaterialButton,
|
bsw/jbe@1309
|
644 classAsString: 'MaterialButton',
|
bsw/jbe@1309
|
645 cssClass: 'mdl-js-button',
|
bsw/jbe@1309
|
646 widget: true
|
bsw/jbe@1309
|
647 });
|
bsw/jbe@1309
|
648 /**
|
bsw/jbe@1309
|
649 * @license
|
bsw/jbe@1309
|
650 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
651 *
|
bsw/jbe@1309
|
652 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
653 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
654 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
655 *
|
bsw/jbe@1309
|
656 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
657 *
|
bsw/jbe@1309
|
658 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
659 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
660 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
661 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
662 * limitations under the License.
|
bsw/jbe@1309
|
663 */
|
bsw/jbe@1309
|
664 /**
|
bsw/jbe@1309
|
665 * Class constructor for Checkbox MDL component.
|
bsw/jbe@1309
|
666 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
667 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
668 *
|
bsw/jbe@1309
|
669 * @constructor
|
bsw/jbe@1309
|
670 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
671 */
|
bsw/jbe@1309
|
672 var MaterialCheckbox = function MaterialCheckbox(element) {
|
bsw/jbe@1309
|
673 this.element_ = element;
|
bsw/jbe@1309
|
674 // Initialize instance.
|
bsw/jbe@1309
|
675 this.init();
|
bsw/jbe@1309
|
676 };
|
bsw/jbe@1309
|
677 window['MaterialCheckbox'] = MaterialCheckbox;
|
bsw/jbe@1309
|
678 /**
|
bsw/jbe@1309
|
679 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
680 *
|
bsw/jbe@1309
|
681 * @enum {string | number}
|
bsw/jbe@1309
|
682 * @private
|
bsw/jbe@1309
|
683 */
|
bsw/jbe@1309
|
684 MaterialCheckbox.prototype.Constant_ = { TINY_TIMEOUT: 0.001 };
|
bsw/jbe@1309
|
685 /**
|
bsw/jbe@1309
|
686 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
687 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
688 * decide to modify at a later date.
|
bsw/jbe@1309
|
689 *
|
bsw/jbe@1309
|
690 * @enum {string}
|
bsw/jbe@1309
|
691 * @private
|
bsw/jbe@1309
|
692 */
|
bsw/jbe@1309
|
693 MaterialCheckbox.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
694 INPUT: 'mdl-checkbox__input',
|
bsw/jbe@1309
|
695 BOX_OUTLINE: 'mdl-checkbox__box-outline',
|
bsw/jbe@1309
|
696 FOCUS_HELPER: 'mdl-checkbox__focus-helper',
|
bsw/jbe@1309
|
697 TICK_OUTLINE: 'mdl-checkbox__tick-outline',
|
bsw/jbe@1309
|
698 RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
699 RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
bsw/jbe@1309
|
700 RIPPLE_CONTAINER: 'mdl-checkbox__ripple-container',
|
bsw/jbe@1309
|
701 RIPPLE_CENTER: 'mdl-ripple--center',
|
bsw/jbe@1309
|
702 RIPPLE: 'mdl-ripple',
|
bsw/jbe@1309
|
703 IS_FOCUSED: 'is-focused',
|
bsw/jbe@1309
|
704 IS_DISABLED: 'is-disabled',
|
bsw/jbe@1309
|
705 IS_CHECKED: 'is-checked',
|
bsw/jbe@1309
|
706 IS_UPGRADED: 'is-upgraded'
|
bsw/jbe@1309
|
707 };
|
bsw/jbe@1309
|
708 /**
|
bsw/jbe@1309
|
709 * Handle change of state.
|
bsw/jbe@1309
|
710 *
|
bsw/jbe@1309
|
711 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
712 * @private
|
bsw/jbe@1309
|
713 */
|
bsw/jbe@1309
|
714 MaterialCheckbox.prototype.onChange_ = function (event) {
|
bsw/jbe@1309
|
715 this.updateClasses_();
|
bsw/jbe@1309
|
716 };
|
bsw/jbe@1309
|
717 /**
|
bsw/jbe@1309
|
718 * Handle focus of element.
|
bsw/jbe@1309
|
719 *
|
bsw/jbe@1309
|
720 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
721 * @private
|
bsw/jbe@1309
|
722 */
|
bsw/jbe@1309
|
723 MaterialCheckbox.prototype.onFocus_ = function (event) {
|
bsw/jbe@1309
|
724 this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
725 };
|
bsw/jbe@1309
|
726 /**
|
bsw/jbe@1309
|
727 * Handle lost focus of element.
|
bsw/jbe@1309
|
728 *
|
bsw/jbe@1309
|
729 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
730 * @private
|
bsw/jbe@1309
|
731 */
|
bsw/jbe@1309
|
732 MaterialCheckbox.prototype.onBlur_ = function (event) {
|
bsw/jbe@1309
|
733 this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
734 };
|
bsw/jbe@1309
|
735 /**
|
bsw/jbe@1309
|
736 * Handle mouseup.
|
bsw/jbe@1309
|
737 *
|
bsw/jbe@1309
|
738 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
739 * @private
|
bsw/jbe@1309
|
740 */
|
bsw/jbe@1309
|
741 MaterialCheckbox.prototype.onMouseUp_ = function (event) {
|
bsw/jbe@1309
|
742 this.blur_();
|
bsw/jbe@1309
|
743 };
|
bsw/jbe@1309
|
744 /**
|
bsw/jbe@1309
|
745 * Handle class updates.
|
bsw/jbe@1309
|
746 *
|
bsw/jbe@1309
|
747 * @private
|
bsw/jbe@1309
|
748 */
|
bsw/jbe@1309
|
749 MaterialCheckbox.prototype.updateClasses_ = function () {
|
bsw/jbe@1309
|
750 this.checkDisabled();
|
bsw/jbe@1309
|
751 this.checkToggleState();
|
bsw/jbe@1309
|
752 };
|
bsw/jbe@1309
|
753 /**
|
bsw/jbe@1309
|
754 * Add blur.
|
bsw/jbe@1309
|
755 *
|
bsw/jbe@1309
|
756 * @private
|
bsw/jbe@1309
|
757 */
|
bsw/jbe@1309
|
758 MaterialCheckbox.prototype.blur_ = function () {
|
bsw/jbe@1309
|
759 // TODO: figure out why there's a focus event being fired after our blur,
|
bsw/jbe@1309
|
760 // so that we can avoid this hack.
|
bsw/jbe@1309
|
761 window.setTimeout(function () {
|
bsw/jbe@1309
|
762 this.inputElement_.blur();
|
bsw/jbe@1309
|
763 }.bind(this), this.Constant_.TINY_TIMEOUT);
|
bsw/jbe@1309
|
764 };
|
bsw/jbe@1309
|
765 // Public methods.
|
bsw/jbe@1309
|
766 /**
|
bsw/jbe@1309
|
767 * Check the inputs toggle state and update display.
|
bsw/jbe@1309
|
768 *
|
bsw/jbe@1309
|
769 * @public
|
bsw/jbe@1309
|
770 */
|
bsw/jbe@1309
|
771 MaterialCheckbox.prototype.checkToggleState = function () {
|
bsw/jbe@1309
|
772 if (this.inputElement_.checked) {
|
bsw/jbe@1309
|
773 this.element_.classList.add(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
774 } else {
|
bsw/jbe@1309
|
775 this.element_.classList.remove(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
776 }
|
bsw/jbe@1309
|
777 };
|
bsw/jbe@1309
|
778 MaterialCheckbox.prototype['checkToggleState'] = MaterialCheckbox.prototype.checkToggleState;
|
bsw/jbe@1309
|
779 /**
|
bsw/jbe@1309
|
780 * Check the inputs disabled state and update display.
|
bsw/jbe@1309
|
781 *
|
bsw/jbe@1309
|
782 * @public
|
bsw/jbe@1309
|
783 */
|
bsw/jbe@1309
|
784 MaterialCheckbox.prototype.checkDisabled = function () {
|
bsw/jbe@1309
|
785 if (this.inputElement_.disabled) {
|
bsw/jbe@1309
|
786 this.element_.classList.add(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
787 } else {
|
bsw/jbe@1309
|
788 this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
789 }
|
bsw/jbe@1309
|
790 };
|
bsw/jbe@1309
|
791 MaterialCheckbox.prototype['checkDisabled'] = MaterialCheckbox.prototype.checkDisabled;
|
bsw/jbe@1309
|
792 /**
|
bsw/jbe@1309
|
793 * Disable checkbox.
|
bsw/jbe@1309
|
794 *
|
bsw/jbe@1309
|
795 * @public
|
bsw/jbe@1309
|
796 */
|
bsw/jbe@1309
|
797 MaterialCheckbox.prototype.disable = function () {
|
bsw/jbe@1309
|
798 this.inputElement_.disabled = true;
|
bsw/jbe@1309
|
799 this.updateClasses_();
|
bsw/jbe@1309
|
800 };
|
bsw/jbe@1309
|
801 MaterialCheckbox.prototype['disable'] = MaterialCheckbox.prototype.disable;
|
bsw/jbe@1309
|
802 /**
|
bsw/jbe@1309
|
803 * Enable checkbox.
|
bsw/jbe@1309
|
804 *
|
bsw/jbe@1309
|
805 * @public
|
bsw/jbe@1309
|
806 */
|
bsw/jbe@1309
|
807 MaterialCheckbox.prototype.enable = function () {
|
bsw/jbe@1309
|
808 this.inputElement_.disabled = false;
|
bsw/jbe@1309
|
809 this.updateClasses_();
|
bsw/jbe@1309
|
810 };
|
bsw/jbe@1309
|
811 MaterialCheckbox.prototype['enable'] = MaterialCheckbox.prototype.enable;
|
bsw/jbe@1309
|
812 /**
|
bsw/jbe@1309
|
813 * Check checkbox.
|
bsw/jbe@1309
|
814 *
|
bsw/jbe@1309
|
815 * @public
|
bsw/jbe@1309
|
816 */
|
bsw/jbe@1309
|
817 MaterialCheckbox.prototype.check = function () {
|
bsw/jbe@1309
|
818 this.inputElement_.checked = true;
|
bsw/jbe@1309
|
819 this.updateClasses_();
|
bsw/jbe@1309
|
820 };
|
bsw/jbe@1309
|
821 MaterialCheckbox.prototype['check'] = MaterialCheckbox.prototype.check;
|
bsw/jbe@1309
|
822 /**
|
bsw/jbe@1309
|
823 * Uncheck checkbox.
|
bsw/jbe@1309
|
824 *
|
bsw/jbe@1309
|
825 * @public
|
bsw/jbe@1309
|
826 */
|
bsw/jbe@1309
|
827 MaterialCheckbox.prototype.uncheck = function () {
|
bsw/jbe@1309
|
828 this.inputElement_.checked = false;
|
bsw/jbe@1309
|
829 this.updateClasses_();
|
bsw/jbe@1309
|
830 };
|
bsw/jbe@1309
|
831 MaterialCheckbox.prototype['uncheck'] = MaterialCheckbox.prototype.uncheck;
|
bsw/jbe@1309
|
832 /**
|
bsw/jbe@1309
|
833 * Initialize element.
|
bsw/jbe@1309
|
834 */
|
bsw/jbe@1309
|
835 MaterialCheckbox.prototype.init = function () {
|
bsw/jbe@1309
|
836 if (this.element_) {
|
bsw/jbe@1309
|
837 this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT);
|
bsw/jbe@1309
|
838 var boxOutline = document.createElement('span');
|
bsw/jbe@1309
|
839 boxOutline.classList.add(this.CssClasses_.BOX_OUTLINE);
|
bsw/jbe@1309
|
840 var tickContainer = document.createElement('span');
|
bsw/jbe@1309
|
841 tickContainer.classList.add(this.CssClasses_.FOCUS_HELPER);
|
bsw/jbe@1309
|
842 var tickOutline = document.createElement('span');
|
bsw/jbe@1309
|
843 tickOutline.classList.add(this.CssClasses_.TICK_OUTLINE);
|
bsw/jbe@1309
|
844 boxOutline.appendChild(tickOutline);
|
bsw/jbe@1309
|
845 this.element_.appendChild(tickContainer);
|
bsw/jbe@1309
|
846 this.element_.appendChild(boxOutline);
|
bsw/jbe@1309
|
847 if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
848 this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
bsw/jbe@1309
|
849 this.rippleContainerElement_ = document.createElement('span');
|
bsw/jbe@1309
|
850 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
851 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT);
|
bsw/jbe@1309
|
852 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER);
|
bsw/jbe@1309
|
853 this.boundRippleMouseUp = this.onMouseUp_.bind(this);
|
bsw/jbe@1309
|
854 this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp);
|
bsw/jbe@1309
|
855 var ripple = document.createElement('span');
|
bsw/jbe@1309
|
856 ripple.classList.add(this.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
857 this.rippleContainerElement_.appendChild(ripple);
|
bsw/jbe@1309
|
858 this.element_.appendChild(this.rippleContainerElement_);
|
bsw/jbe@1309
|
859 }
|
bsw/jbe@1309
|
860 this.boundInputOnChange = this.onChange_.bind(this);
|
bsw/jbe@1309
|
861 this.boundInputOnFocus = this.onFocus_.bind(this);
|
bsw/jbe@1309
|
862 this.boundInputOnBlur = this.onBlur_.bind(this);
|
bsw/jbe@1309
|
863 this.boundElementMouseUp = this.onMouseUp_.bind(this);
|
bsw/jbe@1309
|
864 this.inputElement_.addEventListener('change', this.boundInputOnChange);
|
bsw/jbe@1309
|
865 this.inputElement_.addEventListener('focus', this.boundInputOnFocus);
|
bsw/jbe@1309
|
866 this.inputElement_.addEventListener('blur', this.boundInputOnBlur);
|
bsw/jbe@1309
|
867 this.element_.addEventListener('mouseup', this.boundElementMouseUp);
|
bsw/jbe@1309
|
868 this.updateClasses_();
|
bsw/jbe@1309
|
869 this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
|
bsw/jbe@1309
|
870 }
|
bsw/jbe@1309
|
871 };
|
bsw/jbe@1309
|
872 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
873 // in the global scope.
|
bsw/jbe@1309
|
874 componentHandler.register({
|
bsw/jbe@1309
|
875 constructor: MaterialCheckbox,
|
bsw/jbe@1309
|
876 classAsString: 'MaterialCheckbox',
|
bsw/jbe@1309
|
877 cssClass: 'mdl-js-checkbox',
|
bsw/jbe@1309
|
878 widget: true
|
bsw/jbe@1309
|
879 });
|
bsw/jbe@1309
|
880 /**
|
bsw/jbe@1309
|
881 * @license
|
bsw/jbe@1309
|
882 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
883 *
|
bsw/jbe@1309
|
884 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
885 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
886 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
887 *
|
bsw/jbe@1309
|
888 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
889 *
|
bsw/jbe@1309
|
890 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
891 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
892 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
893 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
894 * limitations under the License.
|
bsw/jbe@1309
|
895 */
|
bsw/jbe@1309
|
896 /**
|
bsw/jbe@1309
|
897 * Class constructor for icon toggle MDL component.
|
bsw/jbe@1309
|
898 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
899 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
900 *
|
bsw/jbe@1309
|
901 * @constructor
|
bsw/jbe@1309
|
902 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
903 */
|
bsw/jbe@1309
|
904 var MaterialIconToggle = function MaterialIconToggle(element) {
|
bsw/jbe@1309
|
905 this.element_ = element;
|
bsw/jbe@1309
|
906 // Initialize instance.
|
bsw/jbe@1309
|
907 this.init();
|
bsw/jbe@1309
|
908 };
|
bsw/jbe@1309
|
909 window['MaterialIconToggle'] = MaterialIconToggle;
|
bsw/jbe@1309
|
910 /**
|
bsw/jbe@1309
|
911 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
912 *
|
bsw/jbe@1309
|
913 * @enum {string | number}
|
bsw/jbe@1309
|
914 * @private
|
bsw/jbe@1309
|
915 */
|
bsw/jbe@1309
|
916 MaterialIconToggle.prototype.Constant_ = { TINY_TIMEOUT: 0.001 };
|
bsw/jbe@1309
|
917 /**
|
bsw/jbe@1309
|
918 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
919 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
920 * decide to modify at a later date.
|
bsw/jbe@1309
|
921 *
|
bsw/jbe@1309
|
922 * @enum {string}
|
bsw/jbe@1309
|
923 * @private
|
bsw/jbe@1309
|
924 */
|
bsw/jbe@1309
|
925 MaterialIconToggle.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
926 INPUT: 'mdl-icon-toggle__input',
|
bsw/jbe@1309
|
927 JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
928 RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
bsw/jbe@1309
|
929 RIPPLE_CONTAINER: 'mdl-icon-toggle__ripple-container',
|
bsw/jbe@1309
|
930 RIPPLE_CENTER: 'mdl-ripple--center',
|
bsw/jbe@1309
|
931 RIPPLE: 'mdl-ripple',
|
bsw/jbe@1309
|
932 IS_FOCUSED: 'is-focused',
|
bsw/jbe@1309
|
933 IS_DISABLED: 'is-disabled',
|
bsw/jbe@1309
|
934 IS_CHECKED: 'is-checked'
|
bsw/jbe@1309
|
935 };
|
bsw/jbe@1309
|
936 /**
|
bsw/jbe@1309
|
937 * Handle change of state.
|
bsw/jbe@1309
|
938 *
|
bsw/jbe@1309
|
939 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
940 * @private
|
bsw/jbe@1309
|
941 */
|
bsw/jbe@1309
|
942 MaterialIconToggle.prototype.onChange_ = function (event) {
|
bsw/jbe@1309
|
943 this.updateClasses_();
|
bsw/jbe@1309
|
944 };
|
bsw/jbe@1309
|
945 /**
|
bsw/jbe@1309
|
946 * Handle focus of element.
|
bsw/jbe@1309
|
947 *
|
bsw/jbe@1309
|
948 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
949 * @private
|
bsw/jbe@1309
|
950 */
|
bsw/jbe@1309
|
951 MaterialIconToggle.prototype.onFocus_ = function (event) {
|
bsw/jbe@1309
|
952 this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
953 };
|
bsw/jbe@1309
|
954 /**
|
bsw/jbe@1309
|
955 * Handle lost focus of element.
|
bsw/jbe@1309
|
956 *
|
bsw/jbe@1309
|
957 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
958 * @private
|
bsw/jbe@1309
|
959 */
|
bsw/jbe@1309
|
960 MaterialIconToggle.prototype.onBlur_ = function (event) {
|
bsw/jbe@1309
|
961 this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
962 };
|
bsw/jbe@1309
|
963 /**
|
bsw/jbe@1309
|
964 * Handle mouseup.
|
bsw/jbe@1309
|
965 *
|
bsw/jbe@1309
|
966 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
967 * @private
|
bsw/jbe@1309
|
968 */
|
bsw/jbe@1309
|
969 MaterialIconToggle.prototype.onMouseUp_ = function (event) {
|
bsw/jbe@1309
|
970 this.blur_();
|
bsw/jbe@1309
|
971 };
|
bsw/jbe@1309
|
972 /**
|
bsw/jbe@1309
|
973 * Handle class updates.
|
bsw/jbe@1309
|
974 *
|
bsw/jbe@1309
|
975 * @private
|
bsw/jbe@1309
|
976 */
|
bsw/jbe@1309
|
977 MaterialIconToggle.prototype.updateClasses_ = function () {
|
bsw/jbe@1309
|
978 this.checkDisabled();
|
bsw/jbe@1309
|
979 this.checkToggleState();
|
bsw/jbe@1309
|
980 };
|
bsw/jbe@1309
|
981 /**
|
bsw/jbe@1309
|
982 * Add blur.
|
bsw/jbe@1309
|
983 *
|
bsw/jbe@1309
|
984 * @private
|
bsw/jbe@1309
|
985 */
|
bsw/jbe@1309
|
986 MaterialIconToggle.prototype.blur_ = function () {
|
bsw/jbe@1309
|
987 // TODO: figure out why there's a focus event being fired after our blur,
|
bsw/jbe@1309
|
988 // so that we can avoid this hack.
|
bsw/jbe@1309
|
989 window.setTimeout(function () {
|
bsw/jbe@1309
|
990 this.inputElement_.blur();
|
bsw/jbe@1309
|
991 }.bind(this), this.Constant_.TINY_TIMEOUT);
|
bsw/jbe@1309
|
992 };
|
bsw/jbe@1309
|
993 // Public methods.
|
bsw/jbe@1309
|
994 /**
|
bsw/jbe@1309
|
995 * Check the inputs toggle state and update display.
|
bsw/jbe@1309
|
996 *
|
bsw/jbe@1309
|
997 * @public
|
bsw/jbe@1309
|
998 */
|
bsw/jbe@1309
|
999 MaterialIconToggle.prototype.checkToggleState = function () {
|
bsw/jbe@1309
|
1000 if (this.inputElement_.checked) {
|
bsw/jbe@1309
|
1001 this.element_.classList.add(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
1002 } else {
|
bsw/jbe@1309
|
1003 this.element_.classList.remove(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
1004 }
|
bsw/jbe@1309
|
1005 };
|
bsw/jbe@1309
|
1006 MaterialIconToggle.prototype['checkToggleState'] = MaterialIconToggle.prototype.checkToggleState;
|
bsw/jbe@1309
|
1007 /**
|
bsw/jbe@1309
|
1008 * Check the inputs disabled state and update display.
|
bsw/jbe@1309
|
1009 *
|
bsw/jbe@1309
|
1010 * @public
|
bsw/jbe@1309
|
1011 */
|
bsw/jbe@1309
|
1012 MaterialIconToggle.prototype.checkDisabled = function () {
|
bsw/jbe@1309
|
1013 if (this.inputElement_.disabled) {
|
bsw/jbe@1309
|
1014 this.element_.classList.add(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
1015 } else {
|
bsw/jbe@1309
|
1016 this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
1017 }
|
bsw/jbe@1309
|
1018 };
|
bsw/jbe@1309
|
1019 MaterialIconToggle.prototype['checkDisabled'] = MaterialIconToggle.prototype.checkDisabled;
|
bsw/jbe@1309
|
1020 /**
|
bsw/jbe@1309
|
1021 * Disable icon toggle.
|
bsw/jbe@1309
|
1022 *
|
bsw/jbe@1309
|
1023 * @public
|
bsw/jbe@1309
|
1024 */
|
bsw/jbe@1309
|
1025 MaterialIconToggle.prototype.disable = function () {
|
bsw/jbe@1309
|
1026 this.inputElement_.disabled = true;
|
bsw/jbe@1309
|
1027 this.updateClasses_();
|
bsw/jbe@1309
|
1028 };
|
bsw/jbe@1309
|
1029 MaterialIconToggle.prototype['disable'] = MaterialIconToggle.prototype.disable;
|
bsw/jbe@1309
|
1030 /**
|
bsw/jbe@1309
|
1031 * Enable icon toggle.
|
bsw/jbe@1309
|
1032 *
|
bsw/jbe@1309
|
1033 * @public
|
bsw/jbe@1309
|
1034 */
|
bsw/jbe@1309
|
1035 MaterialIconToggle.prototype.enable = function () {
|
bsw/jbe@1309
|
1036 this.inputElement_.disabled = false;
|
bsw/jbe@1309
|
1037 this.updateClasses_();
|
bsw/jbe@1309
|
1038 };
|
bsw/jbe@1309
|
1039 MaterialIconToggle.prototype['enable'] = MaterialIconToggle.prototype.enable;
|
bsw/jbe@1309
|
1040 /**
|
bsw/jbe@1309
|
1041 * Check icon toggle.
|
bsw/jbe@1309
|
1042 *
|
bsw/jbe@1309
|
1043 * @public
|
bsw/jbe@1309
|
1044 */
|
bsw/jbe@1309
|
1045 MaterialIconToggle.prototype.check = function () {
|
bsw/jbe@1309
|
1046 this.inputElement_.checked = true;
|
bsw/jbe@1309
|
1047 this.updateClasses_();
|
bsw/jbe@1309
|
1048 };
|
bsw/jbe@1309
|
1049 MaterialIconToggle.prototype['check'] = MaterialIconToggle.prototype.check;
|
bsw/jbe@1309
|
1050 /**
|
bsw/jbe@1309
|
1051 * Uncheck icon toggle.
|
bsw/jbe@1309
|
1052 *
|
bsw/jbe@1309
|
1053 * @public
|
bsw/jbe@1309
|
1054 */
|
bsw/jbe@1309
|
1055 MaterialIconToggle.prototype.uncheck = function () {
|
bsw/jbe@1309
|
1056 this.inputElement_.checked = false;
|
bsw/jbe@1309
|
1057 this.updateClasses_();
|
bsw/jbe@1309
|
1058 };
|
bsw/jbe@1309
|
1059 MaterialIconToggle.prototype['uncheck'] = MaterialIconToggle.prototype.uncheck;
|
bsw/jbe@1309
|
1060 /**
|
bsw/jbe@1309
|
1061 * Initialize element.
|
bsw/jbe@1309
|
1062 */
|
bsw/jbe@1309
|
1063 MaterialIconToggle.prototype.init = function () {
|
bsw/jbe@1309
|
1064 if (this.element_) {
|
bsw/jbe@1309
|
1065 this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT);
|
bsw/jbe@1309
|
1066 if (this.element_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
1067 this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
bsw/jbe@1309
|
1068 this.rippleContainerElement_ = document.createElement('span');
|
bsw/jbe@1309
|
1069 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
1070 this.rippleContainerElement_.classList.add(this.CssClasses_.JS_RIPPLE_EFFECT);
|
bsw/jbe@1309
|
1071 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER);
|
bsw/jbe@1309
|
1072 this.boundRippleMouseUp = this.onMouseUp_.bind(this);
|
bsw/jbe@1309
|
1073 this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp);
|
bsw/jbe@1309
|
1074 var ripple = document.createElement('span');
|
bsw/jbe@1309
|
1075 ripple.classList.add(this.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
1076 this.rippleContainerElement_.appendChild(ripple);
|
bsw/jbe@1309
|
1077 this.element_.appendChild(this.rippleContainerElement_);
|
bsw/jbe@1309
|
1078 }
|
bsw/jbe@1309
|
1079 this.boundInputOnChange = this.onChange_.bind(this);
|
bsw/jbe@1309
|
1080 this.boundInputOnFocus = this.onFocus_.bind(this);
|
bsw/jbe@1309
|
1081 this.boundInputOnBlur = this.onBlur_.bind(this);
|
bsw/jbe@1309
|
1082 this.boundElementOnMouseUp = this.onMouseUp_.bind(this);
|
bsw/jbe@1309
|
1083 this.inputElement_.addEventListener('change', this.boundInputOnChange);
|
bsw/jbe@1309
|
1084 this.inputElement_.addEventListener('focus', this.boundInputOnFocus);
|
bsw/jbe@1309
|
1085 this.inputElement_.addEventListener('blur', this.boundInputOnBlur);
|
bsw/jbe@1309
|
1086 this.element_.addEventListener('mouseup', this.boundElementOnMouseUp);
|
bsw/jbe@1309
|
1087 this.updateClasses_();
|
bsw/jbe@1309
|
1088 this.element_.classList.add('is-upgraded');
|
bsw/jbe@1309
|
1089 }
|
bsw/jbe@1309
|
1090 };
|
bsw/jbe@1309
|
1091 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
1092 // in the global scope.
|
bsw/jbe@1309
|
1093 componentHandler.register({
|
bsw/jbe@1309
|
1094 constructor: MaterialIconToggle,
|
bsw/jbe@1309
|
1095 classAsString: 'MaterialIconToggle',
|
bsw/jbe@1309
|
1096 cssClass: 'mdl-js-icon-toggle',
|
bsw/jbe@1309
|
1097 widget: true
|
bsw/jbe@1309
|
1098 });
|
bsw/jbe@1309
|
1099 /**
|
bsw/jbe@1309
|
1100 * @license
|
bsw/jbe@1309
|
1101 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
1102 *
|
bsw/jbe@1309
|
1103 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
1104 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
1105 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
1106 *
|
bsw/jbe@1309
|
1107 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
1108 *
|
bsw/jbe@1309
|
1109 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
1110 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
1111 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
1112 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
1113 * limitations under the License.
|
bsw/jbe@1309
|
1114 */
|
bsw/jbe@1309
|
1115 /**
|
bsw/jbe@1309
|
1116 * Class constructor for dropdown MDL component.
|
bsw/jbe@1309
|
1117 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
1118 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
1119 *
|
bsw/jbe@1309
|
1120 * @constructor
|
bsw/jbe@1309
|
1121 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
1122 */
|
bsw/jbe@1309
|
1123 var MaterialMenu = function MaterialMenu(element) {
|
bsw/jbe@1309
|
1124 this.element_ = element;
|
bsw/jbe@1309
|
1125 // Initialize instance.
|
bsw/jbe@1309
|
1126 this.init();
|
bsw/jbe@1309
|
1127 };
|
bsw/jbe@1309
|
1128 window['MaterialMenu'] = MaterialMenu;
|
bsw/jbe@1309
|
1129 /**
|
bsw/jbe@1309
|
1130 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
1131 *
|
bsw/jbe@1309
|
1132 * @enum {string | number}
|
bsw/jbe@1309
|
1133 * @private
|
bsw/jbe@1309
|
1134 */
|
bsw/jbe@1309
|
1135 MaterialMenu.prototype.Constant_ = {
|
bsw/jbe@1309
|
1136 // Total duration of the menu animation.
|
bsw/jbe@1309
|
1137 TRANSITION_DURATION_SECONDS: 0.3,
|
bsw/jbe@1309
|
1138 // The fraction of the total duration we want to use for menu item animations.
|
bsw/jbe@1309
|
1139 TRANSITION_DURATION_FRACTION: 0.8,
|
bsw/jbe@1309
|
1140 // How long the menu stays open after choosing an option (so the user can see
|
bsw/jbe@1309
|
1141 // the ripple).
|
bsw/jbe@1309
|
1142 CLOSE_TIMEOUT: 150
|
bsw/jbe@1309
|
1143 };
|
bsw/jbe@1309
|
1144 /**
|
bsw/jbe@1309
|
1145 * Keycodes, for code readability.
|
bsw/jbe@1309
|
1146 *
|
bsw/jbe@1309
|
1147 * @enum {number}
|
bsw/jbe@1309
|
1148 * @private
|
bsw/jbe@1309
|
1149 */
|
bsw/jbe@1309
|
1150 MaterialMenu.prototype.Keycodes_ = {
|
bsw/jbe@1309
|
1151 ENTER: 13,
|
bsw/jbe@1309
|
1152 ESCAPE: 27,
|
bsw/jbe@1309
|
1153 SPACE: 32,
|
bsw/jbe@1309
|
1154 UP_ARROW: 38,
|
bsw/jbe@1309
|
1155 DOWN_ARROW: 40
|
bsw/jbe@1309
|
1156 };
|
bsw/jbe@1309
|
1157 /**
|
bsw/jbe@1309
|
1158 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
1159 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
1160 * decide to modify at a later date.
|
bsw/jbe@1309
|
1161 *
|
bsw/jbe@1309
|
1162 * @enum {string}
|
bsw/jbe@1309
|
1163 * @private
|
bsw/jbe@1309
|
1164 */
|
bsw/jbe@1309
|
1165 MaterialMenu.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
1166 CONTAINER: 'mdl-menu__container',
|
bsw/jbe@1309
|
1167 OUTLINE: 'mdl-menu__outline',
|
bsw/jbe@1309
|
1168 ITEM: 'mdl-menu__item',
|
bsw/jbe@1309
|
1169 ITEM_RIPPLE_CONTAINER: 'mdl-menu__item-ripple-container',
|
bsw/jbe@1309
|
1170 RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
1171 RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
bsw/jbe@1309
|
1172 RIPPLE: 'mdl-ripple',
|
bsw/jbe@1309
|
1173 // Statuses
|
bsw/jbe@1309
|
1174 IS_UPGRADED: 'is-upgraded',
|
bsw/jbe@1309
|
1175 IS_VISIBLE: 'is-visible',
|
bsw/jbe@1309
|
1176 IS_ANIMATING: 'is-animating',
|
bsw/jbe@1309
|
1177 // Alignment options
|
bsw/jbe@1309
|
1178 BOTTOM_LEFT: 'mdl-menu--bottom-left',
|
bsw/jbe@1309
|
1179 // This is the default.
|
bsw/jbe@1309
|
1180 BOTTOM_RIGHT: 'mdl-menu--bottom-right',
|
bsw/jbe@1309
|
1181 TOP_LEFT: 'mdl-menu--top-left',
|
bsw/jbe@1309
|
1182 TOP_RIGHT: 'mdl-menu--top-right',
|
bsw/jbe@1309
|
1183 UNALIGNED: 'mdl-menu--unaligned'
|
bsw/jbe@1309
|
1184 };
|
bsw/jbe@1309
|
1185 /**
|
bsw/jbe@1309
|
1186 * Initialize element.
|
bsw/jbe@1309
|
1187 */
|
bsw/jbe@1309
|
1188 MaterialMenu.prototype.init = function () {
|
bsw/jbe@1309
|
1189 if (this.element_) {
|
bsw/jbe@1309
|
1190 // Create container for the menu.
|
bsw/jbe@1309
|
1191 var container = document.createElement('div');
|
bsw/jbe@1309
|
1192 container.classList.add(this.CssClasses_.CONTAINER);
|
bsw/jbe@1309
|
1193 this.element_.parentElement.insertBefore(container, this.element_);
|
bsw/jbe@1309
|
1194 this.element_.parentElement.removeChild(this.element_);
|
bsw/jbe@1309
|
1195 container.appendChild(this.element_);
|
bsw/jbe@1309
|
1196 this.container_ = container;
|
bsw/jbe@1309
|
1197 // Create outline for the menu (shadow and background).
|
bsw/jbe@1309
|
1198 var outline = document.createElement('div');
|
bsw/jbe@1309
|
1199 outline.classList.add(this.CssClasses_.OUTLINE);
|
bsw/jbe@1309
|
1200 this.outline_ = outline;
|
bsw/jbe@1309
|
1201 container.insertBefore(outline, this.element_);
|
bsw/jbe@1309
|
1202 // Find the "for" element and bind events to it.
|
bsw/jbe@1309
|
1203 var forElId = this.element_.getAttribute('for') || this.element_.getAttribute('data-mdl-for');
|
bsw/jbe@1309
|
1204 var forEl = null;
|
bsw/jbe@1309
|
1205 if (forElId) {
|
bsw/jbe@1309
|
1206 forEl = document.getElementById(forElId);
|
bsw/jbe@1309
|
1207 if (forEl) {
|
bsw/jbe@1309
|
1208 this.forElement_ = forEl;
|
bsw/jbe@1309
|
1209 forEl.addEventListener('click', this.handleForClick_.bind(this));
|
bsw/jbe@1309
|
1210 forEl.addEventListener('keydown', this.handleForKeyboardEvent_.bind(this));
|
bsw/jbe@1309
|
1211 }
|
bsw/jbe@1309
|
1212 }
|
bsw/jbe@1309
|
1213 var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM);
|
bsw/jbe@1309
|
1214 this.boundItemKeydown_ = this.handleItemKeyboardEvent_.bind(this);
|
bsw/jbe@1309
|
1215 this.boundItemClick_ = this.handleItemClick_.bind(this);
|
bsw/jbe@1309
|
1216 for (var i = 0; i < items.length; i++) {
|
bsw/jbe@1309
|
1217 // Add a listener to each menu item.
|
bsw/jbe@1309
|
1218 items[i].addEventListener('click', this.boundItemClick_);
|
bsw/jbe@1309
|
1219 // Add a tab index to each menu item.
|
bsw/jbe@1309
|
1220 items[i].tabIndex = '-1';
|
bsw/jbe@1309
|
1221 // Add a keyboard listener to each menu item.
|
bsw/jbe@1309
|
1222 items[i].addEventListener('keydown', this.boundItemKeydown_);
|
bsw/jbe@1309
|
1223 }
|
bsw/jbe@1309
|
1224 // Add ripple classes to each item, if the user has enabled ripples.
|
bsw/jbe@1309
|
1225 if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
1226 this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
bsw/jbe@1309
|
1227 for (i = 0; i < items.length; i++) {
|
bsw/jbe@1309
|
1228 var item = items[i];
|
bsw/jbe@1309
|
1229 var rippleContainer = document.createElement('span');
|
bsw/jbe@1309
|
1230 rippleContainer.classList.add(this.CssClasses_.ITEM_RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
1231 var ripple = document.createElement('span');
|
bsw/jbe@1309
|
1232 ripple.classList.add(this.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
1233 rippleContainer.appendChild(ripple);
|
bsw/jbe@1309
|
1234 item.appendChild(rippleContainer);
|
bsw/jbe@1309
|
1235 item.classList.add(this.CssClasses_.RIPPLE_EFFECT);
|
bsw/jbe@1309
|
1236 }
|
bsw/jbe@1309
|
1237 }
|
bsw/jbe@1309
|
1238 // Copy alignment classes to the container, so the outline can use them.
|
bsw/jbe@1309
|
1239 if (this.element_.classList.contains(this.CssClasses_.BOTTOM_LEFT)) {
|
bsw/jbe@1309
|
1240 this.outline_.classList.add(this.CssClasses_.BOTTOM_LEFT);
|
bsw/jbe@1309
|
1241 }
|
bsw/jbe@1309
|
1242 if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) {
|
bsw/jbe@1309
|
1243 this.outline_.classList.add(this.CssClasses_.BOTTOM_RIGHT);
|
bsw/jbe@1309
|
1244 }
|
bsw/jbe@1309
|
1245 if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) {
|
bsw/jbe@1309
|
1246 this.outline_.classList.add(this.CssClasses_.TOP_LEFT);
|
bsw/jbe@1309
|
1247 }
|
bsw/jbe@1309
|
1248 if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) {
|
bsw/jbe@1309
|
1249 this.outline_.classList.add(this.CssClasses_.TOP_RIGHT);
|
bsw/jbe@1309
|
1250 }
|
bsw/jbe@1309
|
1251 if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) {
|
bsw/jbe@1309
|
1252 this.outline_.classList.add(this.CssClasses_.UNALIGNED);
|
bsw/jbe@1309
|
1253 }
|
bsw/jbe@1309
|
1254 container.classList.add(this.CssClasses_.IS_UPGRADED);
|
bsw/jbe@1309
|
1255 }
|
bsw/jbe@1309
|
1256 };
|
bsw/jbe@1309
|
1257 /**
|
bsw/jbe@1309
|
1258 * Handles a click on the "for" element, by positioning the menu and then
|
bsw/jbe@1309
|
1259 * toggling it.
|
bsw/jbe@1309
|
1260 *
|
bsw/jbe@1309
|
1261 * @param {Event} evt The event that fired.
|
bsw/jbe@1309
|
1262 * @private
|
bsw/jbe@1309
|
1263 */
|
bsw/jbe@1309
|
1264 MaterialMenu.prototype.handleForClick_ = function (evt) {
|
bsw/jbe@1309
|
1265 if (this.element_ && this.forElement_) {
|
bsw/jbe@1309
|
1266 var rect = this.forElement_.getBoundingClientRect();
|
bsw/jbe@1309
|
1267 var forRect = this.forElement_.parentElement.getBoundingClientRect();
|
bsw/jbe@1309
|
1268 if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) {
|
bsw/jbe@1309
|
1269 } else if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) {
|
bsw/jbe@1309
|
1270 // Position below the "for" element, aligned to its right.
|
bsw/jbe@1309
|
1271 this.container_.style.right = forRect.right - rect.right + 'px';
|
bsw/jbe@1309
|
1272 this.container_.style.top = this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px';
|
bsw/jbe@1309
|
1273 } else if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) {
|
bsw/jbe@1309
|
1274 // Position above the "for" element, aligned to its left.
|
bsw/jbe@1309
|
1275 this.container_.style.left = this.forElement_.offsetLeft + 'px';
|
bsw/jbe@1309
|
1276 this.container_.style.bottom = forRect.bottom - rect.top + 'px';
|
bsw/jbe@1309
|
1277 } else if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) {
|
bsw/jbe@1309
|
1278 // Position above the "for" element, aligned to its right.
|
bsw/jbe@1309
|
1279 this.container_.style.right = forRect.right - rect.right + 'px';
|
bsw/jbe@1309
|
1280 this.container_.style.bottom = forRect.bottom - rect.top + 'px';
|
bsw/jbe@1309
|
1281 } else {
|
bsw/jbe@1309
|
1282 // Default: position below the "for" element, aligned to its left.
|
bsw/jbe@1309
|
1283 this.container_.style.left = this.forElement_.offsetLeft + 'px';
|
bsw/jbe@1309
|
1284 this.container_.style.top = this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px';
|
bsw/jbe@1309
|
1285 }
|
bsw/jbe@1309
|
1286 }
|
bsw/jbe@1309
|
1287 this.toggle(evt);
|
bsw/jbe@1309
|
1288 };
|
bsw/jbe@1309
|
1289 /**
|
bsw/jbe@1309
|
1290 * Handles a keyboard event on the "for" element.
|
bsw/jbe@1309
|
1291 *
|
bsw/jbe@1309
|
1292 * @param {Event} evt The event that fired.
|
bsw/jbe@1309
|
1293 * @private
|
bsw/jbe@1309
|
1294 */
|
bsw/jbe@1309
|
1295 MaterialMenu.prototype.handleForKeyboardEvent_ = function (evt) {
|
bsw/jbe@1309
|
1296 if (this.element_ && this.container_ && this.forElement_) {
|
bsw/jbe@1309
|
1297 var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + ':not([disabled])');
|
bsw/jbe@1309
|
1298 if (items && items.length > 0 && this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) {
|
bsw/jbe@1309
|
1299 if (evt.keyCode === this.Keycodes_.UP_ARROW) {
|
bsw/jbe@1309
|
1300 evt.preventDefault();
|
bsw/jbe@1309
|
1301 items[items.length - 1].focus();
|
bsw/jbe@1309
|
1302 } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) {
|
bsw/jbe@1309
|
1303 evt.preventDefault();
|
bsw/jbe@1309
|
1304 items[0].focus();
|
bsw/jbe@1309
|
1305 }
|
bsw/jbe@1309
|
1306 }
|
bsw/jbe@1309
|
1307 }
|
bsw/jbe@1309
|
1308 };
|
bsw/jbe@1309
|
1309 /**
|
bsw/jbe@1309
|
1310 * Handles a keyboard event on an item.
|
bsw/jbe@1309
|
1311 *
|
bsw/jbe@1309
|
1312 * @param {Event} evt The event that fired.
|
bsw/jbe@1309
|
1313 * @private
|
bsw/jbe@1309
|
1314 */
|
bsw/jbe@1309
|
1315 MaterialMenu.prototype.handleItemKeyboardEvent_ = function (evt) {
|
bsw/jbe@1309
|
1316 if (this.element_ && this.container_) {
|
bsw/jbe@1309
|
1317 var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + ':not([disabled])');
|
bsw/jbe@1309
|
1318 if (items && items.length > 0 && this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) {
|
bsw/jbe@1309
|
1319 var currentIndex = Array.prototype.slice.call(items).indexOf(evt.target);
|
bsw/jbe@1309
|
1320 if (evt.keyCode === this.Keycodes_.UP_ARROW) {
|
bsw/jbe@1309
|
1321 evt.preventDefault();
|
bsw/jbe@1309
|
1322 if (currentIndex > 0) {
|
bsw/jbe@1309
|
1323 items[currentIndex - 1].focus();
|
bsw/jbe@1309
|
1324 } else {
|
bsw/jbe@1309
|
1325 items[items.length - 1].focus();
|
bsw/jbe@1309
|
1326 }
|
bsw/jbe@1309
|
1327 } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) {
|
bsw/jbe@1309
|
1328 evt.preventDefault();
|
bsw/jbe@1309
|
1329 if (items.length > currentIndex + 1) {
|
bsw/jbe@1309
|
1330 items[currentIndex + 1].focus();
|
bsw/jbe@1309
|
1331 } else {
|
bsw/jbe@1309
|
1332 items[0].focus();
|
bsw/jbe@1309
|
1333 }
|
bsw/jbe@1309
|
1334 } else if (evt.keyCode === this.Keycodes_.SPACE || evt.keyCode === this.Keycodes_.ENTER) {
|
bsw/jbe@1309
|
1335 evt.preventDefault();
|
bsw/jbe@1309
|
1336 // Send mousedown and mouseup to trigger ripple.
|
bsw/jbe@1309
|
1337 var e = new MouseEvent('mousedown');
|
bsw/jbe@1309
|
1338 evt.target.dispatchEvent(e);
|
bsw/jbe@1309
|
1339 e = new MouseEvent('mouseup');
|
bsw/jbe@1309
|
1340 evt.target.dispatchEvent(e);
|
bsw/jbe@1309
|
1341 // Send click.
|
bsw/jbe@1309
|
1342 evt.target.click();
|
bsw/jbe@1309
|
1343 } else if (evt.keyCode === this.Keycodes_.ESCAPE) {
|
bsw/jbe@1309
|
1344 evt.preventDefault();
|
bsw/jbe@1309
|
1345 this.hide();
|
bsw/jbe@1309
|
1346 }
|
bsw/jbe@1309
|
1347 }
|
bsw/jbe@1309
|
1348 }
|
bsw/jbe@1309
|
1349 };
|
bsw/jbe@1309
|
1350 /**
|
bsw/jbe@1309
|
1351 * Handles a click event on an item.
|
bsw/jbe@1309
|
1352 *
|
bsw/jbe@1309
|
1353 * @param {Event} evt The event that fired.
|
bsw/jbe@1309
|
1354 * @private
|
bsw/jbe@1309
|
1355 */
|
bsw/jbe@1309
|
1356 MaterialMenu.prototype.handleItemClick_ = function (evt) {
|
bsw/jbe@1309
|
1357 if (evt.target.hasAttribute('disabled')) {
|
bsw/jbe@1309
|
1358 evt.stopPropagation();
|
bsw/jbe@1309
|
1359 } else {
|
bsw/jbe@1309
|
1360 // Wait some time before closing menu, so the user can see the ripple.
|
bsw/jbe@1309
|
1361 this.closing_ = true;
|
bsw/jbe@1309
|
1362 window.setTimeout(function (evt) {
|
bsw/jbe@1309
|
1363 this.hide();
|
bsw/jbe@1309
|
1364 this.closing_ = false;
|
bsw/jbe@1309
|
1365 }.bind(this), this.Constant_.CLOSE_TIMEOUT);
|
bsw/jbe@1309
|
1366 }
|
bsw/jbe@1309
|
1367 };
|
bsw/jbe@1309
|
1368 /**
|
bsw/jbe@1309
|
1369 * Calculates the initial clip (for opening the menu) or final clip (for closing
|
bsw/jbe@1309
|
1370 * it), and applies it. This allows us to animate from or to the correct point,
|
bsw/jbe@1309
|
1371 * that is, the point it's aligned to in the "for" element.
|
bsw/jbe@1309
|
1372 *
|
bsw/jbe@1309
|
1373 * @param {number} height Height of the clip rectangle
|
bsw/jbe@1309
|
1374 * @param {number} width Width of the clip rectangle
|
bsw/jbe@1309
|
1375 * @private
|
bsw/jbe@1309
|
1376 */
|
bsw/jbe@1309
|
1377 MaterialMenu.prototype.applyClip_ = function (height, width) {
|
bsw/jbe@1309
|
1378 if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) {
|
bsw/jbe@1309
|
1379 // Do not clip.
|
bsw/jbe@1309
|
1380 this.element_.style.clip = '';
|
bsw/jbe@1309
|
1381 } else if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) {
|
bsw/jbe@1309
|
1382 // Clip to the top right corner of the menu.
|
bsw/jbe@1309
|
1383 this.element_.style.clip = 'rect(0 ' + width + 'px ' + '0 ' + width + 'px)';
|
bsw/jbe@1309
|
1384 } else if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) {
|
bsw/jbe@1309
|
1385 // Clip to the bottom left corner of the menu.
|
bsw/jbe@1309
|
1386 this.element_.style.clip = 'rect(' + height + 'px 0 ' + height + 'px 0)';
|
bsw/jbe@1309
|
1387 } else if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) {
|
bsw/jbe@1309
|
1388 // Clip to the bottom right corner of the menu.
|
bsw/jbe@1309
|
1389 this.element_.style.clip = 'rect(' + height + 'px ' + width + 'px ' + height + 'px ' + width + 'px)';
|
bsw/jbe@1309
|
1390 } else {
|
bsw/jbe@1309
|
1391 // Default: do not clip (same as clipping to the top left corner).
|
bsw/jbe@1309
|
1392 this.element_.style.clip = '';
|
bsw/jbe@1309
|
1393 }
|
bsw/jbe@1309
|
1394 };
|
bsw/jbe@1309
|
1395 /**
|
bsw/jbe@1309
|
1396 * Cleanup function to remove animation listeners.
|
bsw/jbe@1309
|
1397 *
|
bsw/jbe@1309
|
1398 * @param {Event} evt
|
bsw/jbe@1309
|
1399 * @private
|
bsw/jbe@1309
|
1400 */
|
bsw/jbe@1309
|
1401 MaterialMenu.prototype.removeAnimationEndListener_ = function (evt) {
|
bsw/jbe@1309
|
1402 evt.target.classList.remove(MaterialMenu.prototype.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
1403 };
|
bsw/jbe@1309
|
1404 /**
|
bsw/jbe@1309
|
1405 * Adds an event listener to clean up after the animation ends.
|
bsw/jbe@1309
|
1406 *
|
bsw/jbe@1309
|
1407 * @private
|
bsw/jbe@1309
|
1408 */
|
bsw/jbe@1309
|
1409 MaterialMenu.prototype.addAnimationEndListener_ = function () {
|
bsw/jbe@1309
|
1410 this.element_.addEventListener('transitionend', this.removeAnimationEndListener_);
|
bsw/jbe@1309
|
1411 this.element_.addEventListener('webkitTransitionEnd', this.removeAnimationEndListener_);
|
bsw/jbe@1309
|
1412 };
|
bsw/jbe@1309
|
1413 /**
|
bsw/jbe@1309
|
1414 * Displays the menu.
|
bsw/jbe@1309
|
1415 *
|
bsw/jbe@1309
|
1416 * @public
|
bsw/jbe@1309
|
1417 */
|
bsw/jbe@1309
|
1418 MaterialMenu.prototype.show = function (evt) {
|
bsw/jbe@1309
|
1419 if (this.element_ && this.container_ && this.outline_) {
|
bsw/jbe@1309
|
1420 // Measure the inner element.
|
bsw/jbe@1309
|
1421 var height = this.element_.getBoundingClientRect().height;
|
bsw/jbe@1309
|
1422 var width = this.element_.getBoundingClientRect().width;
|
bsw/jbe@1309
|
1423 // Apply the inner element's size to the container and outline.
|
bsw/jbe@1309
|
1424 this.container_.style.width = width + 'px';
|
bsw/jbe@1309
|
1425 this.container_.style.height = height + 'px';
|
bsw/jbe@1309
|
1426 this.outline_.style.width = width + 'px';
|
bsw/jbe@1309
|
1427 this.outline_.style.height = height + 'px';
|
bsw/jbe@1309
|
1428 var transitionDuration = this.Constant_.TRANSITION_DURATION_SECONDS * this.Constant_.TRANSITION_DURATION_FRACTION;
|
bsw/jbe@1309
|
1429 // Calculate transition delays for individual menu items, so that they fade
|
bsw/jbe@1309
|
1430 // in one at a time.
|
bsw/jbe@1309
|
1431 var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM);
|
bsw/jbe@1309
|
1432 for (var i = 0; i < items.length; i++) {
|
bsw/jbe@1309
|
1433 var itemDelay = null;
|
bsw/jbe@1309
|
1434 if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT) || this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) {
|
bsw/jbe@1309
|
1435 itemDelay = (height - items[i].offsetTop - items[i].offsetHeight) / height * transitionDuration + 's';
|
bsw/jbe@1309
|
1436 } else {
|
bsw/jbe@1309
|
1437 itemDelay = items[i].offsetTop / height * transitionDuration + 's';
|
bsw/jbe@1309
|
1438 }
|
bsw/jbe@1309
|
1439 items[i].style.transitionDelay = itemDelay;
|
bsw/jbe@1309
|
1440 }
|
bsw/jbe@1309
|
1441 // Apply the initial clip to the text before we start animating.
|
bsw/jbe@1309
|
1442 this.applyClip_(height, width);
|
bsw/jbe@1309
|
1443 // Wait for the next frame, turn on animation, and apply the final clip.
|
bsw/jbe@1309
|
1444 // Also make it visible. This triggers the transitions.
|
bsw/jbe@1309
|
1445 window.requestAnimationFrame(function () {
|
bsw/jbe@1309
|
1446 this.element_.classList.add(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
1447 this.element_.style.clip = 'rect(0 ' + width + 'px ' + height + 'px 0)';
|
bsw/jbe@1309
|
1448 this.container_.classList.add(this.CssClasses_.IS_VISIBLE);
|
bsw/jbe@1309
|
1449 }.bind(this));
|
bsw/jbe@1309
|
1450 // Clean up after the animation is complete.
|
bsw/jbe@1309
|
1451 this.addAnimationEndListener_();
|
bsw/jbe@1309
|
1452 // Add a click listener to the document, to close the menu.
|
bsw/jbe@1309
|
1453 var callback = function (e) {
|
bsw/jbe@1309
|
1454 // Check to see if the document is processing the same event that
|
bsw/jbe@1309
|
1455 // displayed the menu in the first place. If so, do nothing.
|
bsw/jbe@1309
|
1456 // Also check to see if the menu is in the process of closing itself, and
|
bsw/jbe@1309
|
1457 // do nothing in that case.
|
bsw/jbe@1309
|
1458 // Also check if the clicked element is a menu item
|
bsw/jbe@1309
|
1459 // if so, do nothing.
|
bsw/jbe@1309
|
1460 if (e !== evt && !this.closing_ && e.target.parentNode !== this.element_) {
|
bsw/jbe@1309
|
1461 document.removeEventListener('click', callback);
|
bsw/jbe@1309
|
1462 this.hide();
|
bsw/jbe@1309
|
1463 }
|
bsw/jbe@1309
|
1464 }.bind(this);
|
bsw/jbe@1309
|
1465 document.addEventListener('click', callback);
|
bsw/jbe@1309
|
1466 }
|
bsw/jbe@1309
|
1467 };
|
bsw/jbe@1309
|
1468 MaterialMenu.prototype['show'] = MaterialMenu.prototype.show;
|
bsw/jbe@1309
|
1469 /**
|
bsw/jbe@1309
|
1470 * Hides the menu.
|
bsw/jbe@1309
|
1471 *
|
bsw/jbe@1309
|
1472 * @public
|
bsw/jbe@1309
|
1473 */
|
bsw/jbe@1309
|
1474 MaterialMenu.prototype.hide = function () {
|
bsw/jbe@1309
|
1475 if (this.element_ && this.container_ && this.outline_) {
|
bsw/jbe@1309
|
1476 var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM);
|
bsw/jbe@1309
|
1477 // Remove all transition delays; menu items fade out concurrently.
|
bsw/jbe@1309
|
1478 for (var i = 0; i < items.length; i++) {
|
bsw/jbe@1309
|
1479 items[i].style.removeProperty('transition-delay');
|
bsw/jbe@1309
|
1480 }
|
bsw/jbe@1309
|
1481 // Measure the inner element.
|
bsw/jbe@1309
|
1482 var rect = this.element_.getBoundingClientRect();
|
bsw/jbe@1309
|
1483 var height = rect.height;
|
bsw/jbe@1309
|
1484 var width = rect.width;
|
bsw/jbe@1309
|
1485 // Turn on animation, and apply the final clip. Also make invisible.
|
bsw/jbe@1309
|
1486 // This triggers the transitions.
|
bsw/jbe@1309
|
1487 this.element_.classList.add(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
1488 this.applyClip_(height, width);
|
bsw/jbe@1309
|
1489 this.container_.classList.remove(this.CssClasses_.IS_VISIBLE);
|
bsw/jbe@1309
|
1490 // Clean up after the animation is complete.
|
bsw/jbe@1309
|
1491 this.addAnimationEndListener_();
|
bsw/jbe@1309
|
1492 }
|
bsw/jbe@1309
|
1493 };
|
bsw/jbe@1309
|
1494 MaterialMenu.prototype['hide'] = MaterialMenu.prototype.hide;
|
bsw/jbe@1309
|
1495 /**
|
bsw/jbe@1309
|
1496 * Displays or hides the menu, depending on current state.
|
bsw/jbe@1309
|
1497 *
|
bsw/jbe@1309
|
1498 * @public
|
bsw/jbe@1309
|
1499 */
|
bsw/jbe@1309
|
1500 MaterialMenu.prototype.toggle = function (evt) {
|
bsw/jbe@1309
|
1501 if (this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) {
|
bsw/jbe@1309
|
1502 this.hide();
|
bsw/jbe@1309
|
1503 } else {
|
bsw/jbe@1309
|
1504 this.show(evt);
|
bsw/jbe@1309
|
1505 }
|
bsw/jbe@1309
|
1506 };
|
bsw/jbe@1309
|
1507 MaterialMenu.prototype['toggle'] = MaterialMenu.prototype.toggle;
|
bsw/jbe@1309
|
1508 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
1509 // in the global scope.
|
bsw/jbe@1309
|
1510 componentHandler.register({
|
bsw/jbe@1309
|
1511 constructor: MaterialMenu,
|
bsw/jbe@1309
|
1512 classAsString: 'MaterialMenu',
|
bsw/jbe@1309
|
1513 cssClass: 'mdl-js-menu',
|
bsw/jbe@1309
|
1514 widget: true
|
bsw/jbe@1309
|
1515 });
|
bsw/jbe@1309
|
1516 /**
|
bsw/jbe@1309
|
1517 * @license
|
bsw/jbe@1309
|
1518 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
1519 *
|
bsw/jbe@1309
|
1520 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
1521 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
1522 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
1523 *
|
bsw/jbe@1309
|
1524 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
1525 *
|
bsw/jbe@1309
|
1526 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
1527 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
1528 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
1529 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
1530 * limitations under the License.
|
bsw/jbe@1309
|
1531 */
|
bsw/jbe@1309
|
1532 /**
|
bsw/jbe@1309
|
1533 * Class constructor for Progress MDL component.
|
bsw/jbe@1309
|
1534 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
1535 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
1536 *
|
bsw/jbe@1309
|
1537 * @constructor
|
bsw/jbe@1309
|
1538 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
1539 */
|
bsw/jbe@1309
|
1540 var MaterialProgress = function MaterialProgress(element) {
|
bsw/jbe@1309
|
1541 this.element_ = element;
|
bsw/jbe@1309
|
1542 // Initialize instance.
|
bsw/jbe@1309
|
1543 this.init();
|
bsw/jbe@1309
|
1544 };
|
bsw/jbe@1309
|
1545 window['MaterialProgress'] = MaterialProgress;
|
bsw/jbe@1309
|
1546 /**
|
bsw/jbe@1309
|
1547 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
1548 *
|
bsw/jbe@1309
|
1549 * @enum {string | number}
|
bsw/jbe@1309
|
1550 * @private
|
bsw/jbe@1309
|
1551 */
|
bsw/jbe@1309
|
1552 MaterialProgress.prototype.Constant_ = {};
|
bsw/jbe@1309
|
1553 /**
|
bsw/jbe@1309
|
1554 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
1555 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
1556 * decide to modify at a later date.
|
bsw/jbe@1309
|
1557 *
|
bsw/jbe@1309
|
1558 * @enum {string}
|
bsw/jbe@1309
|
1559 * @private
|
bsw/jbe@1309
|
1560 */
|
bsw/jbe@1309
|
1561 MaterialProgress.prototype.CssClasses_ = { INDETERMINATE_CLASS: 'mdl-progress__indeterminate' };
|
bsw/jbe@1309
|
1562 /**
|
bsw/jbe@1309
|
1563 * Set the current progress of the progressbar.
|
bsw/jbe@1309
|
1564 *
|
bsw/jbe@1309
|
1565 * @param {number} p Percentage of the progress (0-100)
|
bsw/jbe@1309
|
1566 * @public
|
bsw/jbe@1309
|
1567 */
|
bsw/jbe@1309
|
1568 MaterialProgress.prototype.setProgress = function (p) {
|
bsw/jbe@1309
|
1569 if (this.element_.classList.contains(this.CssClasses_.INDETERMINATE_CLASS)) {
|
bsw/jbe@1309
|
1570 return;
|
bsw/jbe@1309
|
1571 }
|
bsw/jbe@1309
|
1572 this.progressbar_.style.width = p + '%';
|
bsw/jbe@1309
|
1573 };
|
bsw/jbe@1309
|
1574 MaterialProgress.prototype['setProgress'] = MaterialProgress.prototype.setProgress;
|
bsw/jbe@1309
|
1575 /**
|
bsw/jbe@1309
|
1576 * Set the current progress of the buffer.
|
bsw/jbe@1309
|
1577 *
|
bsw/jbe@1309
|
1578 * @param {number} p Percentage of the buffer (0-100)
|
bsw/jbe@1309
|
1579 * @public
|
bsw/jbe@1309
|
1580 */
|
bsw/jbe@1309
|
1581 MaterialProgress.prototype.setBuffer = function (p) {
|
bsw/jbe@1309
|
1582 this.bufferbar_.style.width = p + '%';
|
bsw/jbe@1309
|
1583 this.auxbar_.style.width = 100 - p + '%';
|
bsw/jbe@1309
|
1584 };
|
bsw/jbe@1309
|
1585 MaterialProgress.prototype['setBuffer'] = MaterialProgress.prototype.setBuffer;
|
bsw/jbe@1309
|
1586 /**
|
bsw/jbe@1309
|
1587 * Initialize element.
|
bsw/jbe@1309
|
1588 */
|
bsw/jbe@1309
|
1589 MaterialProgress.prototype.init = function () {
|
bsw/jbe@1309
|
1590 if (this.element_) {
|
bsw/jbe@1309
|
1591 var el = document.createElement('div');
|
bsw/jbe@1309
|
1592 el.className = 'progressbar bar bar1';
|
bsw/jbe@1309
|
1593 this.element_.appendChild(el);
|
bsw/jbe@1309
|
1594 this.progressbar_ = el;
|
bsw/jbe@1309
|
1595 el = document.createElement('div');
|
bsw/jbe@1309
|
1596 el.className = 'bufferbar bar bar2';
|
bsw/jbe@1309
|
1597 this.element_.appendChild(el);
|
bsw/jbe@1309
|
1598 this.bufferbar_ = el;
|
bsw/jbe@1309
|
1599 el = document.createElement('div');
|
bsw/jbe@1309
|
1600 el.className = 'auxbar bar bar3';
|
bsw/jbe@1309
|
1601 this.element_.appendChild(el);
|
bsw/jbe@1309
|
1602 this.auxbar_ = el;
|
bsw/jbe@1309
|
1603 this.progressbar_.style.width = '0%';
|
bsw/jbe@1309
|
1604 this.bufferbar_.style.width = '100%';
|
bsw/jbe@1309
|
1605 this.auxbar_.style.width = '0%';
|
bsw/jbe@1309
|
1606 this.element_.classList.add('is-upgraded');
|
bsw/jbe@1309
|
1607 }
|
bsw/jbe@1309
|
1608 };
|
bsw/jbe@1309
|
1609 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
1610 // in the global scope.
|
bsw/jbe@1309
|
1611 componentHandler.register({
|
bsw/jbe@1309
|
1612 constructor: MaterialProgress,
|
bsw/jbe@1309
|
1613 classAsString: 'MaterialProgress',
|
bsw/jbe@1309
|
1614 cssClass: 'mdl-js-progress',
|
bsw/jbe@1309
|
1615 widget: true
|
bsw/jbe@1309
|
1616 });
|
bsw/jbe@1309
|
1617 /**
|
bsw/jbe@1309
|
1618 * @license
|
bsw/jbe@1309
|
1619 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
1620 *
|
bsw/jbe@1309
|
1621 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
1622 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
1623 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
1624 *
|
bsw/jbe@1309
|
1625 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
1626 *
|
bsw/jbe@1309
|
1627 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
1628 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
1629 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
1630 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
1631 * limitations under the License.
|
bsw/jbe@1309
|
1632 */
|
bsw/jbe@1309
|
1633 /**
|
bsw/jbe@1309
|
1634 * Class constructor for Radio MDL component.
|
bsw/jbe@1309
|
1635 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
1636 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
1637 *
|
bsw/jbe@1309
|
1638 * @constructor
|
bsw/jbe@1309
|
1639 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
1640 */
|
bsw/jbe@1309
|
1641 var MaterialRadio = function MaterialRadio(element) {
|
bsw/jbe@1309
|
1642 this.element_ = element;
|
bsw/jbe@1309
|
1643 // Initialize instance.
|
bsw/jbe@1309
|
1644 this.init();
|
bsw/jbe@1309
|
1645 };
|
bsw/jbe@1309
|
1646 window['MaterialRadio'] = MaterialRadio;
|
bsw/jbe@1309
|
1647 /**
|
bsw/jbe@1309
|
1648 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
1649 *
|
bsw/jbe@1309
|
1650 * @enum {string | number}
|
bsw/jbe@1309
|
1651 * @private
|
bsw/jbe@1309
|
1652 */
|
bsw/jbe@1309
|
1653 MaterialRadio.prototype.Constant_ = { TINY_TIMEOUT: 0.001 };
|
bsw/jbe@1309
|
1654 /**
|
bsw/jbe@1309
|
1655 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
1656 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
1657 * decide to modify at a later date.
|
bsw/jbe@1309
|
1658 *
|
bsw/jbe@1309
|
1659 * @enum {string}
|
bsw/jbe@1309
|
1660 * @private
|
bsw/jbe@1309
|
1661 */
|
bsw/jbe@1309
|
1662 MaterialRadio.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
1663 IS_FOCUSED: 'is-focused',
|
bsw/jbe@1309
|
1664 IS_DISABLED: 'is-disabled',
|
bsw/jbe@1309
|
1665 IS_CHECKED: 'is-checked',
|
bsw/jbe@1309
|
1666 IS_UPGRADED: 'is-upgraded',
|
bsw/jbe@1309
|
1667 JS_RADIO: 'mdl-js-radio',
|
bsw/jbe@1309
|
1668 RADIO_BTN: 'mdl-radio__button',
|
bsw/jbe@1309
|
1669 RADIO_OUTER_CIRCLE: 'mdl-radio__outer-circle',
|
bsw/jbe@1309
|
1670 RADIO_INNER_CIRCLE: 'mdl-radio__inner-circle',
|
bsw/jbe@1309
|
1671 RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
1672 RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
bsw/jbe@1309
|
1673 RIPPLE_CONTAINER: 'mdl-radio__ripple-container',
|
bsw/jbe@1309
|
1674 RIPPLE_CENTER: 'mdl-ripple--center',
|
bsw/jbe@1309
|
1675 RIPPLE: 'mdl-ripple'
|
bsw/jbe@1309
|
1676 };
|
bsw/jbe@1309
|
1677 /**
|
bsw/jbe@1309
|
1678 * Handle change of state.
|
bsw/jbe@1309
|
1679 *
|
bsw/jbe@1309
|
1680 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1681 * @private
|
bsw/jbe@1309
|
1682 */
|
bsw/jbe@1309
|
1683 MaterialRadio.prototype.onChange_ = function (event) {
|
bsw/jbe@1309
|
1684 // Since other radio buttons don't get change events, we need to look for
|
bsw/jbe@1309
|
1685 // them to update their classes.
|
bsw/jbe@1309
|
1686 var radios = document.getElementsByClassName(this.CssClasses_.JS_RADIO);
|
bsw/jbe@1309
|
1687 for (var i = 0; i < radios.length; i++) {
|
bsw/jbe@1309
|
1688 var button = radios[i].querySelector('.' + this.CssClasses_.RADIO_BTN);
|
bsw/jbe@1309
|
1689 // Different name == different group, so no point updating those.
|
bsw/jbe@1309
|
1690 if (button.getAttribute('name') === this.btnElement_.getAttribute('name')) {
|
bsw/jbe@1309
|
1691 radios[i]['MaterialRadio'].updateClasses_();
|
bsw/jbe@1309
|
1692 }
|
bsw/jbe@1309
|
1693 }
|
bsw/jbe@1309
|
1694 };
|
bsw/jbe@1309
|
1695 /**
|
bsw/jbe@1309
|
1696 * Handle focus.
|
bsw/jbe@1309
|
1697 *
|
bsw/jbe@1309
|
1698 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1699 * @private
|
bsw/jbe@1309
|
1700 */
|
bsw/jbe@1309
|
1701 MaterialRadio.prototype.onFocus_ = function (event) {
|
bsw/jbe@1309
|
1702 this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
1703 };
|
bsw/jbe@1309
|
1704 /**
|
bsw/jbe@1309
|
1705 * Handle lost focus.
|
bsw/jbe@1309
|
1706 *
|
bsw/jbe@1309
|
1707 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1708 * @private
|
bsw/jbe@1309
|
1709 */
|
bsw/jbe@1309
|
1710 MaterialRadio.prototype.onBlur_ = function (event) {
|
bsw/jbe@1309
|
1711 this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
1712 };
|
bsw/jbe@1309
|
1713 /**
|
bsw/jbe@1309
|
1714 * Handle mouseup.
|
bsw/jbe@1309
|
1715 *
|
bsw/jbe@1309
|
1716 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1717 * @private
|
bsw/jbe@1309
|
1718 */
|
bsw/jbe@1309
|
1719 MaterialRadio.prototype.onMouseup_ = function (event) {
|
bsw/jbe@1309
|
1720 this.blur_();
|
bsw/jbe@1309
|
1721 };
|
bsw/jbe@1309
|
1722 /**
|
bsw/jbe@1309
|
1723 * Update classes.
|
bsw/jbe@1309
|
1724 *
|
bsw/jbe@1309
|
1725 * @private
|
bsw/jbe@1309
|
1726 */
|
bsw/jbe@1309
|
1727 MaterialRadio.prototype.updateClasses_ = function () {
|
bsw/jbe@1309
|
1728 this.checkDisabled();
|
bsw/jbe@1309
|
1729 this.checkToggleState();
|
bsw/jbe@1309
|
1730 };
|
bsw/jbe@1309
|
1731 /**
|
bsw/jbe@1309
|
1732 * Add blur.
|
bsw/jbe@1309
|
1733 *
|
bsw/jbe@1309
|
1734 * @private
|
bsw/jbe@1309
|
1735 */
|
bsw/jbe@1309
|
1736 MaterialRadio.prototype.blur_ = function () {
|
bsw/jbe@1309
|
1737 // TODO: figure out why there's a focus event being fired after our blur,
|
bsw/jbe@1309
|
1738 // so that we can avoid this hack.
|
bsw/jbe@1309
|
1739 window.setTimeout(function () {
|
bsw/jbe@1309
|
1740 this.btnElement_.blur();
|
bsw/jbe@1309
|
1741 }.bind(this), this.Constant_.TINY_TIMEOUT);
|
bsw/jbe@1309
|
1742 };
|
bsw/jbe@1309
|
1743 // Public methods.
|
bsw/jbe@1309
|
1744 /**
|
bsw/jbe@1309
|
1745 * Check the components disabled state.
|
bsw/jbe@1309
|
1746 *
|
bsw/jbe@1309
|
1747 * @public
|
bsw/jbe@1309
|
1748 */
|
bsw/jbe@1309
|
1749 MaterialRadio.prototype.checkDisabled = function () {
|
bsw/jbe@1309
|
1750 if (this.btnElement_.disabled) {
|
bsw/jbe@1309
|
1751 this.element_.classList.add(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
1752 } else {
|
bsw/jbe@1309
|
1753 this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
1754 }
|
bsw/jbe@1309
|
1755 };
|
bsw/jbe@1309
|
1756 MaterialRadio.prototype['checkDisabled'] = MaterialRadio.prototype.checkDisabled;
|
bsw/jbe@1309
|
1757 /**
|
bsw/jbe@1309
|
1758 * Check the components toggled state.
|
bsw/jbe@1309
|
1759 *
|
bsw/jbe@1309
|
1760 * @public
|
bsw/jbe@1309
|
1761 */
|
bsw/jbe@1309
|
1762 MaterialRadio.prototype.checkToggleState = function () {
|
bsw/jbe@1309
|
1763 if (this.btnElement_.checked) {
|
bsw/jbe@1309
|
1764 this.element_.classList.add(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
1765 } else {
|
bsw/jbe@1309
|
1766 this.element_.classList.remove(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
1767 }
|
bsw/jbe@1309
|
1768 };
|
bsw/jbe@1309
|
1769 MaterialRadio.prototype['checkToggleState'] = MaterialRadio.prototype.checkToggleState;
|
bsw/jbe@1309
|
1770 /**
|
bsw/jbe@1309
|
1771 * Disable radio.
|
bsw/jbe@1309
|
1772 *
|
bsw/jbe@1309
|
1773 * @public
|
bsw/jbe@1309
|
1774 */
|
bsw/jbe@1309
|
1775 MaterialRadio.prototype.disable = function () {
|
bsw/jbe@1309
|
1776 this.btnElement_.disabled = true;
|
bsw/jbe@1309
|
1777 this.updateClasses_();
|
bsw/jbe@1309
|
1778 };
|
bsw/jbe@1309
|
1779 MaterialRadio.prototype['disable'] = MaterialRadio.prototype.disable;
|
bsw/jbe@1309
|
1780 /**
|
bsw/jbe@1309
|
1781 * Enable radio.
|
bsw/jbe@1309
|
1782 *
|
bsw/jbe@1309
|
1783 * @public
|
bsw/jbe@1309
|
1784 */
|
bsw/jbe@1309
|
1785 MaterialRadio.prototype.enable = function () {
|
bsw/jbe@1309
|
1786 this.btnElement_.disabled = false;
|
bsw/jbe@1309
|
1787 this.updateClasses_();
|
bsw/jbe@1309
|
1788 };
|
bsw/jbe@1309
|
1789 MaterialRadio.prototype['enable'] = MaterialRadio.prototype.enable;
|
bsw/jbe@1309
|
1790 /**
|
bsw/jbe@1309
|
1791 * Check radio.
|
bsw/jbe@1309
|
1792 *
|
bsw/jbe@1309
|
1793 * @public
|
bsw/jbe@1309
|
1794 */
|
bsw/jbe@1309
|
1795 MaterialRadio.prototype.check = function () {
|
bsw/jbe@1309
|
1796 this.btnElement_.checked = true;
|
bsw/jbe@1309
|
1797 this.onChange_(null);
|
bsw/jbe@1309
|
1798 };
|
bsw/jbe@1309
|
1799 MaterialRadio.prototype['check'] = MaterialRadio.prototype.check;
|
bsw/jbe@1309
|
1800 /**
|
bsw/jbe@1309
|
1801 * Uncheck radio.
|
bsw/jbe@1309
|
1802 *
|
bsw/jbe@1309
|
1803 * @public
|
bsw/jbe@1309
|
1804 */
|
bsw/jbe@1309
|
1805 MaterialRadio.prototype.uncheck = function () {
|
bsw/jbe@1309
|
1806 this.btnElement_.checked = false;
|
bsw/jbe@1309
|
1807 this.onChange_(null);
|
bsw/jbe@1309
|
1808 };
|
bsw/jbe@1309
|
1809 MaterialRadio.prototype['uncheck'] = MaterialRadio.prototype.uncheck;
|
bsw/jbe@1309
|
1810 /**
|
bsw/jbe@1309
|
1811 * Initialize element.
|
bsw/jbe@1309
|
1812 */
|
bsw/jbe@1309
|
1813 MaterialRadio.prototype.init = function () {
|
bsw/jbe@1309
|
1814 if (this.element_) {
|
bsw/jbe@1309
|
1815 this.btnElement_ = this.element_.querySelector('.' + this.CssClasses_.RADIO_BTN);
|
bsw/jbe@1309
|
1816 this.boundChangeHandler_ = this.onChange_.bind(this);
|
bsw/jbe@1309
|
1817 this.boundFocusHandler_ = this.onChange_.bind(this);
|
bsw/jbe@1309
|
1818 this.boundBlurHandler_ = this.onBlur_.bind(this);
|
bsw/jbe@1309
|
1819 this.boundMouseUpHandler_ = this.onMouseup_.bind(this);
|
bsw/jbe@1309
|
1820 var outerCircle = document.createElement('span');
|
bsw/jbe@1309
|
1821 outerCircle.classList.add(this.CssClasses_.RADIO_OUTER_CIRCLE);
|
bsw/jbe@1309
|
1822 var innerCircle = document.createElement('span');
|
bsw/jbe@1309
|
1823 innerCircle.classList.add(this.CssClasses_.RADIO_INNER_CIRCLE);
|
bsw/jbe@1309
|
1824 this.element_.appendChild(outerCircle);
|
bsw/jbe@1309
|
1825 this.element_.appendChild(innerCircle);
|
bsw/jbe@1309
|
1826 var rippleContainer;
|
bsw/jbe@1309
|
1827 if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
1828 this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
bsw/jbe@1309
|
1829 rippleContainer = document.createElement('span');
|
bsw/jbe@1309
|
1830 rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
1831 rippleContainer.classList.add(this.CssClasses_.RIPPLE_EFFECT);
|
bsw/jbe@1309
|
1832 rippleContainer.classList.add(this.CssClasses_.RIPPLE_CENTER);
|
bsw/jbe@1309
|
1833 rippleContainer.addEventListener('mouseup', this.boundMouseUpHandler_);
|
bsw/jbe@1309
|
1834 var ripple = document.createElement('span');
|
bsw/jbe@1309
|
1835 ripple.classList.add(this.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
1836 rippleContainer.appendChild(ripple);
|
bsw/jbe@1309
|
1837 this.element_.appendChild(rippleContainer);
|
bsw/jbe@1309
|
1838 }
|
bsw/jbe@1309
|
1839 this.btnElement_.addEventListener('change', this.boundChangeHandler_);
|
bsw/jbe@1309
|
1840 this.btnElement_.addEventListener('focus', this.boundFocusHandler_);
|
bsw/jbe@1309
|
1841 this.btnElement_.addEventListener('blur', this.boundBlurHandler_);
|
bsw/jbe@1309
|
1842 this.element_.addEventListener('mouseup', this.boundMouseUpHandler_);
|
bsw/jbe@1309
|
1843 this.updateClasses_();
|
bsw/jbe@1309
|
1844 this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
|
bsw/jbe@1309
|
1845 }
|
bsw/jbe@1309
|
1846 };
|
bsw/jbe@1309
|
1847 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
1848 // in the global scope.
|
bsw/jbe@1309
|
1849 componentHandler.register({
|
bsw/jbe@1309
|
1850 constructor: MaterialRadio,
|
bsw/jbe@1309
|
1851 classAsString: 'MaterialRadio',
|
bsw/jbe@1309
|
1852 cssClass: 'mdl-js-radio',
|
bsw/jbe@1309
|
1853 widget: true
|
bsw/jbe@1309
|
1854 });
|
bsw/jbe@1309
|
1855 /**
|
bsw/jbe@1309
|
1856 * @license
|
bsw/jbe@1309
|
1857 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
1858 *
|
bsw/jbe@1309
|
1859 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
1860 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
1861 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
1862 *
|
bsw/jbe@1309
|
1863 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
1864 *
|
bsw/jbe@1309
|
1865 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
1866 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
1867 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
1868 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
1869 * limitations under the License.
|
bsw/jbe@1309
|
1870 */
|
bsw/jbe@1309
|
1871 /**
|
bsw/jbe@1309
|
1872 * Class constructor for Slider MDL component.
|
bsw/jbe@1309
|
1873 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
1874 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
1875 *
|
bsw/jbe@1309
|
1876 * @constructor
|
bsw/jbe@1309
|
1877 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
1878 */
|
bsw/jbe@1309
|
1879 var MaterialSlider = function MaterialSlider(element) {
|
bsw/jbe@1309
|
1880 this.element_ = element;
|
bsw/jbe@1309
|
1881 // Browser feature detection.
|
bsw/jbe@1309
|
1882 this.isIE_ = window.navigator.msPointerEnabled;
|
bsw/jbe@1309
|
1883 // Initialize instance.
|
bsw/jbe@1309
|
1884 this.init();
|
bsw/jbe@1309
|
1885 };
|
bsw/jbe@1309
|
1886 window['MaterialSlider'] = MaterialSlider;
|
bsw/jbe@1309
|
1887 /**
|
bsw/jbe@1309
|
1888 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
1889 *
|
bsw/jbe@1309
|
1890 * @enum {string | number}
|
bsw/jbe@1309
|
1891 * @private
|
bsw/jbe@1309
|
1892 */
|
bsw/jbe@1309
|
1893 MaterialSlider.prototype.Constant_ = {};
|
bsw/jbe@1309
|
1894 /**
|
bsw/jbe@1309
|
1895 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
1896 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
1897 * decide to modify at a later date.
|
bsw/jbe@1309
|
1898 *
|
bsw/jbe@1309
|
1899 * @enum {string}
|
bsw/jbe@1309
|
1900 * @private
|
bsw/jbe@1309
|
1901 */
|
bsw/jbe@1309
|
1902 MaterialSlider.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
1903 IE_CONTAINER: 'mdl-slider__ie-container',
|
bsw/jbe@1309
|
1904 SLIDER_CONTAINER: 'mdl-slider__container',
|
bsw/jbe@1309
|
1905 BACKGROUND_FLEX: 'mdl-slider__background-flex',
|
bsw/jbe@1309
|
1906 BACKGROUND_LOWER: 'mdl-slider__background-lower',
|
bsw/jbe@1309
|
1907 BACKGROUND_UPPER: 'mdl-slider__background-upper',
|
bsw/jbe@1309
|
1908 IS_LOWEST_VALUE: 'is-lowest-value',
|
bsw/jbe@1309
|
1909 IS_UPGRADED: 'is-upgraded'
|
bsw/jbe@1309
|
1910 };
|
bsw/jbe@1309
|
1911 /**
|
bsw/jbe@1309
|
1912 * Handle input on element.
|
bsw/jbe@1309
|
1913 *
|
bsw/jbe@1309
|
1914 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1915 * @private
|
bsw/jbe@1309
|
1916 */
|
bsw/jbe@1309
|
1917 MaterialSlider.prototype.onInput_ = function (event) {
|
bsw/jbe@1309
|
1918 this.updateValueStyles_();
|
bsw/jbe@1309
|
1919 };
|
bsw/jbe@1309
|
1920 /**
|
bsw/jbe@1309
|
1921 * Handle change on element.
|
bsw/jbe@1309
|
1922 *
|
bsw/jbe@1309
|
1923 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1924 * @private
|
bsw/jbe@1309
|
1925 */
|
bsw/jbe@1309
|
1926 MaterialSlider.prototype.onChange_ = function (event) {
|
bsw/jbe@1309
|
1927 this.updateValueStyles_();
|
bsw/jbe@1309
|
1928 };
|
bsw/jbe@1309
|
1929 /**
|
bsw/jbe@1309
|
1930 * Handle mouseup on element.
|
bsw/jbe@1309
|
1931 *
|
bsw/jbe@1309
|
1932 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1933 * @private
|
bsw/jbe@1309
|
1934 */
|
bsw/jbe@1309
|
1935 MaterialSlider.prototype.onMouseUp_ = function (event) {
|
bsw/jbe@1309
|
1936 event.target.blur();
|
bsw/jbe@1309
|
1937 };
|
bsw/jbe@1309
|
1938 /**
|
bsw/jbe@1309
|
1939 * Handle mousedown on container element.
|
bsw/jbe@1309
|
1940 * This handler is purpose is to not require the use to click
|
bsw/jbe@1309
|
1941 * exactly on the 2px slider element, as FireFox seems to be very
|
bsw/jbe@1309
|
1942 * strict about this.
|
bsw/jbe@1309
|
1943 *
|
bsw/jbe@1309
|
1944 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
1945 * @private
|
bsw/jbe@1309
|
1946 * @suppress {missingProperties}
|
bsw/jbe@1309
|
1947 */
|
bsw/jbe@1309
|
1948 MaterialSlider.prototype.onContainerMouseDown_ = function (event) {
|
bsw/jbe@1309
|
1949 // If this click is not on the parent element (but rather some child)
|
bsw/jbe@1309
|
1950 // ignore. It may still bubble up.
|
bsw/jbe@1309
|
1951 if (event.target !== this.element_.parentElement) {
|
bsw/jbe@1309
|
1952 return;
|
bsw/jbe@1309
|
1953 }
|
bsw/jbe@1309
|
1954 // Discard the original event and create a new event that
|
bsw/jbe@1309
|
1955 // is on the slider element.
|
bsw/jbe@1309
|
1956 event.preventDefault();
|
bsw/jbe@1309
|
1957 var newEvent = new MouseEvent('mousedown', {
|
bsw/jbe@1309
|
1958 target: event.target,
|
bsw/jbe@1309
|
1959 buttons: event.buttons,
|
bsw/jbe@1309
|
1960 clientX: event.clientX,
|
bsw/jbe@1309
|
1961 clientY: this.element_.getBoundingClientRect().y
|
bsw/jbe@1309
|
1962 });
|
bsw/jbe@1309
|
1963 this.element_.dispatchEvent(newEvent);
|
bsw/jbe@1309
|
1964 };
|
bsw/jbe@1309
|
1965 /**
|
bsw/jbe@1309
|
1966 * Handle updating of values.
|
bsw/jbe@1309
|
1967 *
|
bsw/jbe@1309
|
1968 * @private
|
bsw/jbe@1309
|
1969 */
|
bsw/jbe@1309
|
1970 MaterialSlider.prototype.updateValueStyles_ = function () {
|
bsw/jbe@1309
|
1971 // Calculate and apply percentages to div structure behind slider.
|
bsw/jbe@1309
|
1972 var fraction = (this.element_.value - this.element_.min) / (this.element_.max - this.element_.min);
|
bsw/jbe@1309
|
1973 if (fraction === 0) {
|
bsw/jbe@1309
|
1974 this.element_.classList.add(this.CssClasses_.IS_LOWEST_VALUE);
|
bsw/jbe@1309
|
1975 } else {
|
bsw/jbe@1309
|
1976 this.element_.classList.remove(this.CssClasses_.IS_LOWEST_VALUE);
|
bsw/jbe@1309
|
1977 }
|
bsw/jbe@1309
|
1978 if (!this.isIE_) {
|
bsw/jbe@1309
|
1979 this.backgroundLower_.style.flex = fraction;
|
bsw/jbe@1309
|
1980 this.backgroundLower_.style.webkitFlex = fraction;
|
bsw/jbe@1309
|
1981 this.backgroundUpper_.style.flex = 1 - fraction;
|
bsw/jbe@1309
|
1982 this.backgroundUpper_.style.webkitFlex = 1 - fraction;
|
bsw/jbe@1309
|
1983 }
|
bsw/jbe@1309
|
1984 };
|
bsw/jbe@1309
|
1985 // Public methods.
|
bsw/jbe@1309
|
1986 /**
|
bsw/jbe@1309
|
1987 * Disable slider.
|
bsw/jbe@1309
|
1988 *
|
bsw/jbe@1309
|
1989 * @public
|
bsw/jbe@1309
|
1990 */
|
bsw/jbe@1309
|
1991 MaterialSlider.prototype.disable = function () {
|
bsw/jbe@1309
|
1992 this.element_.disabled = true;
|
bsw/jbe@1309
|
1993 };
|
bsw/jbe@1309
|
1994 MaterialSlider.prototype['disable'] = MaterialSlider.prototype.disable;
|
bsw/jbe@1309
|
1995 /**
|
bsw/jbe@1309
|
1996 * Enable slider.
|
bsw/jbe@1309
|
1997 *
|
bsw/jbe@1309
|
1998 * @public
|
bsw/jbe@1309
|
1999 */
|
bsw/jbe@1309
|
2000 MaterialSlider.prototype.enable = function () {
|
bsw/jbe@1309
|
2001 this.element_.disabled = false;
|
bsw/jbe@1309
|
2002 };
|
bsw/jbe@1309
|
2003 MaterialSlider.prototype['enable'] = MaterialSlider.prototype.enable;
|
bsw/jbe@1309
|
2004 /**
|
bsw/jbe@1309
|
2005 * Update slider value.
|
bsw/jbe@1309
|
2006 *
|
bsw/jbe@1309
|
2007 * @param {number} value The value to which to set the control (optional).
|
bsw/jbe@1309
|
2008 * @public
|
bsw/jbe@1309
|
2009 */
|
bsw/jbe@1309
|
2010 MaterialSlider.prototype.change = function (value) {
|
bsw/jbe@1309
|
2011 if (typeof value !== 'undefined') {
|
bsw/jbe@1309
|
2012 this.element_.value = value;
|
bsw/jbe@1309
|
2013 }
|
bsw/jbe@1309
|
2014 this.updateValueStyles_();
|
bsw/jbe@1309
|
2015 };
|
bsw/jbe@1309
|
2016 MaterialSlider.prototype['change'] = MaterialSlider.prototype.change;
|
bsw/jbe@1309
|
2017 /**
|
bsw/jbe@1309
|
2018 * Initialize element.
|
bsw/jbe@1309
|
2019 */
|
bsw/jbe@1309
|
2020 MaterialSlider.prototype.init = function () {
|
bsw/jbe@1309
|
2021 if (this.element_) {
|
bsw/jbe@1309
|
2022 if (this.isIE_) {
|
bsw/jbe@1309
|
2023 // Since we need to specify a very large height in IE due to
|
bsw/jbe@1309
|
2024 // implementation limitations, we add a parent here that trims it down to
|
bsw/jbe@1309
|
2025 // a reasonable size.
|
bsw/jbe@1309
|
2026 var containerIE = document.createElement('div');
|
bsw/jbe@1309
|
2027 containerIE.classList.add(this.CssClasses_.IE_CONTAINER);
|
bsw/jbe@1309
|
2028 this.element_.parentElement.insertBefore(containerIE, this.element_);
|
bsw/jbe@1309
|
2029 this.element_.parentElement.removeChild(this.element_);
|
bsw/jbe@1309
|
2030 containerIE.appendChild(this.element_);
|
bsw/jbe@1309
|
2031 } else {
|
bsw/jbe@1309
|
2032 // For non-IE browsers, we need a div structure that sits behind the
|
bsw/jbe@1309
|
2033 // slider and allows us to style the left and right sides of it with
|
bsw/jbe@1309
|
2034 // different colors.
|
bsw/jbe@1309
|
2035 var container = document.createElement('div');
|
bsw/jbe@1309
|
2036 container.classList.add(this.CssClasses_.SLIDER_CONTAINER);
|
bsw/jbe@1309
|
2037 this.element_.parentElement.insertBefore(container, this.element_);
|
bsw/jbe@1309
|
2038 this.element_.parentElement.removeChild(this.element_);
|
bsw/jbe@1309
|
2039 container.appendChild(this.element_);
|
bsw/jbe@1309
|
2040 var backgroundFlex = document.createElement('div');
|
bsw/jbe@1309
|
2041 backgroundFlex.classList.add(this.CssClasses_.BACKGROUND_FLEX);
|
bsw/jbe@1309
|
2042 container.appendChild(backgroundFlex);
|
bsw/jbe@1309
|
2043 this.backgroundLower_ = document.createElement('div');
|
bsw/jbe@1309
|
2044 this.backgroundLower_.classList.add(this.CssClasses_.BACKGROUND_LOWER);
|
bsw/jbe@1309
|
2045 backgroundFlex.appendChild(this.backgroundLower_);
|
bsw/jbe@1309
|
2046 this.backgroundUpper_ = document.createElement('div');
|
bsw/jbe@1309
|
2047 this.backgroundUpper_.classList.add(this.CssClasses_.BACKGROUND_UPPER);
|
bsw/jbe@1309
|
2048 backgroundFlex.appendChild(this.backgroundUpper_);
|
bsw/jbe@1309
|
2049 }
|
bsw/jbe@1309
|
2050 this.boundInputHandler = this.onInput_.bind(this);
|
bsw/jbe@1309
|
2051 this.boundChangeHandler = this.onChange_.bind(this);
|
bsw/jbe@1309
|
2052 this.boundMouseUpHandler = this.onMouseUp_.bind(this);
|
bsw/jbe@1309
|
2053 this.boundContainerMouseDownHandler = this.onContainerMouseDown_.bind(this);
|
bsw/jbe@1309
|
2054 this.element_.addEventListener('input', this.boundInputHandler);
|
bsw/jbe@1309
|
2055 this.element_.addEventListener('change', this.boundChangeHandler);
|
bsw/jbe@1309
|
2056 this.element_.addEventListener('mouseup', this.boundMouseUpHandler);
|
bsw/jbe@1309
|
2057 this.element_.parentElement.addEventListener('mousedown', this.boundContainerMouseDownHandler);
|
bsw/jbe@1309
|
2058 this.updateValueStyles_();
|
bsw/jbe@1309
|
2059 this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
|
bsw/jbe@1309
|
2060 }
|
bsw/jbe@1309
|
2061 };
|
bsw/jbe@1309
|
2062 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
2063 // in the global scope.
|
bsw/jbe@1309
|
2064 componentHandler.register({
|
bsw/jbe@1309
|
2065 constructor: MaterialSlider,
|
bsw/jbe@1309
|
2066 classAsString: 'MaterialSlider',
|
bsw/jbe@1309
|
2067 cssClass: 'mdl-js-slider',
|
bsw/jbe@1309
|
2068 widget: true
|
bsw/jbe@1309
|
2069 });
|
bsw/jbe@1309
|
2070 /**
|
bsw/jbe@1309
|
2071 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
2072 *
|
bsw/jbe@1309
|
2073 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
2074 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
2075 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
2076 *
|
bsw/jbe@1309
|
2077 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
2078 *
|
bsw/jbe@1309
|
2079 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
2080 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
2081 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
2082 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
2083 * limitations under the License.
|
bsw/jbe@1309
|
2084 */
|
bsw/jbe@1309
|
2085 /**
|
bsw/jbe@1309
|
2086 * Class constructor for Snackbar MDL component.
|
bsw/jbe@1309
|
2087 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
2088 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
2089 *
|
bsw/jbe@1309
|
2090 * @constructor
|
bsw/jbe@1309
|
2091 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
2092 */
|
bsw/jbe@1309
|
2093 var MaterialSnackbar = function MaterialSnackbar(element) {
|
bsw/jbe@1309
|
2094 this.element_ = element;
|
bsw/jbe@1309
|
2095 this.textElement_ = this.element_.querySelector('.' + this.cssClasses_.MESSAGE);
|
bsw/jbe@1309
|
2096 this.actionElement_ = this.element_.querySelector('.' + this.cssClasses_.ACTION);
|
bsw/jbe@1309
|
2097 if (!this.textElement_) {
|
bsw/jbe@1309
|
2098 throw new Error('There must be a message element for a snackbar.');
|
bsw/jbe@1309
|
2099 }
|
bsw/jbe@1309
|
2100 if (!this.actionElement_) {
|
bsw/jbe@1309
|
2101 throw new Error('There must be an action element for a snackbar.');
|
bsw/jbe@1309
|
2102 }
|
bsw/jbe@1309
|
2103 this.active = false;
|
bsw/jbe@1309
|
2104 this.actionHandler_ = undefined;
|
bsw/jbe@1309
|
2105 this.message_ = undefined;
|
bsw/jbe@1309
|
2106 this.actionText_ = undefined;
|
bsw/jbe@1309
|
2107 this.queuedNotifications_ = [];
|
bsw/jbe@1309
|
2108 this.setActionHidden_(true);
|
bsw/jbe@1309
|
2109 };
|
bsw/jbe@1309
|
2110 window['MaterialSnackbar'] = MaterialSnackbar;
|
bsw/jbe@1309
|
2111 /**
|
bsw/jbe@1309
|
2112 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
2113 *
|
bsw/jbe@1309
|
2114 * @enum {string | number}
|
bsw/jbe@1309
|
2115 * @private
|
bsw/jbe@1309
|
2116 */
|
bsw/jbe@1309
|
2117 MaterialSnackbar.prototype.Constant_ = {
|
bsw/jbe@1309
|
2118 // The duration of the snackbar show/hide animation, in ms.
|
bsw/jbe@1309
|
2119 ANIMATION_LENGTH: 250
|
bsw/jbe@1309
|
2120 };
|
bsw/jbe@1309
|
2121 /**
|
bsw/jbe@1309
|
2122 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
2123 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
2124 * decide to modify at a later date.
|
bsw/jbe@1309
|
2125 *
|
bsw/jbe@1309
|
2126 * @enum {string}
|
bsw/jbe@1309
|
2127 * @private
|
bsw/jbe@1309
|
2128 */
|
bsw/jbe@1309
|
2129 MaterialSnackbar.prototype.cssClasses_ = {
|
bsw/jbe@1309
|
2130 SNACKBAR: 'mdl-snackbar',
|
bsw/jbe@1309
|
2131 MESSAGE: 'mdl-snackbar__text',
|
bsw/jbe@1309
|
2132 ACTION: 'mdl-snackbar__action',
|
bsw/jbe@1309
|
2133 ACTIVE: 'mdl-snackbar--active'
|
bsw/jbe@1309
|
2134 };
|
bsw/jbe@1309
|
2135 /**
|
bsw/jbe@1309
|
2136 * Display the snackbar.
|
bsw/jbe@1309
|
2137 *
|
bsw/jbe@1309
|
2138 * @private
|
bsw/jbe@1309
|
2139 */
|
bsw/jbe@1309
|
2140 MaterialSnackbar.prototype.displaySnackbar_ = function () {
|
bsw/jbe@1309
|
2141 this.element_.setAttribute('aria-hidden', 'true');
|
bsw/jbe@1309
|
2142 if (this.actionHandler_) {
|
bsw/jbe@1309
|
2143 this.actionElement_.textContent = this.actionText_;
|
bsw/jbe@1309
|
2144 this.actionElement_.addEventListener('click', this.actionHandler_);
|
bsw/jbe@1309
|
2145 this.setActionHidden_(false);
|
bsw/jbe@1309
|
2146 }
|
bsw/jbe@1309
|
2147 this.textElement_.textContent = this.message_;
|
bsw/jbe@1309
|
2148 this.element_.classList.add(this.cssClasses_.ACTIVE);
|
bsw/jbe@1309
|
2149 this.element_.setAttribute('aria-hidden', 'false');
|
bsw/jbe@1309
|
2150 setTimeout(this.cleanup_.bind(this), this.timeout_);
|
bsw/jbe@1309
|
2151 };
|
bsw/jbe@1309
|
2152 /**
|
bsw/jbe@1309
|
2153 * Show the snackbar.
|
bsw/jbe@1309
|
2154 *
|
bsw/jbe@1309
|
2155 * @param {Object} data The data for the notification.
|
bsw/jbe@1309
|
2156 * @public
|
bsw/jbe@1309
|
2157 */
|
bsw/jbe@1309
|
2158 MaterialSnackbar.prototype.showSnackbar = function (data) {
|
bsw/jbe@1309
|
2159 if (data === undefined) {
|
bsw/jbe@1309
|
2160 throw new Error('Please provide a data object with at least a message to display.');
|
bsw/jbe@1309
|
2161 }
|
bsw/jbe@1309
|
2162 if (data['message'] === undefined) {
|
bsw/jbe@1309
|
2163 throw new Error('Please provide a message to be displayed.');
|
bsw/jbe@1309
|
2164 }
|
bsw/jbe@1309
|
2165 if (data['actionHandler'] && !data['actionText']) {
|
bsw/jbe@1309
|
2166 throw new Error('Please provide action text with the handler.');
|
bsw/jbe@1309
|
2167 }
|
bsw/jbe@1309
|
2168 if (this.active) {
|
bsw/jbe@1309
|
2169 this.queuedNotifications_.push(data);
|
bsw/jbe@1309
|
2170 } else {
|
bsw/jbe@1309
|
2171 this.active = true;
|
bsw/jbe@1309
|
2172 this.message_ = data['message'];
|
bsw/jbe@1309
|
2173 if (data['timeout']) {
|
bsw/jbe@1309
|
2174 this.timeout_ = data['timeout'];
|
bsw/jbe@1309
|
2175 } else {
|
bsw/jbe@1309
|
2176 this.timeout_ = 2750;
|
bsw/jbe@1309
|
2177 }
|
bsw/jbe@1309
|
2178 if (data['actionHandler']) {
|
bsw/jbe@1309
|
2179 this.actionHandler_ = data['actionHandler'];
|
bsw/jbe@1309
|
2180 }
|
bsw/jbe@1309
|
2181 if (data['actionText']) {
|
bsw/jbe@1309
|
2182 this.actionText_ = data['actionText'];
|
bsw/jbe@1309
|
2183 }
|
bsw/jbe@1309
|
2184 this.displaySnackbar_();
|
bsw/jbe@1309
|
2185 }
|
bsw/jbe@1309
|
2186 };
|
bsw/jbe@1309
|
2187 MaterialSnackbar.prototype['showSnackbar'] = MaterialSnackbar.prototype.showSnackbar;
|
bsw/jbe@1309
|
2188 /**
|
bsw/jbe@1309
|
2189 * Check if the queue has items within it.
|
bsw/jbe@1309
|
2190 * If it does, display the next entry.
|
bsw/jbe@1309
|
2191 *
|
bsw/jbe@1309
|
2192 * @private
|
bsw/jbe@1309
|
2193 */
|
bsw/jbe@1309
|
2194 MaterialSnackbar.prototype.checkQueue_ = function () {
|
bsw/jbe@1309
|
2195 if (this.queuedNotifications_.length > 0) {
|
bsw/jbe@1309
|
2196 this.showSnackbar(this.queuedNotifications_.shift());
|
bsw/jbe@1309
|
2197 }
|
bsw/jbe@1309
|
2198 };
|
bsw/jbe@1309
|
2199 /**
|
bsw/jbe@1309
|
2200 * Cleanup the snackbar event listeners and accessiblity attributes.
|
bsw/jbe@1309
|
2201 *
|
bsw/jbe@1309
|
2202 * @private
|
bsw/jbe@1309
|
2203 */
|
bsw/jbe@1309
|
2204 MaterialSnackbar.prototype.cleanup_ = function () {
|
bsw/jbe@1309
|
2205 this.element_.classList.remove(this.cssClasses_.ACTIVE);
|
bsw/jbe@1309
|
2206 setTimeout(function () {
|
bsw/jbe@1309
|
2207 this.element_.setAttribute('aria-hidden', 'true');
|
bsw/jbe@1309
|
2208 this.textElement_.textContent = '';
|
bsw/jbe@1309
|
2209 if (!Boolean(this.actionElement_.getAttribute('aria-hidden'))) {
|
bsw/jbe@1309
|
2210 this.setActionHidden_(true);
|
bsw/jbe@1309
|
2211 this.actionElement_.textContent = '';
|
bsw/jbe@1309
|
2212 this.actionElement_.removeEventListener('click', this.actionHandler_);
|
bsw/jbe@1309
|
2213 }
|
bsw/jbe@1309
|
2214 this.actionHandler_ = undefined;
|
bsw/jbe@1309
|
2215 this.message_ = undefined;
|
bsw/jbe@1309
|
2216 this.actionText_ = undefined;
|
bsw/jbe@1309
|
2217 this.active = false;
|
bsw/jbe@1309
|
2218 this.checkQueue_();
|
bsw/jbe@1309
|
2219 }.bind(this), this.Constant_.ANIMATION_LENGTH);
|
bsw/jbe@1309
|
2220 };
|
bsw/jbe@1309
|
2221 /**
|
bsw/jbe@1309
|
2222 * Set the action handler hidden state.
|
bsw/jbe@1309
|
2223 *
|
bsw/jbe@1309
|
2224 * @param {boolean} value
|
bsw/jbe@1309
|
2225 * @private
|
bsw/jbe@1309
|
2226 */
|
bsw/jbe@1309
|
2227 MaterialSnackbar.prototype.setActionHidden_ = function (value) {
|
bsw/jbe@1309
|
2228 if (value) {
|
bsw/jbe@1309
|
2229 this.actionElement_.setAttribute('aria-hidden', 'true');
|
bsw/jbe@1309
|
2230 } else {
|
bsw/jbe@1309
|
2231 this.actionElement_.removeAttribute('aria-hidden');
|
bsw/jbe@1309
|
2232 }
|
bsw/jbe@1309
|
2233 };
|
bsw/jbe@1309
|
2234 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
2235 // in the global scope.
|
bsw/jbe@1309
|
2236 componentHandler.register({
|
bsw/jbe@1309
|
2237 constructor: MaterialSnackbar,
|
bsw/jbe@1309
|
2238 classAsString: 'MaterialSnackbar',
|
bsw/jbe@1309
|
2239 cssClass: 'mdl-js-snackbar',
|
bsw/jbe@1309
|
2240 widget: true
|
bsw/jbe@1309
|
2241 });
|
bsw/jbe@1309
|
2242 /**
|
bsw/jbe@1309
|
2243 * @license
|
bsw/jbe@1309
|
2244 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
2245 *
|
bsw/jbe@1309
|
2246 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
2247 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
2248 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
2249 *
|
bsw/jbe@1309
|
2250 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
2251 *
|
bsw/jbe@1309
|
2252 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
2253 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
2254 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
2255 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
2256 * limitations under the License.
|
bsw/jbe@1309
|
2257 */
|
bsw/jbe@1309
|
2258 /**
|
bsw/jbe@1309
|
2259 * Class constructor for Spinner MDL component.
|
bsw/jbe@1309
|
2260 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
2261 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
2262 *
|
bsw/jbe@1309
|
2263 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
2264 * @constructor
|
bsw/jbe@1309
|
2265 */
|
bsw/jbe@1309
|
2266 var MaterialSpinner = function MaterialSpinner(element) {
|
bsw/jbe@1309
|
2267 this.element_ = element;
|
bsw/jbe@1309
|
2268 // Initialize instance.
|
bsw/jbe@1309
|
2269 this.init();
|
bsw/jbe@1309
|
2270 };
|
bsw/jbe@1309
|
2271 window['MaterialSpinner'] = MaterialSpinner;
|
bsw/jbe@1309
|
2272 /**
|
bsw/jbe@1309
|
2273 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
2274 *
|
bsw/jbe@1309
|
2275 * @enum {string | number}
|
bsw/jbe@1309
|
2276 * @private
|
bsw/jbe@1309
|
2277 */
|
bsw/jbe@1309
|
2278 MaterialSpinner.prototype.Constant_ = { MDL_SPINNER_LAYER_COUNT: 4 };
|
bsw/jbe@1309
|
2279 /**
|
bsw/jbe@1309
|
2280 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
2281 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
2282 * decide to modify at a later date.
|
bsw/jbe@1309
|
2283 *
|
bsw/jbe@1309
|
2284 * @enum {string}
|
bsw/jbe@1309
|
2285 * @private
|
bsw/jbe@1309
|
2286 */
|
bsw/jbe@1309
|
2287 MaterialSpinner.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
2288 MDL_SPINNER_LAYER: 'mdl-spinner__layer',
|
bsw/jbe@1309
|
2289 MDL_SPINNER_CIRCLE_CLIPPER: 'mdl-spinner__circle-clipper',
|
bsw/jbe@1309
|
2290 MDL_SPINNER_CIRCLE: 'mdl-spinner__circle',
|
bsw/jbe@1309
|
2291 MDL_SPINNER_GAP_PATCH: 'mdl-spinner__gap-patch',
|
bsw/jbe@1309
|
2292 MDL_SPINNER_LEFT: 'mdl-spinner__left',
|
bsw/jbe@1309
|
2293 MDL_SPINNER_RIGHT: 'mdl-spinner__right'
|
bsw/jbe@1309
|
2294 };
|
bsw/jbe@1309
|
2295 /**
|
bsw/jbe@1309
|
2296 * Auxiliary method to create a spinner layer.
|
bsw/jbe@1309
|
2297 *
|
bsw/jbe@1309
|
2298 * @param {number} index Index of the layer to be created.
|
bsw/jbe@1309
|
2299 * @public
|
bsw/jbe@1309
|
2300 */
|
bsw/jbe@1309
|
2301 MaterialSpinner.prototype.createLayer = function (index) {
|
bsw/jbe@1309
|
2302 var layer = document.createElement('div');
|
bsw/jbe@1309
|
2303 layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER);
|
bsw/jbe@1309
|
2304 layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER + '-' + index);
|
bsw/jbe@1309
|
2305 var leftClipper = document.createElement('div');
|
bsw/jbe@1309
|
2306 leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER);
|
bsw/jbe@1309
|
2307 leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_LEFT);
|
bsw/jbe@1309
|
2308 var gapPatch = document.createElement('div');
|
bsw/jbe@1309
|
2309 gapPatch.classList.add(this.CssClasses_.MDL_SPINNER_GAP_PATCH);
|
bsw/jbe@1309
|
2310 var rightClipper = document.createElement('div');
|
bsw/jbe@1309
|
2311 rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER);
|
bsw/jbe@1309
|
2312 rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_RIGHT);
|
bsw/jbe@1309
|
2313 var circleOwners = [
|
bsw/jbe@1309
|
2314 leftClipper,
|
bsw/jbe@1309
|
2315 gapPatch,
|
bsw/jbe@1309
|
2316 rightClipper
|
bsw/jbe@1309
|
2317 ];
|
bsw/jbe@1309
|
2318 for (var i = 0; i < circleOwners.length; i++) {
|
bsw/jbe@1309
|
2319 var circle = document.createElement('div');
|
bsw/jbe@1309
|
2320 circle.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE);
|
bsw/jbe@1309
|
2321 circleOwners[i].appendChild(circle);
|
bsw/jbe@1309
|
2322 }
|
bsw/jbe@1309
|
2323 layer.appendChild(leftClipper);
|
bsw/jbe@1309
|
2324 layer.appendChild(gapPatch);
|
bsw/jbe@1309
|
2325 layer.appendChild(rightClipper);
|
bsw/jbe@1309
|
2326 this.element_.appendChild(layer);
|
bsw/jbe@1309
|
2327 };
|
bsw/jbe@1309
|
2328 MaterialSpinner.prototype['createLayer'] = MaterialSpinner.prototype.createLayer;
|
bsw/jbe@1309
|
2329 /**
|
bsw/jbe@1309
|
2330 * Stops the spinner animation.
|
bsw/jbe@1309
|
2331 * Public method for users who need to stop the spinner for any reason.
|
bsw/jbe@1309
|
2332 *
|
bsw/jbe@1309
|
2333 * @public
|
bsw/jbe@1309
|
2334 */
|
bsw/jbe@1309
|
2335 MaterialSpinner.prototype.stop = function () {
|
bsw/jbe@1309
|
2336 this.element_.classList.remove('is-active');
|
bsw/jbe@1309
|
2337 };
|
bsw/jbe@1309
|
2338 MaterialSpinner.prototype['stop'] = MaterialSpinner.prototype.stop;
|
bsw/jbe@1309
|
2339 /**
|
bsw/jbe@1309
|
2340 * Starts the spinner animation.
|
bsw/jbe@1309
|
2341 * Public method for users who need to manually start the spinner for any reason
|
bsw/jbe@1309
|
2342 * (instead of just adding the 'is-active' class to their markup).
|
bsw/jbe@1309
|
2343 *
|
bsw/jbe@1309
|
2344 * @public
|
bsw/jbe@1309
|
2345 */
|
bsw/jbe@1309
|
2346 MaterialSpinner.prototype.start = function () {
|
bsw/jbe@1309
|
2347 this.element_.classList.add('is-active');
|
bsw/jbe@1309
|
2348 };
|
bsw/jbe@1309
|
2349 MaterialSpinner.prototype['start'] = MaterialSpinner.prototype.start;
|
bsw/jbe@1309
|
2350 /**
|
bsw/jbe@1309
|
2351 * Initialize element.
|
bsw/jbe@1309
|
2352 */
|
bsw/jbe@1309
|
2353 MaterialSpinner.prototype.init = function () {
|
bsw/jbe@1309
|
2354 if (this.element_) {
|
bsw/jbe@1309
|
2355 for (var i = 1; i <= this.Constant_.MDL_SPINNER_LAYER_COUNT; i++) {
|
bsw/jbe@1309
|
2356 this.createLayer(i);
|
bsw/jbe@1309
|
2357 }
|
bsw/jbe@1309
|
2358 this.element_.classList.add('is-upgraded');
|
bsw/jbe@1309
|
2359 }
|
bsw/jbe@1309
|
2360 };
|
bsw/jbe@1309
|
2361 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
2362 // in the global scope.
|
bsw/jbe@1309
|
2363 componentHandler.register({
|
bsw/jbe@1309
|
2364 constructor: MaterialSpinner,
|
bsw/jbe@1309
|
2365 classAsString: 'MaterialSpinner',
|
bsw/jbe@1309
|
2366 cssClass: 'mdl-js-spinner',
|
bsw/jbe@1309
|
2367 widget: true
|
bsw/jbe@1309
|
2368 });
|
bsw/jbe@1309
|
2369 /**
|
bsw/jbe@1309
|
2370 * @license
|
bsw/jbe@1309
|
2371 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
2372 *
|
bsw/jbe@1309
|
2373 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
2374 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
2375 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
2376 *
|
bsw/jbe@1309
|
2377 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
2378 *
|
bsw/jbe@1309
|
2379 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
2380 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
2381 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
2382 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
2383 * limitations under the License.
|
bsw/jbe@1309
|
2384 */
|
bsw/jbe@1309
|
2385 /**
|
bsw/jbe@1309
|
2386 * Class constructor for Checkbox MDL component.
|
bsw/jbe@1309
|
2387 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
2388 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
2389 *
|
bsw/jbe@1309
|
2390 * @constructor
|
bsw/jbe@1309
|
2391 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
2392 */
|
bsw/jbe@1309
|
2393 var MaterialSwitch = function MaterialSwitch(element) {
|
bsw/jbe@1309
|
2394 this.element_ = element;
|
bsw/jbe@1309
|
2395 // Initialize instance.
|
bsw/jbe@1309
|
2396 this.init();
|
bsw/jbe@1309
|
2397 };
|
bsw/jbe@1309
|
2398 window['MaterialSwitch'] = MaterialSwitch;
|
bsw/jbe@1309
|
2399 /**
|
bsw/jbe@1309
|
2400 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
2401 *
|
bsw/jbe@1309
|
2402 * @enum {string | number}
|
bsw/jbe@1309
|
2403 * @private
|
bsw/jbe@1309
|
2404 */
|
bsw/jbe@1309
|
2405 MaterialSwitch.prototype.Constant_ = { TINY_TIMEOUT: 0.001 };
|
bsw/jbe@1309
|
2406 /**
|
bsw/jbe@1309
|
2407 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
2408 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
2409 * decide to modify at a later date.
|
bsw/jbe@1309
|
2410 *
|
bsw/jbe@1309
|
2411 * @enum {string}
|
bsw/jbe@1309
|
2412 * @private
|
bsw/jbe@1309
|
2413 */
|
bsw/jbe@1309
|
2414 MaterialSwitch.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
2415 INPUT: 'mdl-switch__input',
|
bsw/jbe@1309
|
2416 TRACK: 'mdl-switch__track',
|
bsw/jbe@1309
|
2417 THUMB: 'mdl-switch__thumb',
|
bsw/jbe@1309
|
2418 FOCUS_HELPER: 'mdl-switch__focus-helper',
|
bsw/jbe@1309
|
2419 RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
2420 RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
bsw/jbe@1309
|
2421 RIPPLE_CONTAINER: 'mdl-switch__ripple-container',
|
bsw/jbe@1309
|
2422 RIPPLE_CENTER: 'mdl-ripple--center',
|
bsw/jbe@1309
|
2423 RIPPLE: 'mdl-ripple',
|
bsw/jbe@1309
|
2424 IS_FOCUSED: 'is-focused',
|
bsw/jbe@1309
|
2425 IS_DISABLED: 'is-disabled',
|
bsw/jbe@1309
|
2426 IS_CHECKED: 'is-checked'
|
bsw/jbe@1309
|
2427 };
|
bsw/jbe@1309
|
2428 /**
|
bsw/jbe@1309
|
2429 * Handle change of state.
|
bsw/jbe@1309
|
2430 *
|
bsw/jbe@1309
|
2431 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2432 * @private
|
bsw/jbe@1309
|
2433 */
|
bsw/jbe@1309
|
2434 MaterialSwitch.prototype.onChange_ = function (event) {
|
bsw/jbe@1309
|
2435 this.updateClasses_();
|
bsw/jbe@1309
|
2436 };
|
bsw/jbe@1309
|
2437 /**
|
bsw/jbe@1309
|
2438 * Handle focus of element.
|
bsw/jbe@1309
|
2439 *
|
bsw/jbe@1309
|
2440 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2441 * @private
|
bsw/jbe@1309
|
2442 */
|
bsw/jbe@1309
|
2443 MaterialSwitch.prototype.onFocus_ = function (event) {
|
bsw/jbe@1309
|
2444 this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
2445 };
|
bsw/jbe@1309
|
2446 /**
|
bsw/jbe@1309
|
2447 * Handle lost focus of element.
|
bsw/jbe@1309
|
2448 *
|
bsw/jbe@1309
|
2449 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2450 * @private
|
bsw/jbe@1309
|
2451 */
|
bsw/jbe@1309
|
2452 MaterialSwitch.prototype.onBlur_ = function (event) {
|
bsw/jbe@1309
|
2453 this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
2454 };
|
bsw/jbe@1309
|
2455 /**
|
bsw/jbe@1309
|
2456 * Handle mouseup.
|
bsw/jbe@1309
|
2457 *
|
bsw/jbe@1309
|
2458 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2459 * @private
|
bsw/jbe@1309
|
2460 */
|
bsw/jbe@1309
|
2461 MaterialSwitch.prototype.onMouseUp_ = function (event) {
|
bsw/jbe@1309
|
2462 this.blur_();
|
bsw/jbe@1309
|
2463 };
|
bsw/jbe@1309
|
2464 /**
|
bsw/jbe@1309
|
2465 * Handle class updates.
|
bsw/jbe@1309
|
2466 *
|
bsw/jbe@1309
|
2467 * @private
|
bsw/jbe@1309
|
2468 */
|
bsw/jbe@1309
|
2469 MaterialSwitch.prototype.updateClasses_ = function () {
|
bsw/jbe@1309
|
2470 this.checkDisabled();
|
bsw/jbe@1309
|
2471 this.checkToggleState();
|
bsw/jbe@1309
|
2472 };
|
bsw/jbe@1309
|
2473 /**
|
bsw/jbe@1309
|
2474 * Add blur.
|
bsw/jbe@1309
|
2475 *
|
bsw/jbe@1309
|
2476 * @private
|
bsw/jbe@1309
|
2477 */
|
bsw/jbe@1309
|
2478 MaterialSwitch.prototype.blur_ = function () {
|
bsw/jbe@1309
|
2479 // TODO: figure out why there's a focus event being fired after our blur,
|
bsw/jbe@1309
|
2480 // so that we can avoid this hack.
|
bsw/jbe@1309
|
2481 window.setTimeout(function () {
|
bsw/jbe@1309
|
2482 this.inputElement_.blur();
|
bsw/jbe@1309
|
2483 }.bind(this), this.Constant_.TINY_TIMEOUT);
|
bsw/jbe@1309
|
2484 };
|
bsw/jbe@1309
|
2485 // Public methods.
|
bsw/jbe@1309
|
2486 /**
|
bsw/jbe@1309
|
2487 * Check the components disabled state.
|
bsw/jbe@1309
|
2488 *
|
bsw/jbe@1309
|
2489 * @public
|
bsw/jbe@1309
|
2490 */
|
bsw/jbe@1309
|
2491 MaterialSwitch.prototype.checkDisabled = function () {
|
bsw/jbe@1309
|
2492 if (this.inputElement_.disabled) {
|
bsw/jbe@1309
|
2493 this.element_.classList.add(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
2494 } else {
|
bsw/jbe@1309
|
2495 this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
2496 }
|
bsw/jbe@1309
|
2497 };
|
bsw/jbe@1309
|
2498 MaterialSwitch.prototype['checkDisabled'] = MaterialSwitch.prototype.checkDisabled;
|
bsw/jbe@1309
|
2499 /**
|
bsw/jbe@1309
|
2500 * Check the components toggled state.
|
bsw/jbe@1309
|
2501 *
|
bsw/jbe@1309
|
2502 * @public
|
bsw/jbe@1309
|
2503 */
|
bsw/jbe@1309
|
2504 MaterialSwitch.prototype.checkToggleState = function () {
|
bsw/jbe@1309
|
2505 if (this.inputElement_.checked) {
|
bsw/jbe@1309
|
2506 this.element_.classList.add(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
2507 } else {
|
bsw/jbe@1309
|
2508 this.element_.classList.remove(this.CssClasses_.IS_CHECKED);
|
bsw/jbe@1309
|
2509 }
|
bsw/jbe@1309
|
2510 };
|
bsw/jbe@1309
|
2511 MaterialSwitch.prototype['checkToggleState'] = MaterialSwitch.prototype.checkToggleState;
|
bsw/jbe@1309
|
2512 /**
|
bsw/jbe@1309
|
2513 * Disable switch.
|
bsw/jbe@1309
|
2514 *
|
bsw/jbe@1309
|
2515 * @public
|
bsw/jbe@1309
|
2516 */
|
bsw/jbe@1309
|
2517 MaterialSwitch.prototype.disable = function () {
|
bsw/jbe@1309
|
2518 this.inputElement_.disabled = true;
|
bsw/jbe@1309
|
2519 this.updateClasses_();
|
bsw/jbe@1309
|
2520 };
|
bsw/jbe@1309
|
2521 MaterialSwitch.prototype['disable'] = MaterialSwitch.prototype.disable;
|
bsw/jbe@1309
|
2522 /**
|
bsw/jbe@1309
|
2523 * Enable switch.
|
bsw/jbe@1309
|
2524 *
|
bsw/jbe@1309
|
2525 * @public
|
bsw/jbe@1309
|
2526 */
|
bsw/jbe@1309
|
2527 MaterialSwitch.prototype.enable = function () {
|
bsw/jbe@1309
|
2528 this.inputElement_.disabled = false;
|
bsw/jbe@1309
|
2529 this.updateClasses_();
|
bsw/jbe@1309
|
2530 };
|
bsw/jbe@1309
|
2531 MaterialSwitch.prototype['enable'] = MaterialSwitch.prototype.enable;
|
bsw/jbe@1309
|
2532 /**
|
bsw/jbe@1309
|
2533 * Activate switch.
|
bsw/jbe@1309
|
2534 *
|
bsw/jbe@1309
|
2535 * @public
|
bsw/jbe@1309
|
2536 */
|
bsw/jbe@1309
|
2537 MaterialSwitch.prototype.on = function () {
|
bsw/jbe@1309
|
2538 this.inputElement_.checked = true;
|
bsw/jbe@1309
|
2539 this.updateClasses_();
|
bsw/jbe@1309
|
2540 };
|
bsw/jbe@1309
|
2541 MaterialSwitch.prototype['on'] = MaterialSwitch.prototype.on;
|
bsw/jbe@1309
|
2542 /**
|
bsw/jbe@1309
|
2543 * Deactivate switch.
|
bsw/jbe@1309
|
2544 *
|
bsw/jbe@1309
|
2545 * @public
|
bsw/jbe@1309
|
2546 */
|
bsw/jbe@1309
|
2547 MaterialSwitch.prototype.off = function () {
|
bsw/jbe@1309
|
2548 this.inputElement_.checked = false;
|
bsw/jbe@1309
|
2549 this.updateClasses_();
|
bsw/jbe@1309
|
2550 };
|
bsw/jbe@1309
|
2551 MaterialSwitch.prototype['off'] = MaterialSwitch.prototype.off;
|
bsw/jbe@1309
|
2552 /**
|
bsw/jbe@1309
|
2553 * Initialize element.
|
bsw/jbe@1309
|
2554 */
|
bsw/jbe@1309
|
2555 MaterialSwitch.prototype.init = function () {
|
bsw/jbe@1309
|
2556 if (this.element_) {
|
bsw/jbe@1309
|
2557 this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT);
|
bsw/jbe@1309
|
2558 var track = document.createElement('div');
|
bsw/jbe@1309
|
2559 track.classList.add(this.CssClasses_.TRACK);
|
bsw/jbe@1309
|
2560 var thumb = document.createElement('div');
|
bsw/jbe@1309
|
2561 thumb.classList.add(this.CssClasses_.THUMB);
|
bsw/jbe@1309
|
2562 var focusHelper = document.createElement('span');
|
bsw/jbe@1309
|
2563 focusHelper.classList.add(this.CssClasses_.FOCUS_HELPER);
|
bsw/jbe@1309
|
2564 thumb.appendChild(focusHelper);
|
bsw/jbe@1309
|
2565 this.element_.appendChild(track);
|
bsw/jbe@1309
|
2566 this.element_.appendChild(thumb);
|
bsw/jbe@1309
|
2567 this.boundMouseUpHandler = this.onMouseUp_.bind(this);
|
bsw/jbe@1309
|
2568 if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
2569 this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
bsw/jbe@1309
|
2570 this.rippleContainerElement_ = document.createElement('span');
|
bsw/jbe@1309
|
2571 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
2572 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT);
|
bsw/jbe@1309
|
2573 this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER);
|
bsw/jbe@1309
|
2574 this.rippleContainerElement_.addEventListener('mouseup', this.boundMouseUpHandler);
|
bsw/jbe@1309
|
2575 var ripple = document.createElement('span');
|
bsw/jbe@1309
|
2576 ripple.classList.add(this.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
2577 this.rippleContainerElement_.appendChild(ripple);
|
bsw/jbe@1309
|
2578 this.element_.appendChild(this.rippleContainerElement_);
|
bsw/jbe@1309
|
2579 }
|
bsw/jbe@1309
|
2580 this.boundChangeHandler = this.onChange_.bind(this);
|
bsw/jbe@1309
|
2581 this.boundFocusHandler = this.onFocus_.bind(this);
|
bsw/jbe@1309
|
2582 this.boundBlurHandler = this.onBlur_.bind(this);
|
bsw/jbe@1309
|
2583 this.inputElement_.addEventListener('change', this.boundChangeHandler);
|
bsw/jbe@1309
|
2584 this.inputElement_.addEventListener('focus', this.boundFocusHandler);
|
bsw/jbe@1309
|
2585 this.inputElement_.addEventListener('blur', this.boundBlurHandler);
|
bsw/jbe@1309
|
2586 this.element_.addEventListener('mouseup', this.boundMouseUpHandler);
|
bsw/jbe@1309
|
2587 this.updateClasses_();
|
bsw/jbe@1309
|
2588 this.element_.classList.add('is-upgraded');
|
bsw/jbe@1309
|
2589 }
|
bsw/jbe@1309
|
2590 };
|
bsw/jbe@1309
|
2591 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
2592 // in the global scope.
|
bsw/jbe@1309
|
2593 componentHandler.register({
|
bsw/jbe@1309
|
2594 constructor: MaterialSwitch,
|
bsw/jbe@1309
|
2595 classAsString: 'MaterialSwitch',
|
bsw/jbe@1309
|
2596 cssClass: 'mdl-js-switch',
|
bsw/jbe@1309
|
2597 widget: true
|
bsw/jbe@1309
|
2598 });
|
bsw/jbe@1309
|
2599 /**
|
bsw/jbe@1309
|
2600 * @license
|
bsw/jbe@1309
|
2601 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
2602 *
|
bsw/jbe@1309
|
2603 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
2604 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
2605 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
2606 *
|
bsw/jbe@1309
|
2607 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
2608 *
|
bsw/jbe@1309
|
2609 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
2610 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
2611 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
2612 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
2613 * limitations under the License.
|
bsw/jbe@1309
|
2614 */
|
bsw/jbe@1309
|
2615 /**
|
bsw/jbe@1309
|
2616 * Class constructor for Tabs MDL component.
|
bsw/jbe@1309
|
2617 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
2618 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
2619 *
|
bsw/jbe@1309
|
2620 * @constructor
|
bsw/jbe@1309
|
2621 * @param {Element} element The element that will be upgraded.
|
bsw/jbe@1309
|
2622 */
|
bsw/jbe@1309
|
2623 var MaterialTabs = function MaterialTabs(element) {
|
bsw/jbe@1309
|
2624 // Stores the HTML element.
|
bsw/jbe@1309
|
2625 this.element_ = element;
|
bsw/jbe@1309
|
2626 // Initialize instance.
|
bsw/jbe@1309
|
2627 this.init();
|
bsw/jbe@1309
|
2628 };
|
bsw/jbe@1309
|
2629 window['MaterialTabs'] = MaterialTabs;
|
bsw/jbe@1309
|
2630 /**
|
bsw/jbe@1309
|
2631 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
2632 *
|
bsw/jbe@1309
|
2633 * @enum {string}
|
bsw/jbe@1309
|
2634 * @private
|
bsw/jbe@1309
|
2635 */
|
bsw/jbe@1309
|
2636 MaterialTabs.prototype.Constant_ = {};
|
bsw/jbe@1309
|
2637 /**
|
bsw/jbe@1309
|
2638 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
2639 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
2640 * decide to modify at a later date.
|
bsw/jbe@1309
|
2641 *
|
bsw/jbe@1309
|
2642 * @enum {string}
|
bsw/jbe@1309
|
2643 * @private
|
bsw/jbe@1309
|
2644 */
|
bsw/jbe@1309
|
2645 MaterialTabs.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
2646 TAB_CLASS: 'mdl-tabs__tab',
|
bsw/jbe@1309
|
2647 PANEL_CLASS: 'mdl-tabs__panel',
|
bsw/jbe@1309
|
2648 ACTIVE_CLASS: 'is-active',
|
bsw/jbe@1309
|
2649 UPGRADED_CLASS: 'is-upgraded',
|
bsw/jbe@1309
|
2650 MDL_JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
2651 MDL_RIPPLE_CONTAINER: 'mdl-tabs__ripple-container',
|
bsw/jbe@1309
|
2652 MDL_RIPPLE: 'mdl-ripple',
|
bsw/jbe@1309
|
2653 MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events'
|
bsw/jbe@1309
|
2654 };
|
bsw/jbe@1309
|
2655 /**
|
bsw/jbe@1309
|
2656 * Handle clicks to a tabs component
|
bsw/jbe@1309
|
2657 *
|
bsw/jbe@1309
|
2658 * @private
|
bsw/jbe@1309
|
2659 */
|
bsw/jbe@1309
|
2660 MaterialTabs.prototype.initTabs_ = function () {
|
bsw/jbe@1309
|
2661 if (this.element_.classList.contains(this.CssClasses_.MDL_JS_RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
2662 this.element_.classList.add(this.CssClasses_.MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS);
|
bsw/jbe@1309
|
2663 }
|
bsw/jbe@1309
|
2664 // Select element tabs, document panels
|
bsw/jbe@1309
|
2665 this.tabs_ = this.element_.querySelectorAll('.' + this.CssClasses_.TAB_CLASS);
|
bsw/jbe@1309
|
2666 this.panels_ = this.element_.querySelectorAll('.' + this.CssClasses_.PANEL_CLASS);
|
bsw/jbe@1309
|
2667 // Create new tabs for each tab element
|
bsw/jbe@1309
|
2668 for (var i = 0; i < this.tabs_.length; i++) {
|
bsw/jbe@1309
|
2669 new MaterialTab(this.tabs_[i], this);
|
bsw/jbe@1309
|
2670 }
|
bsw/jbe@1309
|
2671 this.element_.classList.add(this.CssClasses_.UPGRADED_CLASS);
|
bsw/jbe@1309
|
2672 };
|
bsw/jbe@1309
|
2673 /**
|
bsw/jbe@1309
|
2674 * Reset tab state, dropping active classes
|
bsw/jbe@1309
|
2675 *
|
bsw/jbe@1309
|
2676 * @private
|
bsw/jbe@1309
|
2677 */
|
bsw/jbe@1309
|
2678 MaterialTabs.prototype.resetTabState_ = function () {
|
bsw/jbe@1309
|
2679 for (var k = 0; k < this.tabs_.length; k++) {
|
bsw/jbe@1309
|
2680 this.tabs_[k].classList.remove(this.CssClasses_.ACTIVE_CLASS);
|
bsw/jbe@1309
|
2681 }
|
bsw/jbe@1309
|
2682 };
|
bsw/jbe@1309
|
2683 /**
|
bsw/jbe@1309
|
2684 * Reset panel state, droping active classes
|
bsw/jbe@1309
|
2685 *
|
bsw/jbe@1309
|
2686 * @private
|
bsw/jbe@1309
|
2687 */
|
bsw/jbe@1309
|
2688 MaterialTabs.prototype.resetPanelState_ = function () {
|
bsw/jbe@1309
|
2689 for (var j = 0; j < this.panels_.length; j++) {
|
bsw/jbe@1309
|
2690 this.panels_[j].classList.remove(this.CssClasses_.ACTIVE_CLASS);
|
bsw/jbe@1309
|
2691 }
|
bsw/jbe@1309
|
2692 };
|
bsw/jbe@1309
|
2693 /**
|
bsw/jbe@1309
|
2694 * Initialize element.
|
bsw/jbe@1309
|
2695 */
|
bsw/jbe@1309
|
2696 MaterialTabs.prototype.init = function () {
|
bsw/jbe@1309
|
2697 if (this.element_) {
|
bsw/jbe@1309
|
2698 this.initTabs_();
|
bsw/jbe@1309
|
2699 }
|
bsw/jbe@1309
|
2700 };
|
bsw/jbe@1309
|
2701 /**
|
bsw/jbe@1309
|
2702 * Constructor for an individual tab.
|
bsw/jbe@1309
|
2703 *
|
bsw/jbe@1309
|
2704 * @constructor
|
bsw/jbe@1309
|
2705 * @param {Element} tab The HTML element for the tab.
|
bsw/jbe@1309
|
2706 * @param {MaterialTabs} ctx The MaterialTabs object that owns the tab.
|
bsw/jbe@1309
|
2707 */
|
bsw/jbe@1309
|
2708 function MaterialTab(tab, ctx) {
|
bsw/jbe@1309
|
2709 if (tab) {
|
bsw/jbe@1309
|
2710 if (ctx.element_.classList.contains(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
2711 var rippleContainer = document.createElement('span');
|
bsw/jbe@1309
|
2712 rippleContainer.classList.add(ctx.CssClasses_.MDL_RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
2713 rippleContainer.classList.add(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT);
|
bsw/jbe@1309
|
2714 var ripple = document.createElement('span');
|
bsw/jbe@1309
|
2715 ripple.classList.add(ctx.CssClasses_.MDL_RIPPLE);
|
bsw/jbe@1309
|
2716 rippleContainer.appendChild(ripple);
|
bsw/jbe@1309
|
2717 tab.appendChild(rippleContainer);
|
bsw/jbe@1309
|
2718 }
|
bsw/jbe@1309
|
2719 tab.addEventListener('click', function (e) {
|
bsw/jbe@1309
|
2720 if (tab.getAttribute('href').charAt(0) === '#') {
|
bsw/jbe@1309
|
2721 e.preventDefault();
|
bsw/jbe@1309
|
2722 }
|
bsw/jbe@1309
|
2723 var href = tab.href.split('#')[1];
|
bsw/jbe@1309
|
2724 var panel = ctx.element_.querySelector('#' + href);
|
bsw/jbe@1309
|
2725 ctx.resetTabState_();
|
bsw/jbe@1309
|
2726 ctx.resetPanelState_();
|
bsw/jbe@1309
|
2727 tab.classList.add(ctx.CssClasses_.ACTIVE_CLASS);
|
bsw/jbe@1309
|
2728 if (panel) {
|
bsw/jbe@1309
|
2729 panel.classList.add(ctx.CssClasses_.ACTIVE_CLASS);
|
bsw/jbe@1309
|
2730 }
|
bsw/jbe@1309
|
2731 });
|
bsw/jbe@1309
|
2732 }
|
bsw/jbe@1309
|
2733 }
|
bsw/jbe@1309
|
2734 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
2735 // in the global scope.
|
bsw/jbe@1309
|
2736 componentHandler.register({
|
bsw/jbe@1309
|
2737 constructor: MaterialTabs,
|
bsw/jbe@1309
|
2738 classAsString: 'MaterialTabs',
|
bsw/jbe@1309
|
2739 cssClass: 'mdl-js-tabs'
|
bsw/jbe@1309
|
2740 });
|
bsw/jbe@1309
|
2741 /**
|
bsw/jbe@1309
|
2742 * @license
|
bsw/jbe@1309
|
2743 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
2744 *
|
bsw/jbe@1309
|
2745 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
2746 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
2747 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
2748 *
|
bsw/jbe@1309
|
2749 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
2750 *
|
bsw/jbe@1309
|
2751 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
2752 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
2753 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
2754 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
2755 * limitations under the License.
|
bsw/jbe@1309
|
2756 */
|
bsw/jbe@1309
|
2757 /**
|
bsw/jbe@1309
|
2758 * Class constructor for Textfield MDL component.
|
bsw/jbe@1309
|
2759 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
2760 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
2761 *
|
bsw/jbe@1309
|
2762 * @constructor
|
bsw/jbe@1309
|
2763 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
2764 */
|
bsw/jbe@1309
|
2765 var MaterialTextfield = function MaterialTextfield(element) {
|
bsw/jbe@1309
|
2766 this.element_ = element;
|
bsw/jbe@1309
|
2767 this.maxRows = this.Constant_.NO_MAX_ROWS;
|
bsw/jbe@1309
|
2768 // Initialize instance.
|
bsw/jbe@1309
|
2769 this.init();
|
bsw/jbe@1309
|
2770 };
|
bsw/jbe@1309
|
2771 window['MaterialTextfield'] = MaterialTextfield;
|
bsw/jbe@1309
|
2772 /**
|
bsw/jbe@1309
|
2773 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
2774 *
|
bsw/jbe@1309
|
2775 * @enum {string | number}
|
bsw/jbe@1309
|
2776 * @private
|
bsw/jbe@1309
|
2777 */
|
bsw/jbe@1309
|
2778 MaterialTextfield.prototype.Constant_ = {
|
bsw/jbe@1309
|
2779 NO_MAX_ROWS: -1,
|
bsw/jbe@1309
|
2780 MAX_ROWS_ATTRIBUTE: 'maxrows'
|
bsw/jbe@1309
|
2781 };
|
bsw/jbe@1309
|
2782 /**
|
bsw/jbe@1309
|
2783 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
2784 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
2785 * decide to modify at a later date.
|
bsw/jbe@1309
|
2786 *
|
bsw/jbe@1309
|
2787 * @enum {string}
|
bsw/jbe@1309
|
2788 * @private
|
bsw/jbe@1309
|
2789 */
|
bsw/jbe@1309
|
2790 MaterialTextfield.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
2791 LABEL: 'mdl-textfield__label',
|
bsw/jbe@1309
|
2792 INPUT: 'mdl-textfield__input',
|
bsw/jbe@1309
|
2793 IS_DIRTY: 'is-dirty',
|
bsw/jbe@1309
|
2794 IS_FOCUSED: 'is-focused',
|
bsw/jbe@1309
|
2795 IS_DISABLED: 'is-disabled',
|
bsw/jbe@1309
|
2796 IS_INVALID: 'is-invalid',
|
bsw/jbe@1309
|
2797 IS_UPGRADED: 'is-upgraded',
|
bsw/jbe@1309
|
2798 HAS_PLACEHOLDER: 'has-placeholder'
|
bsw/jbe@1309
|
2799 };
|
bsw/jbe@1309
|
2800 /**
|
bsw/jbe@1309
|
2801 * Handle input being entered.
|
bsw/jbe@1309
|
2802 *
|
bsw/jbe@1309
|
2803 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2804 * @private
|
bsw/jbe@1309
|
2805 */
|
bsw/jbe@1309
|
2806 MaterialTextfield.prototype.onKeyDown_ = function (event) {
|
bsw/jbe@1309
|
2807 var currentRowCount = event.target.value.split('\n').length;
|
bsw/jbe@1309
|
2808 if (event.keyCode === 13) {
|
bsw/jbe@1309
|
2809 if (currentRowCount >= this.maxRows) {
|
bsw/jbe@1309
|
2810 event.preventDefault();
|
bsw/jbe@1309
|
2811 }
|
bsw/jbe@1309
|
2812 }
|
bsw/jbe@1309
|
2813 };
|
bsw/jbe@1309
|
2814 /**
|
bsw/jbe@1309
|
2815 * Handle focus.
|
bsw/jbe@1309
|
2816 *
|
bsw/jbe@1309
|
2817 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2818 * @private
|
bsw/jbe@1309
|
2819 */
|
bsw/jbe@1309
|
2820 MaterialTextfield.prototype.onFocus_ = function (event) {
|
bsw/jbe@1309
|
2821 this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
2822 };
|
bsw/jbe@1309
|
2823 /**
|
bsw/jbe@1309
|
2824 * Handle lost focus.
|
bsw/jbe@1309
|
2825 *
|
bsw/jbe@1309
|
2826 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2827 * @private
|
bsw/jbe@1309
|
2828 */
|
bsw/jbe@1309
|
2829 MaterialTextfield.prototype.onBlur_ = function (event) {
|
bsw/jbe@1309
|
2830 this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
2831 };
|
bsw/jbe@1309
|
2832 /**
|
bsw/jbe@1309
|
2833 * Handle reset event from out side.
|
bsw/jbe@1309
|
2834 *
|
bsw/jbe@1309
|
2835 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
2836 * @private
|
bsw/jbe@1309
|
2837 */
|
bsw/jbe@1309
|
2838 MaterialTextfield.prototype.onReset_ = function (event) {
|
bsw/jbe@1309
|
2839 this.updateClasses_();
|
bsw/jbe@1309
|
2840 };
|
bsw/jbe@1309
|
2841 /**
|
bsw/jbe@1309
|
2842 * Handle class updates.
|
bsw/jbe@1309
|
2843 *
|
bsw/jbe@1309
|
2844 * @private
|
bsw/jbe@1309
|
2845 */
|
bsw/jbe@1309
|
2846 MaterialTextfield.prototype.updateClasses_ = function () {
|
bsw/jbe@1309
|
2847 this.checkDisabled();
|
bsw/jbe@1309
|
2848 this.checkValidity();
|
bsw/jbe@1309
|
2849 this.checkDirty();
|
bsw/jbe@1309
|
2850 this.checkFocus();
|
bsw/jbe@1309
|
2851 };
|
bsw/jbe@1309
|
2852 // Public methods.
|
bsw/jbe@1309
|
2853 /**
|
bsw/jbe@1309
|
2854 * Check the disabled state and update field accordingly.
|
bsw/jbe@1309
|
2855 *
|
bsw/jbe@1309
|
2856 * @public
|
bsw/jbe@1309
|
2857 */
|
bsw/jbe@1309
|
2858 MaterialTextfield.prototype.checkDisabled = function () {
|
bsw/jbe@1309
|
2859 if (this.input_.disabled) {
|
bsw/jbe@1309
|
2860 this.element_.classList.add(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
2861 } else {
|
bsw/jbe@1309
|
2862 this.element_.classList.remove(this.CssClasses_.IS_DISABLED);
|
bsw/jbe@1309
|
2863 }
|
bsw/jbe@1309
|
2864 };
|
bsw/jbe@1309
|
2865 MaterialTextfield.prototype['checkDisabled'] = MaterialTextfield.prototype.checkDisabled;
|
bsw/jbe@1309
|
2866 /**
|
bsw/jbe@1309
|
2867 * Check the focus state and update field accordingly.
|
bsw/jbe@1309
|
2868 *
|
bsw/jbe@1309
|
2869 * @public
|
bsw/jbe@1309
|
2870 */
|
bsw/jbe@1309
|
2871 MaterialTextfield.prototype.checkFocus = function () {
|
bsw/jbe@1309
|
2872 if (Boolean(this.element_.querySelector(':focus'))) {
|
bsw/jbe@1309
|
2873 this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
2874 } else {
|
bsw/jbe@1309
|
2875 this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
|
bsw/jbe@1309
|
2876 }
|
bsw/jbe@1309
|
2877 };
|
bsw/jbe@1309
|
2878 MaterialTextfield.prototype['checkFocus'] = MaterialTextfield.prototype.checkFocus;
|
bsw/jbe@1309
|
2879 /**
|
bsw/jbe@1309
|
2880 * Check the validity state and update field accordingly.
|
bsw/jbe@1309
|
2881 *
|
bsw/jbe@1309
|
2882 * @public
|
bsw/jbe@1309
|
2883 */
|
bsw/jbe@1309
|
2884 MaterialTextfield.prototype.checkValidity = function () {
|
bsw/jbe@1309
|
2885 if (this.input_.validity) {
|
bsw/jbe@1309
|
2886 if (this.input_.validity.valid) {
|
bsw/jbe@1309
|
2887 this.element_.classList.remove(this.CssClasses_.IS_INVALID);
|
bsw/jbe@1309
|
2888 } else {
|
bsw/jbe@1309
|
2889 this.element_.classList.add(this.CssClasses_.IS_INVALID);
|
bsw/jbe@1309
|
2890 }
|
bsw/jbe@1309
|
2891 }
|
bsw/jbe@1309
|
2892 };
|
bsw/jbe@1309
|
2893 MaterialTextfield.prototype['checkValidity'] = MaterialTextfield.prototype.checkValidity;
|
bsw/jbe@1309
|
2894 /**
|
bsw/jbe@1309
|
2895 * Check the dirty state and update field accordingly.
|
bsw/jbe@1309
|
2896 *
|
bsw/jbe@1309
|
2897 * @public
|
bsw/jbe@1309
|
2898 */
|
bsw/jbe@1309
|
2899 MaterialTextfield.prototype.checkDirty = function () {
|
bsw/jbe@1309
|
2900 if (this.input_.value && this.input_.value.length > 0) {
|
bsw/jbe@1309
|
2901 this.element_.classList.add(this.CssClasses_.IS_DIRTY);
|
bsw/jbe@1309
|
2902 } else {
|
bsw/jbe@1309
|
2903 this.element_.classList.remove(this.CssClasses_.IS_DIRTY);
|
bsw/jbe@1309
|
2904 }
|
bsw/jbe@1309
|
2905 };
|
bsw/jbe@1309
|
2906 MaterialTextfield.prototype['checkDirty'] = MaterialTextfield.prototype.checkDirty;
|
bsw/jbe@1309
|
2907 /**
|
bsw/jbe@1309
|
2908 * Disable text field.
|
bsw/jbe@1309
|
2909 *
|
bsw/jbe@1309
|
2910 * @public
|
bsw/jbe@1309
|
2911 */
|
bsw/jbe@1309
|
2912 MaterialTextfield.prototype.disable = function () {
|
bsw/jbe@1309
|
2913 this.input_.disabled = true;
|
bsw/jbe@1309
|
2914 this.updateClasses_();
|
bsw/jbe@1309
|
2915 };
|
bsw/jbe@1309
|
2916 MaterialTextfield.prototype['disable'] = MaterialTextfield.prototype.disable;
|
bsw/jbe@1309
|
2917 /**
|
bsw/jbe@1309
|
2918 * Enable text field.
|
bsw/jbe@1309
|
2919 *
|
bsw/jbe@1309
|
2920 * @public
|
bsw/jbe@1309
|
2921 */
|
bsw/jbe@1309
|
2922 MaterialTextfield.prototype.enable = function () {
|
bsw/jbe@1309
|
2923 this.input_.disabled = false;
|
bsw/jbe@1309
|
2924 this.updateClasses_();
|
bsw/jbe@1309
|
2925 };
|
bsw/jbe@1309
|
2926 MaterialTextfield.prototype['enable'] = MaterialTextfield.prototype.enable;
|
bsw/jbe@1309
|
2927 /**
|
bsw/jbe@1309
|
2928 * Update text field value.
|
bsw/jbe@1309
|
2929 *
|
bsw/jbe@1309
|
2930 * @param {string} value The value to which to set the control (optional).
|
bsw/jbe@1309
|
2931 * @public
|
bsw/jbe@1309
|
2932 */
|
bsw/jbe@1309
|
2933 MaterialTextfield.prototype.change = function (value) {
|
bsw/jbe@1309
|
2934 this.input_.value = value || '';
|
bsw/jbe@1309
|
2935 this.updateClasses_();
|
bsw/jbe@1309
|
2936 };
|
bsw/jbe@1309
|
2937 MaterialTextfield.prototype['change'] = MaterialTextfield.prototype.change;
|
bsw/jbe@1309
|
2938 /**
|
bsw/jbe@1309
|
2939 * Initialize element.
|
bsw/jbe@1309
|
2940 */
|
bsw/jbe@1309
|
2941 MaterialTextfield.prototype.init = function () {
|
bsw/jbe@1309
|
2942 if (this.element_) {
|
bsw/jbe@1309
|
2943 this.label_ = this.element_.querySelector('.' + this.CssClasses_.LABEL);
|
bsw/jbe@1309
|
2944 this.input_ = this.element_.querySelector('.' + this.CssClasses_.INPUT);
|
bsw/jbe@1309
|
2945 if (this.input_) {
|
bsw/jbe@1309
|
2946 if (this.input_.hasAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE)) {
|
bsw/jbe@1309
|
2947 this.maxRows = parseInt(this.input_.getAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE), 10);
|
bsw/jbe@1309
|
2948 if (isNaN(this.maxRows)) {
|
bsw/jbe@1309
|
2949 this.maxRows = this.Constant_.NO_MAX_ROWS;
|
bsw/jbe@1309
|
2950 }
|
bsw/jbe@1309
|
2951 }
|
bsw/jbe@1309
|
2952 if (this.input_.hasAttribute('placeholder')) {
|
bsw/jbe@1309
|
2953 this.element_.classList.add(this.CssClasses_.HAS_PLACEHOLDER);
|
bsw/jbe@1309
|
2954 }
|
bsw/jbe@1309
|
2955 this.boundUpdateClassesHandler = this.updateClasses_.bind(this);
|
bsw/jbe@1309
|
2956 this.boundFocusHandler = this.onFocus_.bind(this);
|
bsw/jbe@1309
|
2957 this.boundBlurHandler = this.onBlur_.bind(this);
|
bsw/jbe@1309
|
2958 this.boundResetHandler = this.onReset_.bind(this);
|
bsw/jbe@1309
|
2959 this.input_.addEventListener('input', this.boundUpdateClassesHandler);
|
bsw/jbe@1309
|
2960 this.input_.addEventListener('focus', this.boundFocusHandler);
|
bsw/jbe@1309
|
2961 this.input_.addEventListener('blur', this.boundBlurHandler);
|
bsw/jbe@1309
|
2962 this.input_.addEventListener('reset', this.boundResetHandler);
|
bsw/jbe@1309
|
2963 if (this.maxRows !== this.Constant_.NO_MAX_ROWS) {
|
bsw/jbe@1309
|
2964 // TODO: This should handle pasting multi line text.
|
bsw/jbe@1309
|
2965 // Currently doesn't.
|
bsw/jbe@1309
|
2966 this.boundKeyDownHandler = this.onKeyDown_.bind(this);
|
bsw/jbe@1309
|
2967 this.input_.addEventListener('keydown', this.boundKeyDownHandler);
|
bsw/jbe@1309
|
2968 }
|
bsw/jbe@1309
|
2969 var invalid = this.element_.classList.contains(this.CssClasses_.IS_INVALID);
|
bsw/jbe@1309
|
2970 this.updateClasses_();
|
bsw/jbe@1309
|
2971 this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
|
bsw/jbe@1309
|
2972 if (invalid) {
|
bsw/jbe@1309
|
2973 this.element_.classList.add(this.CssClasses_.IS_INVALID);
|
bsw/jbe@1309
|
2974 }
|
bsw/jbe@1309
|
2975 if (this.input_.hasAttribute('autofocus')) {
|
bsw/jbe@1309
|
2976 this.element_.focus();
|
bsw/jbe@1309
|
2977 this.checkFocus();
|
bsw/jbe@1309
|
2978 }
|
bsw/jbe@1309
|
2979 }
|
bsw/jbe@1309
|
2980 }
|
bsw/jbe@1309
|
2981 };
|
bsw/jbe@1309
|
2982 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
2983 // in the global scope.
|
bsw/jbe@1309
|
2984 componentHandler.register({
|
bsw/jbe@1309
|
2985 constructor: MaterialTextfield,
|
bsw/jbe@1309
|
2986 classAsString: 'MaterialTextfield',
|
bsw/jbe@1309
|
2987 cssClass: 'mdl-js-textfield',
|
bsw/jbe@1309
|
2988 widget: true
|
bsw/jbe@1309
|
2989 });
|
bsw/jbe@1309
|
2990 /**
|
bsw/jbe@1309
|
2991 * @license
|
bsw/jbe@1309
|
2992 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
2993 *
|
bsw/jbe@1309
|
2994 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
2995 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
2996 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
2997 *
|
bsw/jbe@1309
|
2998 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
2999 *
|
bsw/jbe@1309
|
3000 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
3001 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
3002 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
3003 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
3004 * limitations under the License.
|
bsw/jbe@1309
|
3005 */
|
bsw/jbe@1309
|
3006 /**
|
bsw/jbe@1309
|
3007 * Class constructor for Tooltip MDL component.
|
bsw/jbe@1309
|
3008 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
3009 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
3010 *
|
bsw/jbe@1309
|
3011 * @constructor
|
bsw/jbe@1309
|
3012 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
3013 */
|
bsw/jbe@1309
|
3014 var MaterialTooltip = function MaterialTooltip(element) {
|
bsw/jbe@1309
|
3015 this.element_ = element;
|
bsw/jbe@1309
|
3016 // Initialize instance.
|
bsw/jbe@1309
|
3017 this.init();
|
bsw/jbe@1309
|
3018 };
|
bsw/jbe@1309
|
3019 window['MaterialTooltip'] = MaterialTooltip;
|
bsw/jbe@1309
|
3020 /**
|
bsw/jbe@1309
|
3021 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
3022 *
|
bsw/jbe@1309
|
3023 * @enum {string | number}
|
bsw/jbe@1309
|
3024 * @private
|
bsw/jbe@1309
|
3025 */
|
bsw/jbe@1309
|
3026 MaterialTooltip.prototype.Constant_ = {};
|
bsw/jbe@1309
|
3027 /**
|
bsw/jbe@1309
|
3028 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
3029 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
3030 * decide to modify at a later date.
|
bsw/jbe@1309
|
3031 *
|
bsw/jbe@1309
|
3032 * @enum {string}
|
bsw/jbe@1309
|
3033 * @private
|
bsw/jbe@1309
|
3034 */
|
bsw/jbe@1309
|
3035 MaterialTooltip.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
3036 IS_ACTIVE: 'is-active',
|
bsw/jbe@1309
|
3037 BOTTOM: 'mdl-tooltip--bottom',
|
bsw/jbe@1309
|
3038 LEFT: 'mdl-tooltip--left',
|
bsw/jbe@1309
|
3039 RIGHT: 'mdl-tooltip--right',
|
bsw/jbe@1309
|
3040 TOP: 'mdl-tooltip--top'
|
bsw/jbe@1309
|
3041 };
|
bsw/jbe@1309
|
3042 /**
|
bsw/jbe@1309
|
3043 * Handle mouseenter for tooltip.
|
bsw/jbe@1309
|
3044 *
|
bsw/jbe@1309
|
3045 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
3046 * @private
|
bsw/jbe@1309
|
3047 */
|
bsw/jbe@1309
|
3048 MaterialTooltip.prototype.handleMouseEnter_ = function (event) {
|
bsw/jbe@1309
|
3049 var props = event.target.getBoundingClientRect();
|
bsw/jbe@1309
|
3050 var left = props.left + props.width / 2;
|
bsw/jbe@1309
|
3051 var top = props.top + props.height / 2;
|
bsw/jbe@1309
|
3052 var marginLeft = -1 * (this.element_.offsetWidth / 2);
|
bsw/jbe@1309
|
3053 var marginTop = -1 * (this.element_.offsetHeight / 2);
|
bsw/jbe@1309
|
3054 if (this.element_.classList.contains(this.CssClasses_.LEFT) || this.element_.classList.contains(this.CssClasses_.RIGHT)) {
|
bsw/jbe@1309
|
3055 left = props.width / 2;
|
bsw/jbe@1309
|
3056 if (top + marginTop < 0) {
|
bsw/jbe@1309
|
3057 this.element_.style.top = '0';
|
bsw/jbe@1309
|
3058 this.element_.style.marginTop = '0';
|
bsw/jbe@1309
|
3059 } else {
|
bsw/jbe@1309
|
3060 this.element_.style.top = top + 'px';
|
bsw/jbe@1309
|
3061 this.element_.style.marginTop = marginTop + 'px';
|
bsw/jbe@1309
|
3062 }
|
bsw/jbe@1309
|
3063 } else {
|
bsw/jbe@1309
|
3064 if (left + marginLeft < 0) {
|
bsw/jbe@1309
|
3065 this.element_.style.left = '0';
|
bsw/jbe@1309
|
3066 this.element_.style.marginLeft = '0';
|
bsw/jbe@1309
|
3067 } else {
|
bsw/jbe@1309
|
3068 this.element_.style.left = left + 'px';
|
bsw/jbe@1309
|
3069 this.element_.style.marginLeft = marginLeft + 'px';
|
bsw/jbe@1309
|
3070 }
|
bsw/jbe@1309
|
3071 }
|
bsw/jbe@1309
|
3072 if (this.element_.classList.contains(this.CssClasses_.TOP)) {
|
bsw/jbe@1309
|
3073 this.element_.style.top = props.top - this.element_.offsetHeight - 10 + 'px';
|
bsw/jbe@1309
|
3074 } else if (this.element_.classList.contains(this.CssClasses_.RIGHT)) {
|
bsw/jbe@1309
|
3075 this.element_.style.left = props.left + props.width + 10 + 'px';
|
bsw/jbe@1309
|
3076 } else if (this.element_.classList.contains(this.CssClasses_.LEFT)) {
|
bsw/jbe@1309
|
3077 this.element_.style.left = props.left - this.element_.offsetWidth - 10 + 'px';
|
bsw/jbe@1309
|
3078 } else {
|
bsw/jbe@1309
|
3079 this.element_.style.top = props.top + props.height + 10 + 'px';
|
bsw/jbe@1309
|
3080 }
|
bsw/jbe@1309
|
3081 this.element_.classList.add(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3082 };
|
bsw/jbe@1309
|
3083 /**
|
bsw/jbe@1309
|
3084 * Hide tooltip on mouseleave or scroll
|
bsw/jbe@1309
|
3085 *
|
bsw/jbe@1309
|
3086 * @private
|
bsw/jbe@1309
|
3087 */
|
bsw/jbe@1309
|
3088 MaterialTooltip.prototype.hideTooltip_ = function () {
|
bsw/jbe@1309
|
3089 this.element_.classList.remove(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3090 };
|
bsw/jbe@1309
|
3091 /**
|
bsw/jbe@1309
|
3092 * Initialize element.
|
bsw/jbe@1309
|
3093 */
|
bsw/jbe@1309
|
3094 MaterialTooltip.prototype.init = function () {
|
bsw/jbe@1309
|
3095 if (this.element_) {
|
bsw/jbe@1309
|
3096 var forElId = this.element_.getAttribute('for') || this.element_.getAttribute('data-mdl-for');
|
bsw/jbe@1309
|
3097 if (forElId) {
|
bsw/jbe@1309
|
3098 this.forElement_ = document.getElementById(forElId);
|
bsw/jbe@1309
|
3099 }
|
bsw/jbe@1309
|
3100 if (this.forElement_) {
|
bsw/jbe@1309
|
3101 // It's left here because it prevents accidental text selection on Android
|
bsw/jbe@1309
|
3102 if (!this.forElement_.hasAttribute('tabindex')) {
|
bsw/jbe@1309
|
3103 this.forElement_.setAttribute('tabindex', '0');
|
bsw/jbe@1309
|
3104 }
|
bsw/jbe@1309
|
3105 this.boundMouseEnterHandler = this.handleMouseEnter_.bind(this);
|
bsw/jbe@1309
|
3106 this.boundMouseLeaveAndScrollHandler = this.hideTooltip_.bind(this);
|
bsw/jbe@1309
|
3107 this.forElement_.addEventListener('mouseenter', this.boundMouseEnterHandler, false);
|
bsw/jbe@1309
|
3108 this.forElement_.addEventListener('touchend', this.boundMouseEnterHandler, false);
|
bsw/jbe@1309
|
3109 this.forElement_.addEventListener('mouseleave', this.boundMouseLeaveAndScrollHandler, false);
|
bsw/jbe@1309
|
3110 window.addEventListener('scroll', this.boundMouseLeaveAndScrollHandler, true);
|
bsw/jbe@1309
|
3111 window.addEventListener('touchstart', this.boundMouseLeaveAndScrollHandler);
|
bsw/jbe@1309
|
3112 }
|
bsw/jbe@1309
|
3113 }
|
bsw/jbe@1309
|
3114 };
|
bsw/jbe@1309
|
3115 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
3116 // in the global scope.
|
bsw/jbe@1309
|
3117 componentHandler.register({
|
bsw/jbe@1309
|
3118 constructor: MaterialTooltip,
|
bsw/jbe@1309
|
3119 classAsString: 'MaterialTooltip',
|
bsw/jbe@1309
|
3120 cssClass: 'mdl-tooltip'
|
bsw/jbe@1309
|
3121 });
|
bsw/jbe@1309
|
3122 /**
|
bsw/jbe@1309
|
3123 * @license
|
bsw/jbe@1309
|
3124 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
3125 *
|
bsw/jbe@1309
|
3126 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
3127 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
3128 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
3129 *
|
bsw/jbe@1309
|
3130 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
3131 *
|
bsw/jbe@1309
|
3132 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
3133 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
3134 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
3135 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
3136 * limitations under the License.
|
bsw/jbe@1309
|
3137 */
|
bsw/jbe@1309
|
3138 /**
|
bsw/jbe@1309
|
3139 * Class constructor for Layout MDL component.
|
bsw/jbe@1309
|
3140 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
3141 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
3142 *
|
bsw/jbe@1309
|
3143 * @constructor
|
bsw/jbe@1309
|
3144 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
3145 */
|
bsw/jbe@1309
|
3146 var MaterialLayout = function MaterialLayout(element) {
|
bsw/jbe@1309
|
3147 this.element_ = element;
|
bsw/jbe@1309
|
3148 // Initialize instance.
|
bsw/jbe@1309
|
3149 this.init();
|
bsw/jbe@1309
|
3150 };
|
bsw/jbe@1309
|
3151 window['MaterialLayout'] = MaterialLayout;
|
bsw/jbe@1309
|
3152 /**
|
bsw/jbe@1309
|
3153 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
3154 *
|
bsw/jbe@1309
|
3155 * @enum {string | number}
|
bsw/jbe@1309
|
3156 * @private
|
bsw/jbe@1309
|
3157 */
|
bsw/jbe@1309
|
3158 MaterialLayout.prototype.Constant_ = {
|
bsw/jbe@1309
|
3159 MAX_WIDTH: '(max-width: 1024px)',
|
bsw/jbe@1309
|
3160 TAB_SCROLL_PIXELS: 100,
|
bsw/jbe@1309
|
3161 RESIZE_TIMEOUT: 100,
|
bsw/jbe@1309
|
3162 MENU_ICON: '',
|
bsw/jbe@1309
|
3163 CHEVRON_LEFT: 'chevron_left',
|
bsw/jbe@1309
|
3164 CHEVRON_RIGHT: 'chevron_right'
|
bsw/jbe@1309
|
3165 };
|
bsw/jbe@1309
|
3166 /**
|
bsw/jbe@1309
|
3167 * Keycodes, for code readability.
|
bsw/jbe@1309
|
3168 *
|
bsw/jbe@1309
|
3169 * @enum {number}
|
bsw/jbe@1309
|
3170 * @private
|
bsw/jbe@1309
|
3171 */
|
bsw/jbe@1309
|
3172 MaterialLayout.prototype.Keycodes_ = {
|
bsw/jbe@1309
|
3173 ENTER: 13,
|
bsw/jbe@1309
|
3174 ESCAPE: 27,
|
bsw/jbe@1309
|
3175 SPACE: 32
|
bsw/jbe@1309
|
3176 };
|
bsw/jbe@1309
|
3177 /**
|
bsw/jbe@1309
|
3178 * Modes.
|
bsw/jbe@1309
|
3179 *
|
bsw/jbe@1309
|
3180 * @enum {number}
|
bsw/jbe@1309
|
3181 * @private
|
bsw/jbe@1309
|
3182 */
|
bsw/jbe@1309
|
3183 MaterialLayout.prototype.Mode_ = {
|
bsw/jbe@1309
|
3184 STANDARD: 0,
|
bsw/jbe@1309
|
3185 SEAMED: 1,
|
bsw/jbe@1309
|
3186 WATERFALL: 2,
|
bsw/jbe@1309
|
3187 SCROLL: 3
|
bsw/jbe@1309
|
3188 };
|
bsw/jbe@1309
|
3189 /**
|
bsw/jbe@1309
|
3190 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
3191 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
3192 * decide to modify at a later date.
|
bsw/jbe@1309
|
3193 *
|
bsw/jbe@1309
|
3194 * @enum {string}
|
bsw/jbe@1309
|
3195 * @private
|
bsw/jbe@1309
|
3196 */
|
bsw/jbe@1309
|
3197 MaterialLayout.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
3198 CONTAINER: 'mdl-layout__container',
|
bsw/jbe@1309
|
3199 HEADER: 'mdl-layout__header',
|
bsw/jbe@1309
|
3200 DRAWER: 'mdl-layout__drawer',
|
bsw/jbe@1309
|
3201 CONTENT: 'mdl-layout__content',
|
bsw/jbe@1309
|
3202 DRAWER_BTN: 'mdl-layout__drawer-button',
|
bsw/jbe@1309
|
3203 ICON: 'material-icons',
|
bsw/jbe@1309
|
3204 JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
3205 RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container',
|
bsw/jbe@1309
|
3206 RIPPLE: 'mdl-ripple',
|
bsw/jbe@1309
|
3207 RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
bsw/jbe@1309
|
3208 HEADER_SEAMED: 'mdl-layout__header--seamed',
|
bsw/jbe@1309
|
3209 HEADER_WATERFALL: 'mdl-layout__header--waterfall',
|
bsw/jbe@1309
|
3210 HEADER_SCROLL: 'mdl-layout__header--scroll',
|
bsw/jbe@1309
|
3211 FIXED_HEADER: 'mdl-layout--fixed-header',
|
bsw/jbe@1309
|
3212 OBFUSCATOR: 'mdl-layout__obfuscator',
|
bsw/jbe@1309
|
3213 TAB_BAR: 'mdl-layout__tab-bar',
|
bsw/jbe@1309
|
3214 TAB_CONTAINER: 'mdl-layout__tab-bar-container',
|
bsw/jbe@1309
|
3215 TAB: 'mdl-layout__tab',
|
bsw/jbe@1309
|
3216 TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button',
|
bsw/jbe@1309
|
3217 TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button',
|
bsw/jbe@1309
|
3218 TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button',
|
bsw/jbe@1309
|
3219 PANEL: 'mdl-layout__tab-panel',
|
bsw/jbe@1309
|
3220 HAS_DRAWER: 'has-drawer',
|
bsw/jbe@1309
|
3221 HAS_TABS: 'has-tabs',
|
bsw/jbe@1309
|
3222 HAS_SCROLLING_HEADER: 'has-scrolling-header',
|
bsw/jbe@1309
|
3223 CASTING_SHADOW: 'is-casting-shadow',
|
bsw/jbe@1309
|
3224 IS_COMPACT: 'is-compact',
|
bsw/jbe@1309
|
3225 IS_SMALL_SCREEN: 'is-small-screen',
|
bsw/jbe@1309
|
3226 IS_DRAWER_OPEN: 'is-visible',
|
bsw/jbe@1309
|
3227 IS_ACTIVE: 'is-active',
|
bsw/jbe@1309
|
3228 IS_UPGRADED: 'is-upgraded',
|
bsw/jbe@1309
|
3229 IS_ANIMATING: 'is-animating',
|
bsw/jbe@1309
|
3230 ON_LARGE_SCREEN: 'mdl-layout--large-screen-only',
|
bsw/jbe@1309
|
3231 ON_SMALL_SCREEN: 'mdl-layout--small-screen-only'
|
bsw/jbe@1309
|
3232 };
|
bsw/jbe@1309
|
3233 /**
|
bsw/jbe@1309
|
3234 * Handles scrolling on the content.
|
bsw/jbe@1309
|
3235 *
|
bsw/jbe@1309
|
3236 * @private
|
bsw/jbe@1309
|
3237 */
|
bsw/jbe@1309
|
3238 MaterialLayout.prototype.contentScrollHandler_ = function () {
|
bsw/jbe@1309
|
3239 if (this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)) {
|
bsw/jbe@1309
|
3240 return;
|
bsw/jbe@1309
|
3241 }
|
bsw/jbe@1309
|
3242 var headerVisible = !this.element_.classList.contains(this.CssClasses_.IS_SMALL_SCREEN) || this.element_.classList.contains(this.CssClasses_.FIXED_HEADER);
|
bsw/jbe@1309
|
3243 if (this.content_.scrollTop > 0 && !this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
|
bsw/jbe@1309
|
3244 this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
|
bsw/jbe@1309
|
3245 this.header_.classList.add(this.CssClasses_.IS_COMPACT);
|
bsw/jbe@1309
|
3246 if (headerVisible) {
|
bsw/jbe@1309
|
3247 this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
3248 }
|
bsw/jbe@1309
|
3249 } else if (this.content_.scrollTop <= 0 && this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
|
bsw/jbe@1309
|
3250 this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
|
bsw/jbe@1309
|
3251 this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
|
bsw/jbe@1309
|
3252 if (headerVisible) {
|
bsw/jbe@1309
|
3253 this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
3254 }
|
bsw/jbe@1309
|
3255 }
|
bsw/jbe@1309
|
3256 };
|
bsw/jbe@1309
|
3257 /**
|
bsw/jbe@1309
|
3258 * Handles a keyboard event on the drawer.
|
bsw/jbe@1309
|
3259 *
|
bsw/jbe@1309
|
3260 * @param {Event} evt The event that fired.
|
bsw/jbe@1309
|
3261 * @private
|
bsw/jbe@1309
|
3262 */
|
bsw/jbe@1309
|
3263 MaterialLayout.prototype.keyboardEventHandler_ = function (evt) {
|
bsw/jbe@1309
|
3264 // Only react when the drawer is open.
|
bsw/jbe@1309
|
3265 if (evt.keyCode === this.Keycodes_.ESCAPE && this.drawer_.classList.contains(this.CssClasses_.IS_DRAWER_OPEN)) {
|
bsw/jbe@1309
|
3266 this.toggleDrawer();
|
bsw/jbe@1309
|
3267 }
|
bsw/jbe@1309
|
3268 };
|
bsw/jbe@1309
|
3269 /**
|
bsw/jbe@1309
|
3270 * Handles changes in screen size.
|
bsw/jbe@1309
|
3271 *
|
bsw/jbe@1309
|
3272 * @private
|
bsw/jbe@1309
|
3273 */
|
bsw/jbe@1309
|
3274 MaterialLayout.prototype.screenSizeHandler_ = function () {
|
bsw/jbe@1309
|
3275 if (this.screenSizeMediaQuery_.matches) {
|
bsw/jbe@1309
|
3276 this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN);
|
bsw/jbe@1309
|
3277 } else {
|
bsw/jbe@1309
|
3278 this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN);
|
bsw/jbe@1309
|
3279 // Collapse drawer (if any) when moving to a large screen size.
|
bsw/jbe@1309
|
3280 if (this.drawer_) {
|
bsw/jbe@1309
|
3281 this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
|
bsw/jbe@1309
|
3282 this.obfuscator_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
|
bsw/jbe@1309
|
3283 }
|
bsw/jbe@1309
|
3284 }
|
bsw/jbe@1309
|
3285 };
|
bsw/jbe@1309
|
3286 /**
|
bsw/jbe@1309
|
3287 * Handles events of drawer button.
|
bsw/jbe@1309
|
3288 *
|
bsw/jbe@1309
|
3289 * @param {Event} evt The event that fired.
|
bsw/jbe@1309
|
3290 * @private
|
bsw/jbe@1309
|
3291 */
|
bsw/jbe@1309
|
3292 MaterialLayout.prototype.drawerToggleHandler_ = function (evt) {
|
bsw/jbe@1309
|
3293 if (evt && evt.type === 'keydown') {
|
bsw/jbe@1309
|
3294 if (evt.keyCode === this.Keycodes_.SPACE || evt.keyCode === this.Keycodes_.ENTER) {
|
bsw/jbe@1309
|
3295 // prevent scrolling in drawer nav
|
bsw/jbe@1309
|
3296 evt.preventDefault();
|
bsw/jbe@1309
|
3297 } else {
|
bsw/jbe@1309
|
3298 // prevent other keys
|
bsw/jbe@1309
|
3299 return;
|
bsw/jbe@1309
|
3300 }
|
bsw/jbe@1309
|
3301 }
|
bsw/jbe@1309
|
3302 this.toggleDrawer();
|
bsw/jbe@1309
|
3303 };
|
bsw/jbe@1309
|
3304 /**
|
bsw/jbe@1309
|
3305 * Handles (un)setting the `is-animating` class
|
bsw/jbe@1309
|
3306 *
|
bsw/jbe@1309
|
3307 * @private
|
bsw/jbe@1309
|
3308 */
|
bsw/jbe@1309
|
3309 MaterialLayout.prototype.headerTransitionEndHandler_ = function () {
|
bsw/jbe@1309
|
3310 this.header_.classList.remove(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
3311 };
|
bsw/jbe@1309
|
3312 /**
|
bsw/jbe@1309
|
3313 * Handles expanding the header on click
|
bsw/jbe@1309
|
3314 *
|
bsw/jbe@1309
|
3315 * @private
|
bsw/jbe@1309
|
3316 */
|
bsw/jbe@1309
|
3317 MaterialLayout.prototype.headerClickHandler_ = function () {
|
bsw/jbe@1309
|
3318 if (this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) {
|
bsw/jbe@1309
|
3319 this.header_.classList.remove(this.CssClasses_.IS_COMPACT);
|
bsw/jbe@1309
|
3320 this.header_.classList.add(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
3321 }
|
bsw/jbe@1309
|
3322 };
|
bsw/jbe@1309
|
3323 /**
|
bsw/jbe@1309
|
3324 * Reset tab state, dropping active classes
|
bsw/jbe@1309
|
3325 *
|
bsw/jbe@1309
|
3326 * @private
|
bsw/jbe@1309
|
3327 */
|
bsw/jbe@1309
|
3328 MaterialLayout.prototype.resetTabState_ = function (tabBar) {
|
bsw/jbe@1309
|
3329 for (var k = 0; k < tabBar.length; k++) {
|
bsw/jbe@1309
|
3330 tabBar[k].classList.remove(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3331 }
|
bsw/jbe@1309
|
3332 };
|
bsw/jbe@1309
|
3333 /**
|
bsw/jbe@1309
|
3334 * Reset panel state, droping active classes
|
bsw/jbe@1309
|
3335 *
|
bsw/jbe@1309
|
3336 * @private
|
bsw/jbe@1309
|
3337 */
|
bsw/jbe@1309
|
3338 MaterialLayout.prototype.resetPanelState_ = function (panels) {
|
bsw/jbe@1309
|
3339 for (var j = 0; j < panels.length; j++) {
|
bsw/jbe@1309
|
3340 panels[j].classList.remove(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3341 }
|
bsw/jbe@1309
|
3342 };
|
bsw/jbe@1309
|
3343 /**
|
bsw/jbe@1309
|
3344 * Toggle drawer state
|
bsw/jbe@1309
|
3345 *
|
bsw/jbe@1309
|
3346 * @public
|
bsw/jbe@1309
|
3347 */
|
bsw/jbe@1309
|
3348 MaterialLayout.prototype.toggleDrawer = function () {
|
bsw/jbe@1309
|
3349 var drawerButton = this.element_.querySelector('.' + this.CssClasses_.DRAWER_BTN);
|
bsw/jbe@1309
|
3350 this.drawer_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN);
|
bsw/jbe@1309
|
3351 this.obfuscator_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN);
|
bsw/jbe@1309
|
3352 // Set accessibility properties.
|
bsw/jbe@1309
|
3353 if (this.drawer_.classList.contains(this.CssClasses_.IS_DRAWER_OPEN)) {
|
bsw/jbe@1309
|
3354 this.drawer_.setAttribute('aria-hidden', 'false');
|
bsw/jbe@1309
|
3355 drawerButton.setAttribute('aria-expanded', 'true');
|
bsw/jbe@1309
|
3356 } else {
|
bsw/jbe@1309
|
3357 this.drawer_.setAttribute('aria-hidden', 'true');
|
bsw/jbe@1309
|
3358 drawerButton.setAttribute('aria-expanded', 'false');
|
bsw/jbe@1309
|
3359 }
|
bsw/jbe@1309
|
3360 };
|
bsw/jbe@1309
|
3361 MaterialLayout.prototype['toggleDrawer'] = MaterialLayout.prototype.toggleDrawer;
|
bsw/jbe@1309
|
3362 /**
|
bsw/jbe@1309
|
3363 * Initialize element.
|
bsw/jbe@1309
|
3364 */
|
bsw/jbe@1309
|
3365 MaterialLayout.prototype.init = function () {
|
bsw/jbe@1309
|
3366 if (this.element_) {
|
bsw/jbe@1309
|
3367 var container = document.createElement('div');
|
bsw/jbe@1309
|
3368 container.classList.add(this.CssClasses_.CONTAINER);
|
bsw/jbe@1309
|
3369 var focusedElement = this.element_.querySelector(':focus');
|
bsw/jbe@1309
|
3370 this.element_.parentElement.insertBefore(container, this.element_);
|
bsw/jbe@1309
|
3371 this.element_.parentElement.removeChild(this.element_);
|
bsw/jbe@1309
|
3372 container.appendChild(this.element_);
|
bsw/jbe@1309
|
3373 if (focusedElement) {
|
bsw/jbe@1309
|
3374 focusedElement.focus();
|
bsw/jbe@1309
|
3375 }
|
bsw/jbe@1309
|
3376 var directChildren = this.element_.childNodes;
|
bsw/jbe@1309
|
3377 var numChildren = directChildren.length;
|
bsw/jbe@1309
|
3378 for (var c = 0; c < numChildren; c++) {
|
bsw/jbe@1309
|
3379 var child = directChildren[c];
|
bsw/jbe@1309
|
3380 if (child.classList && child.classList.contains(this.CssClasses_.HEADER)) {
|
bsw/jbe@1309
|
3381 this.header_ = child;
|
bsw/jbe@1309
|
3382 }
|
bsw/jbe@1309
|
3383 if (child.classList && child.classList.contains(this.CssClasses_.DRAWER)) {
|
bsw/jbe@1309
|
3384 this.drawer_ = child;
|
bsw/jbe@1309
|
3385 }
|
bsw/jbe@1309
|
3386 if (child.classList && child.classList.contains(this.CssClasses_.CONTENT)) {
|
bsw/jbe@1309
|
3387 this.content_ = child;
|
bsw/jbe@1309
|
3388 }
|
bsw/jbe@1309
|
3389 }
|
bsw/jbe@1309
|
3390 window.addEventListener('pageshow', function (e) {
|
bsw/jbe@1309
|
3391 if (e.persisted) {
|
bsw/jbe@1309
|
3392 // when page is loaded from back/forward cache
|
bsw/jbe@1309
|
3393 // trigger repaint to let layout scroll in safari
|
bsw/jbe@1309
|
3394 this.element_.style.overflowY = 'hidden';
|
bsw/jbe@1309
|
3395 requestAnimationFrame(function () {
|
bsw/jbe@1309
|
3396 this.element_.style.overflowY = '';
|
bsw/jbe@1309
|
3397 }.bind(this));
|
bsw/jbe@1309
|
3398 }
|
bsw/jbe@1309
|
3399 }.bind(this), false);
|
bsw/jbe@1309
|
3400 if (this.header_) {
|
bsw/jbe@1309
|
3401 this.tabBar_ = this.header_.querySelector('.' + this.CssClasses_.TAB_BAR);
|
bsw/jbe@1309
|
3402 }
|
bsw/jbe@1309
|
3403 var mode = this.Mode_.STANDARD;
|
bsw/jbe@1309
|
3404 if (this.header_) {
|
bsw/jbe@1309
|
3405 if (this.header_.classList.contains(this.CssClasses_.HEADER_SEAMED)) {
|
bsw/jbe@1309
|
3406 mode = this.Mode_.SEAMED;
|
bsw/jbe@1309
|
3407 } else if (this.header_.classList.contains(this.CssClasses_.HEADER_WATERFALL)) {
|
bsw/jbe@1309
|
3408 mode = this.Mode_.WATERFALL;
|
bsw/jbe@1309
|
3409 this.header_.addEventListener('transitionend', this.headerTransitionEndHandler_.bind(this));
|
bsw/jbe@1309
|
3410 this.header_.addEventListener('click', this.headerClickHandler_.bind(this));
|
bsw/jbe@1309
|
3411 } else if (this.header_.classList.contains(this.CssClasses_.HEADER_SCROLL)) {
|
bsw/jbe@1309
|
3412 mode = this.Mode_.SCROLL;
|
bsw/jbe@1309
|
3413 container.classList.add(this.CssClasses_.HAS_SCROLLING_HEADER);
|
bsw/jbe@1309
|
3414 }
|
bsw/jbe@1309
|
3415 if (mode === this.Mode_.STANDARD) {
|
bsw/jbe@1309
|
3416 this.header_.classList.add(this.CssClasses_.CASTING_SHADOW);
|
bsw/jbe@1309
|
3417 if (this.tabBar_) {
|
bsw/jbe@1309
|
3418 this.tabBar_.classList.add(this.CssClasses_.CASTING_SHADOW);
|
bsw/jbe@1309
|
3419 }
|
bsw/jbe@1309
|
3420 } else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) {
|
bsw/jbe@1309
|
3421 this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW);
|
bsw/jbe@1309
|
3422 if (this.tabBar_) {
|
bsw/jbe@1309
|
3423 this.tabBar_.classList.remove(this.CssClasses_.CASTING_SHADOW);
|
bsw/jbe@1309
|
3424 }
|
bsw/jbe@1309
|
3425 } else if (mode === this.Mode_.WATERFALL) {
|
bsw/jbe@1309
|
3426 // Add and remove shadows depending on scroll position.
|
bsw/jbe@1309
|
3427 // Also add/remove auxiliary class for styling of the compact version of
|
bsw/jbe@1309
|
3428 // the header.
|
bsw/jbe@1309
|
3429 this.content_.addEventListener('scroll', this.contentScrollHandler_.bind(this));
|
bsw/jbe@1309
|
3430 this.contentScrollHandler_();
|
bsw/jbe@1309
|
3431 }
|
bsw/jbe@1309
|
3432 }
|
bsw/jbe@1309
|
3433 // Add drawer toggling button to our layout, if we have an openable drawer.
|
bsw/jbe@1309
|
3434 if (this.drawer_) {
|
bsw/jbe@1309
|
3435 var drawerButton = this.element_.querySelector('.' + this.CssClasses_.DRAWER_BTN);
|
bsw/jbe@1309
|
3436 if (!drawerButton) {
|
bsw/jbe@1309
|
3437 drawerButton = document.createElement('div');
|
bsw/jbe@1309
|
3438 drawerButton.setAttribute('aria-expanded', 'false');
|
bsw/jbe@1309
|
3439 drawerButton.setAttribute('role', 'button');
|
bsw/jbe@1309
|
3440 drawerButton.setAttribute('tabindex', '0');
|
bsw/jbe@1309
|
3441 drawerButton.classList.add(this.CssClasses_.DRAWER_BTN);
|
bsw/jbe@1309
|
3442 var drawerButtonIcon = document.createElement('i');
|
bsw/jbe@1309
|
3443 drawerButtonIcon.classList.add(this.CssClasses_.ICON);
|
bsw/jbe@1309
|
3444 drawerButtonIcon.innerHTML = this.Constant_.MENU_ICON;
|
bsw/jbe@1309
|
3445 drawerButton.appendChild(drawerButtonIcon);
|
bsw/jbe@1309
|
3446 }
|
bsw/jbe@1309
|
3447 if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) {
|
bsw/jbe@1309
|
3448 //If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well.
|
bsw/jbe@1309
|
3449 drawerButton.classList.add(this.CssClasses_.ON_LARGE_SCREEN);
|
bsw/jbe@1309
|
3450 } else if (this.drawer_.classList.contains(this.CssClasses_.ON_SMALL_SCREEN)) {
|
bsw/jbe@1309
|
3451 //If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well.
|
bsw/jbe@1309
|
3452 drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN);
|
bsw/jbe@1309
|
3453 }
|
bsw/jbe@1309
|
3454 drawerButton.addEventListener('click', this.drawerToggleHandler_.bind(this));
|
bsw/jbe@1309
|
3455 drawerButton.addEventListener('keydown', this.drawerToggleHandler_.bind(this));
|
bsw/jbe@1309
|
3456 // Add a class if the layout has a drawer, for altering the left padding.
|
bsw/jbe@1309
|
3457 // Adds the HAS_DRAWER to the elements since this.header_ may or may
|
bsw/jbe@1309
|
3458 // not be present.
|
bsw/jbe@1309
|
3459 this.element_.classList.add(this.CssClasses_.HAS_DRAWER);
|
bsw/jbe@1309
|
3460 // If we have a fixed header, add the button to the header rather than
|
bsw/jbe@1309
|
3461 // the layout.
|
bsw/jbe@1309
|
3462 if (this.element_.classList.contains(this.CssClasses_.FIXED_HEADER)) {
|
bsw/jbe@1309
|
3463 this.header_.insertBefore(drawerButton, this.header_.firstChild);
|
bsw/jbe@1309
|
3464 } else {
|
bsw/jbe@1309
|
3465 this.element_.insertBefore(drawerButton, this.content_);
|
bsw/jbe@1309
|
3466 }
|
bsw/jbe@1309
|
3467 var obfuscator = document.createElement('div');
|
bsw/jbe@1309
|
3468 obfuscator.classList.add(this.CssClasses_.OBFUSCATOR);
|
bsw/jbe@1309
|
3469 this.element_.appendChild(obfuscator);
|
bsw/jbe@1309
|
3470 obfuscator.addEventListener('click', this.drawerToggleHandler_.bind(this));
|
bsw/jbe@1309
|
3471 this.obfuscator_ = obfuscator;
|
bsw/jbe@1309
|
3472 this.drawer_.addEventListener('keydown', this.keyboardEventHandler_.bind(this));
|
bsw/jbe@1309
|
3473 this.drawer_.setAttribute('aria-hidden', 'true');
|
bsw/jbe@1309
|
3474 }
|
bsw/jbe@1309
|
3475 // Keep an eye on screen size, and add/remove auxiliary class for styling
|
bsw/jbe@1309
|
3476 // of small screens.
|
bsw/jbe@1309
|
3477 this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH);
|
bsw/jbe@1309
|
3478 this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this));
|
bsw/jbe@1309
|
3479 this.screenSizeHandler_();
|
bsw/jbe@1309
|
3480 // Initialize tabs, if any.
|
bsw/jbe@1309
|
3481 if (this.header_ && this.tabBar_) {
|
bsw/jbe@1309
|
3482 this.element_.classList.add(this.CssClasses_.HAS_TABS);
|
bsw/jbe@1309
|
3483 var tabContainer = document.createElement('div');
|
bsw/jbe@1309
|
3484 tabContainer.classList.add(this.CssClasses_.TAB_CONTAINER);
|
bsw/jbe@1309
|
3485 this.header_.insertBefore(tabContainer, this.tabBar_);
|
bsw/jbe@1309
|
3486 this.header_.removeChild(this.tabBar_);
|
bsw/jbe@1309
|
3487 var leftButton = document.createElement('div');
|
bsw/jbe@1309
|
3488 leftButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
|
bsw/jbe@1309
|
3489 leftButton.classList.add(this.CssClasses_.TAB_BAR_LEFT_BUTTON);
|
bsw/jbe@1309
|
3490 var leftButtonIcon = document.createElement('i');
|
bsw/jbe@1309
|
3491 leftButtonIcon.classList.add(this.CssClasses_.ICON);
|
bsw/jbe@1309
|
3492 leftButtonIcon.textContent = this.Constant_.CHEVRON_LEFT;
|
bsw/jbe@1309
|
3493 leftButton.appendChild(leftButtonIcon);
|
bsw/jbe@1309
|
3494 leftButton.addEventListener('click', function () {
|
bsw/jbe@1309
|
3495 this.tabBar_.scrollLeft -= this.Constant_.TAB_SCROLL_PIXELS;
|
bsw/jbe@1309
|
3496 }.bind(this));
|
bsw/jbe@1309
|
3497 var rightButton = document.createElement('div');
|
bsw/jbe@1309
|
3498 rightButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON);
|
bsw/jbe@1309
|
3499 rightButton.classList.add(this.CssClasses_.TAB_BAR_RIGHT_BUTTON);
|
bsw/jbe@1309
|
3500 var rightButtonIcon = document.createElement('i');
|
bsw/jbe@1309
|
3501 rightButtonIcon.classList.add(this.CssClasses_.ICON);
|
bsw/jbe@1309
|
3502 rightButtonIcon.textContent = this.Constant_.CHEVRON_RIGHT;
|
bsw/jbe@1309
|
3503 rightButton.appendChild(rightButtonIcon);
|
bsw/jbe@1309
|
3504 rightButton.addEventListener('click', function () {
|
bsw/jbe@1309
|
3505 this.tabBar_.scrollLeft += this.Constant_.TAB_SCROLL_PIXELS;
|
bsw/jbe@1309
|
3506 }.bind(this));
|
bsw/jbe@1309
|
3507 tabContainer.appendChild(leftButton);
|
bsw/jbe@1309
|
3508 tabContainer.appendChild(this.tabBar_);
|
bsw/jbe@1309
|
3509 tabContainer.appendChild(rightButton);
|
bsw/jbe@1309
|
3510 // Add and remove tab buttons depending on scroll position and total
|
bsw/jbe@1309
|
3511 // window size.
|
bsw/jbe@1309
|
3512 var tabUpdateHandler = function () {
|
bsw/jbe@1309
|
3513 if (this.tabBar_.scrollLeft > 0) {
|
bsw/jbe@1309
|
3514 leftButton.classList.add(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3515 } else {
|
bsw/jbe@1309
|
3516 leftButton.classList.remove(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3517 }
|
bsw/jbe@1309
|
3518 if (this.tabBar_.scrollLeft < this.tabBar_.scrollWidth - this.tabBar_.offsetWidth) {
|
bsw/jbe@1309
|
3519 rightButton.classList.add(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3520 } else {
|
bsw/jbe@1309
|
3521 rightButton.classList.remove(this.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3522 }
|
bsw/jbe@1309
|
3523 }.bind(this);
|
bsw/jbe@1309
|
3524 this.tabBar_.addEventListener('scroll', tabUpdateHandler);
|
bsw/jbe@1309
|
3525 tabUpdateHandler();
|
bsw/jbe@1309
|
3526 // Update tabs when the window resizes.
|
bsw/jbe@1309
|
3527 var windowResizeHandler = function () {
|
bsw/jbe@1309
|
3528 // Use timeouts to make sure it doesn't happen too often.
|
bsw/jbe@1309
|
3529 if (this.resizeTimeoutId_) {
|
bsw/jbe@1309
|
3530 clearTimeout(this.resizeTimeoutId_);
|
bsw/jbe@1309
|
3531 }
|
bsw/jbe@1309
|
3532 this.resizeTimeoutId_ = setTimeout(function () {
|
bsw/jbe@1309
|
3533 tabUpdateHandler();
|
bsw/jbe@1309
|
3534 this.resizeTimeoutId_ = null;
|
bsw/jbe@1309
|
3535 }.bind(this), this.Constant_.RESIZE_TIMEOUT);
|
bsw/jbe@1309
|
3536 }.bind(this);
|
bsw/jbe@1309
|
3537 window.addEventListener('resize', windowResizeHandler);
|
bsw/jbe@1309
|
3538 if (this.tabBar_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
3539 this.tabBar_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
|
bsw/jbe@1309
|
3540 }
|
bsw/jbe@1309
|
3541 // Select element tabs, document panels
|
bsw/jbe@1309
|
3542 var tabs = this.tabBar_.querySelectorAll('.' + this.CssClasses_.TAB);
|
bsw/jbe@1309
|
3543 var panels = this.content_.querySelectorAll('.' + this.CssClasses_.PANEL);
|
bsw/jbe@1309
|
3544 // Create new tabs for each tab element
|
bsw/jbe@1309
|
3545 for (var i = 0; i < tabs.length; i++) {
|
bsw/jbe@1309
|
3546 new MaterialLayoutTab(tabs[i], tabs, panels, this);
|
bsw/jbe@1309
|
3547 }
|
bsw/jbe@1309
|
3548 }
|
bsw/jbe@1309
|
3549 this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
|
bsw/jbe@1309
|
3550 }
|
bsw/jbe@1309
|
3551 };
|
bsw/jbe@1309
|
3552 /**
|
bsw/jbe@1309
|
3553 * Constructor for an individual tab.
|
bsw/jbe@1309
|
3554 *
|
bsw/jbe@1309
|
3555 * @constructor
|
bsw/jbe@1309
|
3556 * @param {HTMLElement} tab The HTML element for the tab.
|
bsw/jbe@1309
|
3557 * @param {!Array<HTMLElement>} tabs Array with HTML elements for all tabs.
|
bsw/jbe@1309
|
3558 * @param {!Array<HTMLElement>} panels Array with HTML elements for all panels.
|
bsw/jbe@1309
|
3559 * @param {MaterialLayout} layout The MaterialLayout object that owns the tab.
|
bsw/jbe@1309
|
3560 */
|
bsw/jbe@1309
|
3561 function MaterialLayoutTab(tab, tabs, panels, layout) {
|
bsw/jbe@1309
|
3562 /**
|
bsw/jbe@1309
|
3563 * Auxiliary method to programmatically select a tab in the UI.
|
bsw/jbe@1309
|
3564 */
|
bsw/jbe@1309
|
3565 function selectTab() {
|
bsw/jbe@1309
|
3566 var href = tab.href.split('#')[1];
|
bsw/jbe@1309
|
3567 var panel = layout.content_.querySelector('#' + href);
|
bsw/jbe@1309
|
3568 layout.resetTabState_(tabs);
|
bsw/jbe@1309
|
3569 layout.resetPanelState_(panels);
|
bsw/jbe@1309
|
3570 tab.classList.add(layout.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3571 panel.classList.add(layout.CssClasses_.IS_ACTIVE);
|
bsw/jbe@1309
|
3572 }
|
bsw/jbe@1309
|
3573 if (layout.tabBar_.classList.contains(layout.CssClasses_.JS_RIPPLE_EFFECT)) {
|
bsw/jbe@1309
|
3574 var rippleContainer = document.createElement('span');
|
bsw/jbe@1309
|
3575 rippleContainer.classList.add(layout.CssClasses_.RIPPLE_CONTAINER);
|
bsw/jbe@1309
|
3576 rippleContainer.classList.add(layout.CssClasses_.JS_RIPPLE_EFFECT);
|
bsw/jbe@1309
|
3577 var ripple = document.createElement('span');
|
bsw/jbe@1309
|
3578 ripple.classList.add(layout.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
3579 rippleContainer.appendChild(ripple);
|
bsw/jbe@1309
|
3580 tab.appendChild(rippleContainer);
|
bsw/jbe@1309
|
3581 }
|
bsw/jbe@1309
|
3582 tab.addEventListener('click', function (e) {
|
bsw/jbe@1309
|
3583 if (tab.getAttribute('href').charAt(0) === '#') {
|
bsw/jbe@1309
|
3584 e.preventDefault();
|
bsw/jbe@1309
|
3585 selectTab();
|
bsw/jbe@1309
|
3586 }
|
bsw/jbe@1309
|
3587 });
|
bsw/jbe@1309
|
3588 tab.show = selectTab;
|
bsw/jbe@1309
|
3589 }
|
bsw/jbe@1309
|
3590 window['MaterialLayoutTab'] = MaterialLayoutTab;
|
bsw/jbe@1309
|
3591 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
3592 // in the global scope.
|
bsw/jbe@1309
|
3593 componentHandler.register({
|
bsw/jbe@1309
|
3594 constructor: MaterialLayout,
|
bsw/jbe@1309
|
3595 classAsString: 'MaterialLayout',
|
bsw/jbe@1309
|
3596 cssClass: 'mdl-js-layout'
|
bsw/jbe@1309
|
3597 });
|
bsw/jbe@1309
|
3598 /**
|
bsw/jbe@1309
|
3599 * @license
|
bsw/jbe@1309
|
3600 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
3601 *
|
bsw/jbe@1309
|
3602 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
3603 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
3604 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
3605 *
|
bsw/jbe@1309
|
3606 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
3607 *
|
bsw/jbe@1309
|
3608 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
3609 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
3610 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
3611 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
3612 * limitations under the License.
|
bsw/jbe@1309
|
3613 */
|
bsw/jbe@1309
|
3614 /**
|
bsw/jbe@1309
|
3615 * Class constructor for Data Table Card MDL component.
|
bsw/jbe@1309
|
3616 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
3617 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
3618 *
|
bsw/jbe@1309
|
3619 * @constructor
|
bsw/jbe@1309
|
3620 * @param {Element} element The element that will be upgraded.
|
bsw/jbe@1309
|
3621 */
|
bsw/jbe@1309
|
3622 var MaterialDataTable = function MaterialDataTable(element) {
|
bsw/jbe@1309
|
3623 this.element_ = element;
|
bsw/jbe@1309
|
3624 // Initialize instance.
|
bsw/jbe@1309
|
3625 this.init();
|
bsw/jbe@1309
|
3626 };
|
bsw/jbe@1309
|
3627 window['MaterialDataTable'] = MaterialDataTable;
|
bsw/jbe@1309
|
3628 /**
|
bsw/jbe@1309
|
3629 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
3630 *
|
bsw/jbe@1309
|
3631 * @enum {string | number}
|
bsw/jbe@1309
|
3632 * @private
|
bsw/jbe@1309
|
3633 */
|
bsw/jbe@1309
|
3634 MaterialDataTable.prototype.Constant_ = {};
|
bsw/jbe@1309
|
3635 /**
|
bsw/jbe@1309
|
3636 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
3637 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
3638 * decide to modify at a later date.
|
bsw/jbe@1309
|
3639 *
|
bsw/jbe@1309
|
3640 * @enum {string}
|
bsw/jbe@1309
|
3641 * @private
|
bsw/jbe@1309
|
3642 */
|
bsw/jbe@1309
|
3643 MaterialDataTable.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
3644 DATA_TABLE: 'mdl-data-table',
|
bsw/jbe@1309
|
3645 SELECTABLE: 'mdl-data-table--selectable',
|
bsw/jbe@1309
|
3646 SELECT_ELEMENT: 'mdl-data-table__select',
|
bsw/jbe@1309
|
3647 IS_SELECTED: 'is-selected',
|
bsw/jbe@1309
|
3648 IS_UPGRADED: 'is-upgraded'
|
bsw/jbe@1309
|
3649 };
|
bsw/jbe@1309
|
3650 /**
|
bsw/jbe@1309
|
3651 * Generates and returns a function that toggles the selection state of a
|
bsw/jbe@1309
|
3652 * single row (or multiple rows).
|
bsw/jbe@1309
|
3653 *
|
bsw/jbe@1309
|
3654 * @param {Element} checkbox Checkbox that toggles the selection state.
|
bsw/jbe@1309
|
3655 * @param {Element} row Row to toggle when checkbox changes.
|
bsw/jbe@1309
|
3656 * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
|
bsw/jbe@1309
|
3657 * @private
|
bsw/jbe@1309
|
3658 */
|
bsw/jbe@1309
|
3659 MaterialDataTable.prototype.selectRow_ = function (checkbox, row, opt_rows) {
|
bsw/jbe@1309
|
3660 if (row) {
|
bsw/jbe@1309
|
3661 return function () {
|
bsw/jbe@1309
|
3662 if (checkbox.checked) {
|
bsw/jbe@1309
|
3663 row.classList.add(this.CssClasses_.IS_SELECTED);
|
bsw/jbe@1309
|
3664 } else {
|
bsw/jbe@1309
|
3665 row.classList.remove(this.CssClasses_.IS_SELECTED);
|
bsw/jbe@1309
|
3666 }
|
bsw/jbe@1309
|
3667 }.bind(this);
|
bsw/jbe@1309
|
3668 }
|
bsw/jbe@1309
|
3669 if (opt_rows) {
|
bsw/jbe@1309
|
3670 return function () {
|
bsw/jbe@1309
|
3671 var i;
|
bsw/jbe@1309
|
3672 var el;
|
bsw/jbe@1309
|
3673 if (checkbox.checked) {
|
bsw/jbe@1309
|
3674 for (i = 0; i < opt_rows.length; i++) {
|
bsw/jbe@1309
|
3675 el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
|
bsw/jbe@1309
|
3676 el['MaterialCheckbox'].check();
|
bsw/jbe@1309
|
3677 opt_rows[i].classList.add(this.CssClasses_.IS_SELECTED);
|
bsw/jbe@1309
|
3678 }
|
bsw/jbe@1309
|
3679 } else {
|
bsw/jbe@1309
|
3680 for (i = 0; i < opt_rows.length; i++) {
|
bsw/jbe@1309
|
3681 el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox');
|
bsw/jbe@1309
|
3682 el['MaterialCheckbox'].uncheck();
|
bsw/jbe@1309
|
3683 opt_rows[i].classList.remove(this.CssClasses_.IS_SELECTED);
|
bsw/jbe@1309
|
3684 }
|
bsw/jbe@1309
|
3685 }
|
bsw/jbe@1309
|
3686 }.bind(this);
|
bsw/jbe@1309
|
3687 }
|
bsw/jbe@1309
|
3688 };
|
bsw/jbe@1309
|
3689 /**
|
bsw/jbe@1309
|
3690 * Creates a checkbox for a single or or multiple rows and hooks up the
|
bsw/jbe@1309
|
3691 * event handling.
|
bsw/jbe@1309
|
3692 *
|
bsw/jbe@1309
|
3693 * @param {Element} row Row to toggle when checkbox changes.
|
bsw/jbe@1309
|
3694 * @param {(Array<Object>|NodeList)=} opt_rows Rows to toggle when checkbox changes.
|
bsw/jbe@1309
|
3695 * @private
|
bsw/jbe@1309
|
3696 */
|
bsw/jbe@1309
|
3697 MaterialDataTable.prototype.createCheckbox_ = function (row, opt_rows) {
|
bsw/jbe@1309
|
3698 var label = document.createElement('label');
|
bsw/jbe@1309
|
3699 var labelClasses = [
|
bsw/jbe@1309
|
3700 'mdl-checkbox',
|
bsw/jbe@1309
|
3701 'mdl-js-checkbox',
|
bsw/jbe@1309
|
3702 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
3703 this.CssClasses_.SELECT_ELEMENT
|
bsw/jbe@1309
|
3704 ];
|
bsw/jbe@1309
|
3705 label.className = labelClasses.join(' ');
|
bsw/jbe@1309
|
3706 var checkbox = document.createElement('input');
|
bsw/jbe@1309
|
3707 checkbox.type = 'checkbox';
|
bsw/jbe@1309
|
3708 checkbox.classList.add('mdl-checkbox__input');
|
bsw/jbe@1309
|
3709 if (row) {
|
bsw/jbe@1309
|
3710 checkbox.checked = row.classList.contains(this.CssClasses_.IS_SELECTED);
|
bsw/jbe@1309
|
3711 checkbox.addEventListener('change', this.selectRow_(checkbox, row));
|
bsw/jbe@1309
|
3712 } else if (opt_rows) {
|
bsw/jbe@1309
|
3713 checkbox.addEventListener('change', this.selectRow_(checkbox, null, opt_rows));
|
bsw/jbe@1309
|
3714 }
|
bsw/jbe@1309
|
3715 label.appendChild(checkbox);
|
bsw/jbe@1309
|
3716 componentHandler.upgradeElement(label, 'MaterialCheckbox');
|
bsw/jbe@1309
|
3717 return label;
|
bsw/jbe@1309
|
3718 };
|
bsw/jbe@1309
|
3719 /**
|
bsw/jbe@1309
|
3720 * Initialize element.
|
bsw/jbe@1309
|
3721 */
|
bsw/jbe@1309
|
3722 MaterialDataTable.prototype.init = function () {
|
bsw/jbe@1309
|
3723 if (this.element_) {
|
bsw/jbe@1309
|
3724 var firstHeader = this.element_.querySelector('th');
|
bsw/jbe@1309
|
3725 var bodyRows = Array.prototype.slice.call(this.element_.querySelectorAll('tbody tr'));
|
bsw/jbe@1309
|
3726 var footRows = Array.prototype.slice.call(this.element_.querySelectorAll('tfoot tr'));
|
bsw/jbe@1309
|
3727 var rows = bodyRows.concat(footRows);
|
bsw/jbe@1309
|
3728 if (this.element_.classList.contains(this.CssClasses_.SELECTABLE)) {
|
bsw/jbe@1309
|
3729 var th = document.createElement('th');
|
bsw/jbe@1309
|
3730 var headerCheckbox = this.createCheckbox_(null, rows);
|
bsw/jbe@1309
|
3731 th.appendChild(headerCheckbox);
|
bsw/jbe@1309
|
3732 firstHeader.parentElement.insertBefore(th, firstHeader);
|
bsw/jbe@1309
|
3733 for (var i = 0; i < rows.length; i++) {
|
bsw/jbe@1309
|
3734 var firstCell = rows[i].querySelector('td');
|
bsw/jbe@1309
|
3735 if (firstCell) {
|
bsw/jbe@1309
|
3736 var td = document.createElement('td');
|
bsw/jbe@1309
|
3737 if (rows[i].parentNode.nodeName.toUpperCase() === 'TBODY') {
|
bsw/jbe@1309
|
3738 var rowCheckbox = this.createCheckbox_(rows[i]);
|
bsw/jbe@1309
|
3739 td.appendChild(rowCheckbox);
|
bsw/jbe@1309
|
3740 }
|
bsw/jbe@1309
|
3741 rows[i].insertBefore(td, firstCell);
|
bsw/jbe@1309
|
3742 }
|
bsw/jbe@1309
|
3743 }
|
bsw/jbe@1309
|
3744 this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
|
bsw/jbe@1309
|
3745 }
|
bsw/jbe@1309
|
3746 }
|
bsw/jbe@1309
|
3747 };
|
bsw/jbe@1309
|
3748 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
3749 // in the global scope.
|
bsw/jbe@1309
|
3750 componentHandler.register({
|
bsw/jbe@1309
|
3751 constructor: MaterialDataTable,
|
bsw/jbe@1309
|
3752 classAsString: 'MaterialDataTable',
|
bsw/jbe@1309
|
3753 cssClass: 'mdl-js-data-table'
|
bsw/jbe@1309
|
3754 });
|
bsw/jbe@1309
|
3755 /**
|
bsw/jbe@1309
|
3756 * @license
|
bsw/jbe@1309
|
3757 * Copyright 2015 Google Inc. All Rights Reserved.
|
bsw/jbe@1309
|
3758 *
|
bsw/jbe@1309
|
3759 * Licensed under the Apache License, Version 2.0 (the "License");
|
bsw/jbe@1309
|
3760 * you may not use this file except in compliance with the License.
|
bsw/jbe@1309
|
3761 * You may obtain a copy of the License at
|
bsw/jbe@1309
|
3762 *
|
bsw/jbe@1309
|
3763 * http://www.apache.org/licenses/LICENSE-2.0
|
bsw/jbe@1309
|
3764 *
|
bsw/jbe@1309
|
3765 * Unless required by applicable law or agreed to in writing, software
|
bsw/jbe@1309
|
3766 * distributed under the License is distributed on an "AS IS" BASIS,
|
bsw/jbe@1309
|
3767 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
bsw/jbe@1309
|
3768 * See the License for the specific language governing permissions and
|
bsw/jbe@1309
|
3769 * limitations under the License.
|
bsw/jbe@1309
|
3770 */
|
bsw/jbe@1309
|
3771 /**
|
bsw/jbe@1309
|
3772 * Class constructor for Ripple MDL component.
|
bsw/jbe@1309
|
3773 * Implements MDL component design pattern defined at:
|
bsw/jbe@1309
|
3774 * https://github.com/jasonmayes/mdl-component-design-pattern
|
bsw/jbe@1309
|
3775 *
|
bsw/jbe@1309
|
3776 * @constructor
|
bsw/jbe@1309
|
3777 * @param {HTMLElement} element The element that will be upgraded.
|
bsw/jbe@1309
|
3778 */
|
bsw/jbe@1309
|
3779 var MaterialRipple = function MaterialRipple(element) {
|
bsw/jbe@1309
|
3780 this.element_ = element;
|
bsw/jbe@1309
|
3781 // Initialize instance.
|
bsw/jbe@1309
|
3782 this.init();
|
bsw/jbe@1309
|
3783 };
|
bsw/jbe@1309
|
3784 window['MaterialRipple'] = MaterialRipple;
|
bsw/jbe@1309
|
3785 /**
|
bsw/jbe@1309
|
3786 * Store constants in one place so they can be updated easily.
|
bsw/jbe@1309
|
3787 *
|
bsw/jbe@1309
|
3788 * @enum {string | number}
|
bsw/jbe@1309
|
3789 * @private
|
bsw/jbe@1309
|
3790 */
|
bsw/jbe@1309
|
3791 MaterialRipple.prototype.Constant_ = {
|
bsw/jbe@1309
|
3792 INITIAL_SCALE: 'scale(0.0001, 0.0001)',
|
bsw/jbe@1309
|
3793 INITIAL_SIZE: '1px',
|
bsw/jbe@1309
|
3794 INITIAL_OPACITY: '0.4',
|
bsw/jbe@1309
|
3795 FINAL_OPACITY: '0',
|
bsw/jbe@1309
|
3796 FINAL_SCALE: ''
|
bsw/jbe@1309
|
3797 };
|
bsw/jbe@1309
|
3798 /**
|
bsw/jbe@1309
|
3799 * Store strings for class names defined by this component that are used in
|
bsw/jbe@1309
|
3800 * JavaScript. This allows us to simply change it in one place should we
|
bsw/jbe@1309
|
3801 * decide to modify at a later date.
|
bsw/jbe@1309
|
3802 *
|
bsw/jbe@1309
|
3803 * @enum {string}
|
bsw/jbe@1309
|
3804 * @private
|
bsw/jbe@1309
|
3805 */
|
bsw/jbe@1309
|
3806 MaterialRipple.prototype.CssClasses_ = {
|
bsw/jbe@1309
|
3807 RIPPLE_CENTER: 'mdl-ripple--center',
|
bsw/jbe@1309
|
3808 RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
|
bsw/jbe@1309
|
3809 RIPPLE: 'mdl-ripple',
|
bsw/jbe@1309
|
3810 IS_ANIMATING: 'is-animating',
|
bsw/jbe@1309
|
3811 IS_VISIBLE: 'is-visible'
|
bsw/jbe@1309
|
3812 };
|
bsw/jbe@1309
|
3813 /**
|
bsw/jbe@1309
|
3814 * Handle mouse / finger down on element.
|
bsw/jbe@1309
|
3815 *
|
bsw/jbe@1309
|
3816 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
3817 * @private
|
bsw/jbe@1309
|
3818 */
|
bsw/jbe@1309
|
3819 MaterialRipple.prototype.downHandler_ = function (event) {
|
bsw/jbe@1309
|
3820 if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) {
|
bsw/jbe@1309
|
3821 var rect = this.element_.getBoundingClientRect();
|
bsw/jbe@1309
|
3822 this.boundHeight = rect.height;
|
bsw/jbe@1309
|
3823 this.boundWidth = rect.width;
|
bsw/jbe@1309
|
3824 this.rippleSize_ = Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2;
|
bsw/jbe@1309
|
3825 this.rippleElement_.style.width = this.rippleSize_ + 'px';
|
bsw/jbe@1309
|
3826 this.rippleElement_.style.height = this.rippleSize_ + 'px';
|
bsw/jbe@1309
|
3827 }
|
bsw/jbe@1309
|
3828 this.rippleElement_.classList.add(this.CssClasses_.IS_VISIBLE);
|
bsw/jbe@1309
|
3829 if (event.type === 'mousedown' && this.ignoringMouseDown_) {
|
bsw/jbe@1309
|
3830 this.ignoringMouseDown_ = false;
|
bsw/jbe@1309
|
3831 } else {
|
bsw/jbe@1309
|
3832 if (event.type === 'touchstart') {
|
bsw/jbe@1309
|
3833 this.ignoringMouseDown_ = true;
|
bsw/jbe@1309
|
3834 }
|
bsw/jbe@1309
|
3835 var frameCount = this.getFrameCount();
|
bsw/jbe@1309
|
3836 if (frameCount > 0) {
|
bsw/jbe@1309
|
3837 return;
|
bsw/jbe@1309
|
3838 }
|
bsw/jbe@1309
|
3839 this.setFrameCount(1);
|
bsw/jbe@1309
|
3840 var bound = event.currentTarget.getBoundingClientRect();
|
bsw/jbe@1309
|
3841 var x;
|
bsw/jbe@1309
|
3842 var y;
|
bsw/jbe@1309
|
3843 // Check if we are handling a keyboard click.
|
bsw/jbe@1309
|
3844 if (event.clientX === 0 && event.clientY === 0) {
|
bsw/jbe@1309
|
3845 x = Math.round(bound.width / 2);
|
bsw/jbe@1309
|
3846 y = Math.round(bound.height / 2);
|
bsw/jbe@1309
|
3847 } else {
|
bsw/jbe@1309
|
3848 var clientX = event.clientX ? event.clientX : event.touches[0].clientX;
|
bsw/jbe@1309
|
3849 var clientY = event.clientY ? event.clientY : event.touches[0].clientY;
|
bsw/jbe@1309
|
3850 x = Math.round(clientX - bound.left);
|
bsw/jbe@1309
|
3851 y = Math.round(clientY - bound.top);
|
bsw/jbe@1309
|
3852 }
|
bsw/jbe@1309
|
3853 this.setRippleXY(x, y);
|
bsw/jbe@1309
|
3854 this.setRippleStyles(true);
|
bsw/jbe@1309
|
3855 window.requestAnimationFrame(this.animFrameHandler.bind(this));
|
bsw/jbe@1309
|
3856 }
|
bsw/jbe@1309
|
3857 };
|
bsw/jbe@1309
|
3858 /**
|
bsw/jbe@1309
|
3859 * Handle mouse / finger up on element.
|
bsw/jbe@1309
|
3860 *
|
bsw/jbe@1309
|
3861 * @param {Event} event The event that fired.
|
bsw/jbe@1309
|
3862 * @private
|
bsw/jbe@1309
|
3863 */
|
bsw/jbe@1309
|
3864 MaterialRipple.prototype.upHandler_ = function (event) {
|
bsw/jbe@1309
|
3865 // Don't fire for the artificial "mouseup" generated by a double-click.
|
bsw/jbe@1309
|
3866 if (event && event.detail !== 2) {
|
bsw/jbe@1309
|
3867 // Allow a repaint to occur before removing this class, so the animation
|
bsw/jbe@1309
|
3868 // shows for tap events, which seem to trigger a mouseup too soon after
|
bsw/jbe@1309
|
3869 // mousedown.
|
bsw/jbe@1309
|
3870 window.setTimeout(function () {
|
bsw/jbe@1309
|
3871 this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE);
|
bsw/jbe@1309
|
3872 }.bind(this), 0);
|
bsw/jbe@1309
|
3873 }
|
bsw/jbe@1309
|
3874 };
|
bsw/jbe@1309
|
3875 /**
|
bsw/jbe@1309
|
3876 * Initialize element.
|
bsw/jbe@1309
|
3877 */
|
bsw/jbe@1309
|
3878 MaterialRipple.prototype.init = function () {
|
bsw/jbe@1309
|
3879 if (this.element_) {
|
bsw/jbe@1309
|
3880 var recentering = this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER);
|
bsw/jbe@1309
|
3881 if (!this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)) {
|
bsw/jbe@1309
|
3882 this.rippleElement_ = this.element_.querySelector('.' + this.CssClasses_.RIPPLE);
|
bsw/jbe@1309
|
3883 this.frameCount_ = 0;
|
bsw/jbe@1309
|
3884 this.rippleSize_ = 0;
|
bsw/jbe@1309
|
3885 this.x_ = 0;
|
bsw/jbe@1309
|
3886 this.y_ = 0;
|
bsw/jbe@1309
|
3887 // Touch start produces a compat mouse down event, which would cause a
|
bsw/jbe@1309
|
3888 // second ripples. To avoid that, we use this property to ignore the first
|
bsw/jbe@1309
|
3889 // mouse down after a touch start.
|
bsw/jbe@1309
|
3890 this.ignoringMouseDown_ = false;
|
bsw/jbe@1309
|
3891 this.boundDownHandler = this.downHandler_.bind(this);
|
bsw/jbe@1309
|
3892 this.element_.addEventListener('mousedown', this.boundDownHandler);
|
bsw/jbe@1309
|
3893 this.element_.addEventListener('touchstart', this.boundDownHandler);
|
bsw/jbe@1309
|
3894 this.boundUpHandler = this.upHandler_.bind(this);
|
bsw/jbe@1309
|
3895 this.element_.addEventListener('mouseup', this.boundUpHandler);
|
bsw/jbe@1309
|
3896 this.element_.addEventListener('mouseleave', this.boundUpHandler);
|
bsw/jbe@1309
|
3897 this.element_.addEventListener('touchend', this.boundUpHandler);
|
bsw/jbe@1309
|
3898 this.element_.addEventListener('blur', this.boundUpHandler);
|
bsw/jbe@1309
|
3899 /**
|
bsw/jbe@1309
|
3900 * Getter for frameCount_.
|
bsw/jbe@1309
|
3901 * @return {number} the frame count.
|
bsw/jbe@1309
|
3902 */
|
bsw/jbe@1309
|
3903 this.getFrameCount = function () {
|
bsw/jbe@1309
|
3904 return this.frameCount_;
|
bsw/jbe@1309
|
3905 };
|
bsw/jbe@1309
|
3906 /**
|
bsw/jbe@1309
|
3907 * Setter for frameCount_.
|
bsw/jbe@1309
|
3908 * @param {number} fC the frame count.
|
bsw/jbe@1309
|
3909 */
|
bsw/jbe@1309
|
3910 this.setFrameCount = function (fC) {
|
bsw/jbe@1309
|
3911 this.frameCount_ = fC;
|
bsw/jbe@1309
|
3912 };
|
bsw/jbe@1309
|
3913 /**
|
bsw/jbe@1309
|
3914 * Getter for rippleElement_.
|
bsw/jbe@1309
|
3915 * @return {Element} the ripple element.
|
bsw/jbe@1309
|
3916 */
|
bsw/jbe@1309
|
3917 this.getRippleElement = function () {
|
bsw/jbe@1309
|
3918 return this.rippleElement_;
|
bsw/jbe@1309
|
3919 };
|
bsw/jbe@1309
|
3920 /**
|
bsw/jbe@1309
|
3921 * Sets the ripple X and Y coordinates.
|
bsw/jbe@1309
|
3922 * @param {number} newX the new X coordinate
|
bsw/jbe@1309
|
3923 * @param {number} newY the new Y coordinate
|
bsw/jbe@1309
|
3924 */
|
bsw/jbe@1309
|
3925 this.setRippleXY = function (newX, newY) {
|
bsw/jbe@1309
|
3926 this.x_ = newX;
|
bsw/jbe@1309
|
3927 this.y_ = newY;
|
bsw/jbe@1309
|
3928 };
|
bsw/jbe@1309
|
3929 /**
|
bsw/jbe@1309
|
3930 * Sets the ripple styles.
|
bsw/jbe@1309
|
3931 * @param {boolean} start whether or not this is the start frame.
|
bsw/jbe@1309
|
3932 */
|
bsw/jbe@1309
|
3933 this.setRippleStyles = function (start) {
|
bsw/jbe@1309
|
3934 if (this.rippleElement_ !== null) {
|
bsw/jbe@1309
|
3935 var transformString;
|
bsw/jbe@1309
|
3936 var scale;
|
bsw/jbe@1309
|
3937 var size;
|
bsw/jbe@1309
|
3938 var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)';
|
bsw/jbe@1309
|
3939 if (start) {
|
bsw/jbe@1309
|
3940 scale = this.Constant_.INITIAL_SCALE;
|
bsw/jbe@1309
|
3941 size = this.Constant_.INITIAL_SIZE;
|
bsw/jbe@1309
|
3942 } else {
|
bsw/jbe@1309
|
3943 scale = this.Constant_.FINAL_SCALE;
|
bsw/jbe@1309
|
3944 size = this.rippleSize_ + 'px';
|
bsw/jbe@1309
|
3945 if (recentering) {
|
bsw/jbe@1309
|
3946 offset = 'translate(' + this.boundWidth / 2 + 'px, ' + this.boundHeight / 2 + 'px)';
|
bsw/jbe@1309
|
3947 }
|
bsw/jbe@1309
|
3948 }
|
bsw/jbe@1309
|
3949 transformString = 'translate(-50%, -50%) ' + offset + scale;
|
bsw/jbe@1309
|
3950 this.rippleElement_.style.webkitTransform = transformString;
|
bsw/jbe@1309
|
3951 this.rippleElement_.style.msTransform = transformString;
|
bsw/jbe@1309
|
3952 this.rippleElement_.style.transform = transformString;
|
bsw/jbe@1309
|
3953 if (start) {
|
bsw/jbe@1309
|
3954 this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
3955 } else {
|
bsw/jbe@1309
|
3956 this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING);
|
bsw/jbe@1309
|
3957 }
|
bsw/jbe@1309
|
3958 }
|
bsw/jbe@1309
|
3959 };
|
bsw/jbe@1309
|
3960 /**
|
bsw/jbe@1309
|
3961 * Handles an animation frame.
|
bsw/jbe@1309
|
3962 */
|
bsw/jbe@1309
|
3963 this.animFrameHandler = function () {
|
bsw/jbe@1309
|
3964 if (this.frameCount_-- > 0) {
|
bsw/jbe@1309
|
3965 window.requestAnimationFrame(this.animFrameHandler.bind(this));
|
bsw/jbe@1309
|
3966 } else {
|
bsw/jbe@1309
|
3967 this.setRippleStyles(false);
|
bsw/jbe@1309
|
3968 }
|
bsw/jbe@1309
|
3969 };
|
bsw/jbe@1309
|
3970 }
|
bsw/jbe@1309
|
3971 }
|
bsw/jbe@1309
|
3972 };
|
bsw/jbe@1309
|
3973 // The component registers itself. It can assume componentHandler is available
|
bsw/jbe@1309
|
3974 // in the global scope.
|
bsw/jbe@1309
|
3975 componentHandler.register({
|
bsw/jbe@1309
|
3976 constructor: MaterialRipple,
|
bsw/jbe@1309
|
3977 classAsString: 'MaterialRipple',
|
bsw/jbe@1309
|
3978 cssClass: 'mdl-js-ripple-effect',
|
bsw/jbe@1309
|
3979 widget: false
|
bsw/jbe@1309
|
3980 });
|
bsw/jbe@1309
|
3981 }());
|