vendor/assets/javascripts/material.js in material_design_lite-rails-1.0.2 vs vendor/assets/javascripts/material.js in material_design_lite-rails-1.0.3

- old
+ new

@@ -1,5 +1,8 @@ +;(function() { +"use strict"; + /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,27 +20,33 @@ /** * A component handler interface using the revealing module design pattern. * More details on this design pattern here: * https://github.com/jasonmayes/mdl-component-design-pattern + * * @author Jason Mayes. */ /* exported componentHandler */ -var componentHandler = (function() { +window.componentHandler = (function() { 'use strict'; + /** @type {!Array<componentHandler.ComponentConfig>} */ var registeredComponents_ = []; + + /** @type {!Array<componentHandler.Component>} */ var createdComponents_ = []; + var downgradeMethod_ = 'mdlDowngrade_'; var componentConfigProperty_ = 'mdlComponentConfigInternal_'; /** * Searches registered components for a class we are interested in using. * Optionally replaces a match with passed object if specified. - * @param {string} name The name of a class we want to use. - * @param {Object=} optReplace Optional object to replace match with. - * @return {Object | boolean} + * + * @param {String} name The name of a class we want to use. + * @param {componentHandler.ComponentConfig=} optReplace Optional object to replace match with. + * @return {!Object|Boolean} * @private */ function findRegisteredClass_(name, optReplace) { for (var i = 0; i < registeredComponents_.length; i++) { if (registeredComponents_[i].className === name) { @@ -50,12 +59,13 @@ return false; } /** * Returns an array of the classNames of the upgraded classes on the element. - * @param {HTMLElement} element The element to fetch data from. - * @return {Array<string>} + * + * @param {!HTMLElement} element The element to fetch data from. + * @return {!Array<String>} * @private */ function getUpgradedListOfElement_(element) { var dataUpgraded = element.getAttribute('data-upgraded'); // Use `['']` as default value to conform the `,name,name...` style. @@ -63,36 +73,38 @@ } /** * Returns true if the given element has already been upgraded for the given * class. - * @param {HTMLElement} element The element we want to check. - * @param {string} jsClass The class to check for. - * @return boolean + * + * @param {!HTMLElement} element The element we want to check. + * @param {String} jsClass The class to check for. + * @returns {Boolean} * @private */ function isElementUpgraded_(element, jsClass) { var upgradedList = getUpgradedListOfElement_(element); return upgradedList.indexOf(jsClass) !== -1; } /** * Searches existing DOM for elements of our component type and upgrades them * if they have not already been upgraded. - * @param {!string=} optJsClass the programatic name of the element class we + * + * @param {String=} optJsClass the programatic name of the element class we * need to create a new instance of. - * @param {!string=} optCssClass the name of the CSS class elements of this + * @param {String=} optCssClass the name of the CSS class elements of this * type will have. */ function upgradeDomInternal(optJsClass, optCssClass) { if (optJsClass === undefined && optCssClass === undefined) { for (var i = 0; i < registeredComponents_.length; i++) { upgradeDomInternal(registeredComponents_[i].className, registeredComponents_[i].cssClass); } } else { - var jsClass = /** @type {!string} */ (optJsClass); + var jsClass = /** @type {String} */ (optJsClass); if (optCssClass === undefined) { var registeredClass = findRegisteredClass_(jsClass); if (registeredClass) { optCssClass = registeredClass.cssClass; } @@ -105,12 +117,13 @@ } } /** * Upgrades a specific element rather than all in the DOM. - * @param {HTMLElement} element The element we wish to upgrade. - * @param {!string=} optJsClass Optional name of the class we want to upgrade + * + * @param {!HTMLElement} element The element we wish to upgrade. + * @param {String=} optJsClass Optional name of the class we want to upgrade * the element to. */ function upgradeElementInternal(element, optJsClass) { // Verify argument type. if (!(typeof element === 'object' && element instanceof Element)) { @@ -120,11 +133,11 @@ var classesToUpgrade = []; // If jsClass is not provided scan the registered components to find the // ones matching the element's CSS classList. if (!optJsClass) { var classList = element.classList; - registeredComponents_.forEach(function (component) { + registeredComponents_.forEach(function(component) { // Match CSS & Not to be upgraded & Not upgraded. if (classList.contains(component.cssClass) && classesToUpgrade.indexOf(component) === -1 && !isElementUpgraded_(element, component.className)) { classesToUpgrade.push(component); @@ -164,17 +177,18 @@ } } /** * Upgrades a specific list of elements rather than all in the DOM. - * @param {HTMLElement | Array<HTMLElement> | NodeList | HTMLCollection} elements + * + * @param {!HTMLElement|!Array<!HTMLElement>|!NodeList|!HTMLCollection} elements * The elements we wish to upgrade. */ function upgradeElementsInternal(elements) { if (!Array.isArray(elements)) { if (typeof elements.item === 'function') { - elements = Array.prototype.slice.call(elements); + elements = Array.prototype.slice.call(/** @type {Array} */ (elements)); } else { elements = [elements]; } } for (var i = 0, n = elements.length, element; i < n; i++) { @@ -188,21 +202,21 @@ } } /** * Registers a class for future use and attempts to upgrade existing DOM. - * @param {Object} config An object containing: - * {constructor: Constructor, classAsString: string, cssClass: string} + * + * @param {{constructor: !Function, classAsString: String, cssClass: String, widget: String}} config */ function registerInternal(config) { - var newConfig = { + var newConfig = /** @type {componentHandler.ComponentConfig} */ ({ 'classConstructor': config.constructor, 'className': config.classAsString, 'cssClass': config.cssClass, 'widget': config.widget === undefined ? true : config.widget, 'callbacks': [] - }; + }); registeredComponents_.forEach(function(item) { if (item.cssClass === newConfig.cssClass) { throw new Error('The provided cssClass has already been registered.'); } @@ -212,11 +226,11 @@ }); if (config.constructor.prototype .hasOwnProperty(componentConfigProperty_)) { throw new Error( - 'MDL component classes must not have ' + componentConfigProperty_ + + 'MDL component classes must not have ' + componentConfigProperty_ + ' defined as a property.'); } var found = findRegisteredClass_(config.classAsString, newConfig); @@ -226,14 +240,16 @@ } /** * Allows user to be alerted to any upgrades that are performed for a given * component type - * @param {string} jsClass The class name of the MDL component we wish + * + * @param {String} jsClass The class name of the MDL component we wish * to hook into for any upgrades performed. - * @param {!Function} callback The function to call upon an upgrade. This - * function should expect 1 parameter - the HTMLElement which got upgraded. + * @param {function(!HTMLElement)} callback The function to call upon an + * upgrade. This function should expect 1 parameter - the HTMLElement which + * got upgraded. */ function registerUpgradedCallbackInternal(jsClass, callback) { var regClass = findRegisteredClass_(jsClass); if (regClass) { regClass.callbacks.push(callback); @@ -251,11 +267,11 @@ } /** * Finds a created component by a given DOM node. * - * @param {!Element} node + * @param {!Node} node * @return {*} */ function findCreatedComponentByNodeInternal(node) { for (var n = 0; n < createdComponents_.length; n++) { var component = createdComponents_[n]; @@ -294,11 +310,11 @@ } /** * Downgrade either a given node, an array of nodes, or a NodeList. * - * @param {*} nodes + * @param {!Node|!Array<!Node>|!NodeList} nodes */ function downgradeNodesInternal(nodes) { var downgradeNode = function(node) { deconstructComponentInternal(findCreatedComponentByNodeInternal(node)); }; @@ -343,49 +359,70 @@ componentHandler.upgradeElement = componentHandler.register = function() {}; } }); +/** + * Describes the type of a registered component type managed by + * componentHandler. Provided for benefit of the Closure compiler. + * + * @typedef {{ + * constructor: !Function, + * className: String, + * cssClass: String, + * widget: String, + * callbacks: !Array<function(!HTMLElement)> + * }} + */ +componentHandler.ComponentConfig; // jshint ignore:line + +/** + * Created component (i.e., upgraded element) type as managed by + * componentHandler. Provided for benefit of the Closure compiler. + * + * @typedef {{ + * element_: !HTMLElement, + * className: String, + * classAsString: String, + * cssClass: String, + * widget: String + * }} + */ +componentHandler.Component; // jshint ignore:line + // Source: https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js // Adapted from https://gist.github.com/paulirish/1579671 which derived from // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating - // requestAnimationFrame polyfill by Erik Möller. // Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon - // MIT license - -(function() { -'use strict'; - if (!Date.now) { - Date.now = function() { return new Date().getTime(); }; + Date.now = function () { + return new Date().getTime(); + }; } - -var vendors = ['webkit', 'moz']; +var vendors = [ + 'webkit', + 'moz' +]; for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { - var vp = vendors[i]; - window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; - window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame'] || - window[vp + 'CancelRequestAnimationFrame']); + var vp = vendors[i]; + window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame']; } - if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) { - var lastTime = 0; - window.requestAnimationFrame = function(callback) { - var now = Date.now(); - var nextTime = Math.max(lastTime + 16, now); - return setTimeout(function() { callback(lastTime = nextTime); }, - nextTime - now); + var lastTime = 0; + window.requestAnimationFrame = function (callback) { + var now = Date.now(); + var nextTime = Math.max(lastTime + 16, now); + return setTimeout(function () { + callback(lastTime = nextTime); + }, nextTime - now); }; - window.cancelAnimationFrame = clearTimeout; + window.cancelAnimationFrame = clearTimeout; } - -})(); - - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -398,127 +435,111 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Button MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialButton(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialButton.prototype.Constant_ = { - // None for now. + * Class constructor for Button MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialButton = function MaterialButton(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialButton = MaterialButton; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialButton.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialButton.prototype.CssClasses_ = { - RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_CONTAINER: 'mdl-button__ripple-container', - RIPPLE: 'mdl-ripple' + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_CONTAINER: 'mdl-button__ripple-container', + RIPPLE: 'mdl-ripple' }; - /** - * Handle blur of element. - * @param {HTMLElement} element The instance of a button we want to blur. - * @private - */ -MaterialButton.prototype.blurHandler = function(event) { - 'use strict'; - - if (event) { - this.element_.blur(); - } + * Handle blur of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialButton.prototype.blurHandler_ = function (event) { + if (event) { + this.element_.blur(); + } }; - // Public methods. - /** - * Disable button. - * @public - */ -MaterialButton.prototype.disable = function() { - 'use strict'; - - this.element_.disabled = true; + * Disable button. + * + * @public + */ +MaterialButton.prototype.disable = function () { + this.element_.disabled = true; }; - /** - * Enable button. - * @public - */ -MaterialButton.prototype.enable = function() { - 'use strict'; - - this.element_.disabled = false; + * Enable button. + * + * @public + */ +MaterialButton.prototype.enable = function () { + this.element_.disabled = false; }; - /** - * Initialize element. - */ -MaterialButton.prototype.init = function() { - 'use strict'; - - if (this.element_) { - if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { - var rippleContainer = document.createElement('span'); - rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER); - this.rippleElement_ = document.createElement('span'); - this.rippleElement_.classList.add(this.CssClasses_.RIPPLE); - rippleContainer.appendChild(this.rippleElement_); - this.boundRippleBlurHandler = this.blurHandler.bind(this); - this.rippleElement_.addEventListener('mouseup', this.boundRippleBlurHandler); - this.element_.appendChild(rippleContainer); + * Initialize element. + */ +MaterialButton.prototype.init = function () { + if (this.element_) { + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleElement_ = document.createElement('span'); + this.rippleElement_.classList.add(this.CssClasses_.RIPPLE); + rippleContainer.appendChild(this.rippleElement_); + this.boundRippleBlurHandler = this.blurHandler_.bind(this); + this.rippleElement_.addEventListener('mouseup', this.boundRippleBlurHandler); + this.element_.appendChild(rippleContainer); + } + this.boundButtonBlurHandler = this.blurHandler_.bind(this); + this.element_.addEventListener('mouseup', this.boundButtonBlurHandler); + this.element_.addEventListener('mouseleave', this.boundButtonBlurHandler); } - this.boundButtonBlurHandler = this.blurHandler.bind(this); - this.element_.addEventListener('mouseup', this.boundButtonBlurHandler); - this.element_.addEventListener('mouseleave', this.boundButtonBlurHandler); - } }; - /** - * Downgrade the element. - */ -MaterialButton.prototype.mdlDowngrade_ = function() { - 'use strict'; - if (this.rippleElement_) { - this.rippleElement_.removeEventListener('mouseup', this.boundRippleBlurHandler); - } - this.element_.removeEventListener('mouseup', this.boundButtonBlurHandler); - this.element_.removeEventListener('mouseleave', this.boundButtonBlurHandler); + * Downgrade the element. + * + * @private + */ +MaterialButton.prototype.mdlDowngrade_ = function () { + if (this.rippleElement_) { + this.rippleElement_.removeEventListener('mouseup', this.boundRippleBlurHandler); + } + this.element_.removeEventListener('mouseup', this.boundButtonBlurHandler); + this.element_.removeEventListener('mouseleave', this.boundButtonBlurHandler); }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialButton, - classAsString: 'MaterialButton', - cssClass: 'mdl-js-button', - widget: true + constructor: MaterialButton, + classAsString: 'MaterialButton', + cssClass: 'mdl-js-button', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -531,276 +552,234 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Checkbox MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialCheckbox(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialCheckbox.prototype.Constant_ = { - TINY_TIMEOUT: 0.001 + * Class constructor for Checkbox MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialCheckbox = function MaterialCheckbox(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialCheckbox = MaterialCheckbox; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialCheckbox.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialCheckbox.prototype.CssClasses_ = { - INPUT: 'mdl-checkbox__input', - BOX_OUTLINE: 'mdl-checkbox__box-outline', - FOCUS_HELPER: 'mdl-checkbox__focus-helper', - TICK_OUTLINE: 'mdl-checkbox__tick-outline', - RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', - RIPPLE_CONTAINER: 'mdl-checkbox__ripple-container', - RIPPLE_CENTER: 'mdl-ripple--center', - RIPPLE: 'mdl-ripple', - IS_FOCUSED: 'is-focused', - IS_DISABLED: 'is-disabled', - IS_CHECKED: 'is-checked', - IS_UPGRADED: 'is-upgraded' + INPUT: 'mdl-checkbox__input', + BOX_OUTLINE: 'mdl-checkbox__box-outline', + FOCUS_HELPER: 'mdl-checkbox__focus-helper', + TICK_OUTLINE: 'mdl-checkbox__tick-outline', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-checkbox__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked', + IS_UPGRADED: 'is-upgraded' }; - /** - * Handle change of state. - * @param {Event} event The event that fired. - * @private - */ -MaterialCheckbox.prototype.onChange_ = function(event) { - 'use strict'; - - this.updateClasses_(); + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onChange_ = function (event) { + this.updateClasses_(); }; - /** - * Handle focus of element. - * @param {Event} event The event that fired. - * @private - */ -MaterialCheckbox.prototype.onFocus_ = function(event) { - 'use strict'; - - this.element_.classList.add(this.CssClasses_.IS_FOCUSED); + * Handle focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle lost focus of element. - * @param {Event} event The event that fired. - * @private - */ -MaterialCheckbox.prototype.onBlur_ = function(event) { - 'use strict'; - - this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); + * Handle lost focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle mouseup. - * @param {Event} event The event that fired. - * @private - */ -MaterialCheckbox.prototype.onMouseUp_ = function(event) { - 'use strict'; - - this.blur_(); + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onMouseUp_ = function (event) { + this.blur_(); }; - /** - * Handle class updates. - * @param {HTMLElement} button The button whose classes we should update. - * @param {HTMLElement} label The label whose classes we should update. - * @private - */ -MaterialCheckbox.prototype.updateClasses_ = function() { - 'use strict'; - this.checkDisabled(); - this.checkToggleState(); + * Handle class updates. + * + * @private + */ +MaterialCheckbox.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); }; - /** - * Add blur. - * @private - */ -MaterialCheckbox.prototype.blur_ = function(event) { - 'use strict'; - - // TODO: figure out why there's a focus event being fired after our blur, - // so that we can avoid this hack. - window.setTimeout(function() { - this.inputElement_.blur(); - }.bind(this), this.Constant_.TINY_TIMEOUT); + * Add blur. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.blur_ = function (event) { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.inputElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); }; - // Public methods. - /** -* Check the inputs toggle state and update display. -* @public -*/ -MaterialCheckbox.prototype.checkToggleState = function() { - 'use strict'; - if (this.inputElement_.checked) { - this.element_.classList.add(this.CssClasses_.IS_CHECKED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_CHECKED); - } + * Check the inputs toggle state and update display. + * + * @public + */ +MaterialCheckbox.prototype.checkToggleState = function () { + if (this.inputElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } }; - /** -* Check the inputs disabled state and update display. -* @public -*/ -MaterialCheckbox.prototype.checkDisabled = function() { - 'use strict'; - if (this.inputElement_.disabled) { - this.element_.classList.add(this.CssClasses_.IS_DISABLED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_DISABLED); - } + * Check the inputs disabled state and update display. + * + * @public + */ +MaterialCheckbox.prototype.checkDisabled = function () { + if (this.inputElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } }; - /** - * Disable checkbox. - * @public - */ -MaterialCheckbox.prototype.disable = function() { - 'use strict'; - - this.inputElement_.disabled = true; - this.updateClasses_(); + * Disable checkbox. + * + * @public + */ +MaterialCheckbox.prototype.disable = function () { + this.inputElement_.disabled = true; + this.updateClasses_(); }; - /** - * Enable checkbox. - * @public - */ -MaterialCheckbox.prototype.enable = function() { - 'use strict'; - - this.inputElement_.disabled = false; - this.updateClasses_(); + * Enable checkbox. + * + * @public + */ +MaterialCheckbox.prototype.enable = function () { + this.inputElement_.disabled = false; + this.updateClasses_(); }; - /** - * Check checkbox. - * @public - */ -MaterialCheckbox.prototype.check = function() { - 'use strict'; - - this.inputElement_.checked = true; - this.updateClasses_(); + * Check checkbox. + * + * @public + */ +MaterialCheckbox.prototype.check = function () { + this.inputElement_.checked = true; + this.updateClasses_(); }; - /** - * Uncheck checkbox. - * @public - */ -MaterialCheckbox.prototype.uncheck = function() { - 'use strict'; - - this.inputElement_.checked = false; - this.updateClasses_(); + * Uncheck checkbox. + * + * @public + */ +MaterialCheckbox.prototype.uncheck = function () { + this.inputElement_.checked = false; + this.updateClasses_(); }; - /** - * Initialize element. - */ -MaterialCheckbox.prototype.init = function() { - 'use strict'; - - if (this.element_) { - this.inputElement_ = this.element_.querySelector('.' + - this.CssClasses_.INPUT); - - var boxOutline = document.createElement('span'); - boxOutline.classList.add(this.CssClasses_.BOX_OUTLINE); - - var tickContainer = document.createElement('span'); - tickContainer.classList.add(this.CssClasses_.FOCUS_HELPER); - - var tickOutline = document.createElement('span'); - tickOutline.classList.add(this.CssClasses_.TICK_OUTLINE); - - boxOutline.appendChild(tickOutline); - - this.element_.appendChild(tickContainer); - this.element_.appendChild(boxOutline); - - if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { - this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); - this.rippleContainerElement_ = document.createElement('span'); - this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); - this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT); - this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); - this.boundRippleMouseUp = this.onMouseUp_.bind(this); - this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp); - - var ripple = document.createElement('span'); - ripple.classList.add(this.CssClasses_.RIPPLE); - - this.rippleContainerElement_.appendChild(ripple); - this.element_.appendChild(this.rippleContainerElement_); + * Initialize element. + */ +MaterialCheckbox.prototype.init = function () { + if (this.element_) { + this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + var boxOutline = document.createElement('span'); + boxOutline.classList.add(this.CssClasses_.BOX_OUTLINE); + var tickContainer = document.createElement('span'); + tickContainer.classList.add(this.CssClasses_.FOCUS_HELPER); + var tickOutline = document.createElement('span'); + tickOutline.classList.add(this.CssClasses_.TICK_OUTLINE); + boxOutline.appendChild(tickOutline); + this.element_.appendChild(tickContainer); + this.element_.appendChild(boxOutline); + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + this.rippleContainerElement_ = document.createElement('span'); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); + this.boundRippleMouseUp = this.onMouseUp_.bind(this); + this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + this.rippleContainerElement_.appendChild(ripple); + this.element_.appendChild(this.rippleContainerElement_); + } + this.boundInputOnChange = this.onChange_.bind(this); + this.boundInputOnFocus = this.onFocus_.bind(this); + this.boundInputOnBlur = this.onBlur_.bind(this); + this.boundElementMouseUp = this.onMouseUp_.bind(this); + this.inputElement_.addEventListener('change', this.boundInputOnChange); + this.inputElement_.addEventListener('focus', this.boundInputOnFocus); + this.inputElement_.addEventListener('blur', this.boundInputOnBlur); + this.element_.addEventListener('mouseup', this.boundElementMouseUp); + this.updateClasses_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); } - this.boundInputOnChange = this.onChange_.bind(this); - this.boundInputOnFocus = this.onFocus_.bind(this); - this.boundInputOnBlur = this.onBlur_.bind(this); - this.boundElementMouseUp = this.onMouseUp_.bind(this); - this.inputElement_.addEventListener('change', this.boundInputOnChange); - this.inputElement_.addEventListener('focus', this.boundInputOnFocus); - this.inputElement_.addEventListener('blur', this.boundInputOnBlur); - this.element_.addEventListener('mouseup', this.boundElementMouseUp); - - this.updateClasses_(); - this.element_.classList.add(this.CssClasses_.IS_UPGRADED); - } }; - -/* -* Downgrade the component. -*/ -MaterialCheckbox.prototype.mdlDowngrade_ = function() { - 'use strict'; - if (this.rippleContainerElement_) { - this.rippleContainerElement_.removeEventListener('mouseup', this.boundRippleMouseUp); - } - this.inputElement_.removeEventListener('change', this.boundInputOnChange); - this.inputElement_.removeEventListener('focus', this.boundInputOnFocus); - this.inputElement_.removeEventListener('blur', this.boundInputOnBlur); - this.element_.removeEventListener('mouseup', this.boundElementMouseUp); +/** + * Downgrade the component. + * + * @private + */ +MaterialCheckbox.prototype.mdlDowngrade_ = function () { + if (this.rippleContainerElement_) { + this.rippleContainerElement_.removeEventListener('mouseup', this.boundRippleMouseUp); + } + this.inputElement_.removeEventListener('change', this.boundInputOnChange); + this.inputElement_.removeEventListener('focus', this.boundInputOnFocus); + this.inputElement_.removeEventListener('blur', this.boundInputOnBlur); + this.element_.removeEventListener('mouseup', this.boundElementMouseUp); }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialCheckbox, - classAsString: 'MaterialCheckbox', - cssClass: 'mdl-js-checkbox', - widget: true + constructor: MaterialCheckbox, + classAsString: 'MaterialCheckbox', + cssClass: 'mdl-js-checkbox', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -813,259 +792,221 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for icon toggle MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialIconToggle(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialIconToggle.prototype.Constant_ = { - TINY_TIMEOUT: 0.001 + * Class constructor for icon toggle MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialIconToggle = function MaterialIconToggle(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialIconToggle = MaterialIconToggle; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialIconToggle.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialIconToggle.prototype.CssClasses_ = { - INPUT: 'mdl-icon-toggle__input', - JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', - RIPPLE_CONTAINER: 'mdl-icon-toggle__ripple-container', - RIPPLE_CENTER: 'mdl-ripple--center', - RIPPLE: 'mdl-ripple', - IS_FOCUSED: 'is-focused', - IS_DISABLED: 'is-disabled', - IS_CHECKED: 'is-checked' + INPUT: 'mdl-icon-toggle__input', + JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-icon-toggle__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked' }; - /** - * Handle change of state. - * @param {Event} event The event that fired. - * @private - */ -MaterialIconToggle.prototype.onChange_ = function(event) { - 'use strict'; - - this.updateClasses_(); + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onChange_ = function (event) { + this.updateClasses_(); }; - /** - * Handle focus of element. - * @param {Event} event The event that fired. - * @private - */ -MaterialIconToggle.prototype.onFocus_ = function(event) { - 'use strict'; - - this.element_.classList.add(this.CssClasses_.IS_FOCUSED); + * Handle focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle lost focus of element. - * @param {Event} event The event that fired. - * @private - */ -MaterialIconToggle.prototype.onBlur_ = function(event) { - 'use strict'; - - this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); + * Handle lost focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle mouseup. - * @param {Event} event The event that fired. - * @private - */ -MaterialIconToggle.prototype.onMouseUp_ = function(event) { - 'use strict'; - - this.blur_(); + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onMouseUp_ = function (event) { + this.blur_(); }; - /** - * Handle class updates. - * @param {HTMLElement} button The button whose classes we should update. - * @param {HTMLElement} label The label whose classes we should update. - * @private - */ -MaterialIconToggle.prototype.updateClasses_ = function() { - 'use strict'; - this.checkDisabled(); - this.checkToggleState(); + * Handle class updates. + * + * @private + */ +MaterialIconToggle.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); }; - /** - * Add blur. - * @private - */ -MaterialIconToggle.prototype.blur_ = function(event) { - 'use strict'; - - // TODO: figure out why there's a focus event being fired after our blur, - // so that we can avoid this hack. - window.setTimeout(function() { - this.inputElement_.blur(); - }.bind(this), this.Constant_.TINY_TIMEOUT); + * Add blur. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.blur_ = function (event) { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.inputElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); }; - // Public methods. - /** -* Check the inputs toggle state and update display. -* @public -*/ -MaterialIconToggle.prototype.checkToggleState = function() { - 'use strict'; - if (this.inputElement_.checked) { - this.element_.classList.add(this.CssClasses_.IS_CHECKED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_CHECKED); - } + * Check the inputs toggle state and update display. + * + * @public + */ +MaterialIconToggle.prototype.checkToggleState = function () { + if (this.inputElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } }; - /** -* Check the inputs disabled state and update display. -* @public -*/ -MaterialIconToggle.prototype.checkDisabled = function() { - 'use strict'; - if (this.inputElement_.disabled) { - this.element_.classList.add(this.CssClasses_.IS_DISABLED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_DISABLED); - } + * Check the inputs disabled state and update display. + * + * @public + */ +MaterialIconToggle.prototype.checkDisabled = function () { + if (this.inputElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } }; - /** - * Disable icon toggle. - * @public - */ -MaterialIconToggle.prototype.disable = function() { - 'use strict'; - - this.inputElement_.disabled = true; - this.updateClasses_(); + * Disable icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.disable = function () { + this.inputElement_.disabled = true; + this.updateClasses_(); }; - /** - * Enable icon toggle. - * @public - */ -MaterialIconToggle.prototype.enable = function() { - 'use strict'; - - this.inputElement_.disabled = false; - this.updateClasses_(); + * Enable icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.enable = function () { + this.inputElement_.disabled = false; + this.updateClasses_(); }; - /** - * Check icon toggle. - * @public - */ -MaterialIconToggle.prototype.check = function() { - 'use strict'; - - this.inputElement_.checked = true; - this.updateClasses_(); + * Check icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.check = function () { + this.inputElement_.checked = true; + this.updateClasses_(); }; - /** - * Uncheck icon toggle. - * @public - */ -MaterialIconToggle.prototype.uncheck = function() { - 'use strict'; - - this.inputElement_.checked = false; - this.updateClasses_(); + * Uncheck icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.uncheck = function () { + this.inputElement_.checked = false; + this.updateClasses_(); }; - /** - * Initialize element. - */ -MaterialIconToggle.prototype.init = function() { - 'use strict'; - - if (this.element_) { - this.inputElement_ = - this.element_.querySelector('.' + this.CssClasses_.INPUT); - - if (this.element_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) { - this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); - this.rippleContainerElement_ = document.createElement('span'); - this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); - this.rippleContainerElement_.classList.add(this.CssClasses_.JS_RIPPLE_EFFECT); - this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); - this.boundRippleMouseUp = this.onMouseUp_.bind(this); - this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp); - - var ripple = document.createElement('span'); - ripple.classList.add(this.CssClasses_.RIPPLE); - - this.rippleContainerElement_.appendChild(ripple); - this.element_.appendChild(this.rippleContainerElement_); + * Initialize element. + */ +MaterialIconToggle.prototype.init = function () { + if (this.element_) { + this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + if (this.element_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + this.rippleContainerElement_ = document.createElement('span'); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleContainerElement_.classList.add(this.CssClasses_.JS_RIPPLE_EFFECT); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); + this.boundRippleMouseUp = this.onMouseUp_.bind(this); + this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + this.rippleContainerElement_.appendChild(ripple); + this.element_.appendChild(this.rippleContainerElement_); + } + this.boundInputOnChange = this.onChange_.bind(this); + this.boundInputOnFocus = this.onFocus_.bind(this); + this.boundInputOnBlur = this.onBlur_.bind(this); + this.boundElementOnMouseUp = this.onMouseUp_.bind(this); + this.inputElement_.addEventListener('change', this.boundInputOnChange); + this.inputElement_.addEventListener('focus', this.boundInputOnFocus); + this.inputElement_.addEventListener('blur', this.boundInputOnBlur); + this.element_.addEventListener('mouseup', this.boundElementOnMouseUp); + this.updateClasses_(); + this.element_.classList.add('is-upgraded'); } - - this.boundInputOnChange = this.onChange_.bind(this); - this.boundInputOnFocus = this.onFocus_.bind(this); - this.boundInputOnBlur = this.onBlur_.bind(this); - this.boundElementOnMouseUp = this.onMouseUp_.bind(this); - this.inputElement_.addEventListener('change', this.boundInputOnChange); - this.inputElement_.addEventListener('focus', this.boundInputOnFocus); - this.inputElement_.addEventListener('blur', this.boundInputOnBlur); - this.element_.addEventListener('mouseup', this.boundElementOnMouseUp); - - this.updateClasses_(); - this.element_.classList.add('is-upgraded'); - } }; - -/* -* Downgrade the component -*/ -MaterialIconToggle.prototype.mdlDowngrade_ = function() { - 'use strict'; - if (this.rippleContainerElement_) { - this.rippleContainerElement_.removeEventListener('mouseup', this.boundRippleMouseUp); - } - this.inputElement_.removeEventListener('change', this.boundInputOnChange); - this.inputElement_.removeEventListener('focus', this.boundInputOnFocus); - this.inputElement_.removeEventListener('blur', this.boundInputOnBlur); - this.element_.removeEventListener('mouseup', this.boundElementOnMouseUp); +/** + * Downgrade the component + * + * @private + */ +MaterialIconToggle.prototype.mdlDowngrade_ = function () { + if (this.rippleContainerElement_) { + this.rippleContainerElement_.removeEventListener('mouseup', this.boundRippleMouseUp); + } + this.inputElement_.removeEventListener('change', this.boundInputOnChange); + this.inputElement_.removeEventListener('focus', this.boundInputOnFocus); + this.inputElement_.removeEventListener('blur', this.boundInputOnBlur); + this.element_.removeEventListener('mouseup', this.boundElementOnMouseUp); }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialIconToggle, - classAsString: 'MaterialIconToggle', - cssClass: 'mdl-js-icon-toggle', - widget: true + constructor: MaterialIconToggle, + classAsString: 'MaterialIconToggle', + cssClass: 'mdl-js-icon-toggle', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1078,463 +1019,413 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for dropdown MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialMenu(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - + * Class constructor for dropdown MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialMenu = function MaterialMenu(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window.MaterialMenu = MaterialMenu; /** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ MaterialMenu.prototype.Constant_ = { - // Total duration of the menu animation. - TRANSITION_DURATION_SECONDS: 0.3, - // The fraction of the total duration we want to use for menu item animations. - TRANSITION_DURATION_FRACTION: 0.8, - // How long the menu stays open after choosing an option (so the user can see - // the ripple). - CLOSE_TIMEOUT: 150 + // Total duration of the menu animation. + TRANSITION_DURATION_SECONDS: 0.3, + // The fraction of the total duration we want to use for menu item animations. + TRANSITION_DURATION_FRACTION: 0.8, + // How long the menu stays open after choosing an option (so the user can see + // the ripple). + CLOSE_TIMEOUT: 150 }; - /** - * Keycodes, for code readability. - * @enum {number} - * @private - */ + * Keycodes, for code readability. + * + * @enum {Number} + * @private + */ MaterialMenu.prototype.Keycodes_ = { - ENTER: 13, - ESCAPE: 27, - SPACE: 32, - UP_ARROW: 38, - DOWN_ARROW: 40 + ENTER: 13, + ESCAPE: 27, + SPACE: 32, + UP_ARROW: 38, + DOWN_ARROW: 40 }; - /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialMenu.prototype.CssClasses_ = { - CONTAINER: 'mdl-menu__container', - OUTLINE: 'mdl-menu__outline', - ITEM: 'mdl-menu__item', - ITEM_RIPPLE_CONTAINER: 'mdl-menu__item-ripple-container', - RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', - RIPPLE: 'mdl-ripple', - // Statuses - IS_UPGRADED: 'is-upgraded', - IS_VISIBLE: 'is-visible', - IS_ANIMATING: 'is-animating', - // Alignment options - BOTTOM_LEFT: 'mdl-menu--bottom-left', // This is the default. - BOTTOM_RIGHT: 'mdl-menu--bottom-right', - TOP_LEFT: 'mdl-menu--top-left', - TOP_RIGHT: 'mdl-menu--top-right', - UNALIGNED: 'mdl-menu--unaligned' + CONTAINER: 'mdl-menu__container', + OUTLINE: 'mdl-menu__outline', + ITEM: 'mdl-menu__item', + ITEM_RIPPLE_CONTAINER: 'mdl-menu__item-ripple-container', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE: 'mdl-ripple', + // Statuses + IS_UPGRADED: 'is-upgraded', + IS_VISIBLE: 'is-visible', + IS_ANIMATING: 'is-animating', + // Alignment options + BOTTOM_LEFT: 'mdl-menu--bottom-left', + // This is the default. + BOTTOM_RIGHT: 'mdl-menu--bottom-right', + TOP_LEFT: 'mdl-menu--top-left', + TOP_RIGHT: 'mdl-menu--top-right', + UNALIGNED: 'mdl-menu--unaligned' }; - /** - * Initialize element. - */ -MaterialMenu.prototype.init = function() { - 'use strict'; - - if (this.element_) { - // Create container for the menu. - var container = document.createElement('div'); - container.classList.add(this.CssClasses_.CONTAINER); - this.element_.parentElement.insertBefore(container, this.element_); - this.element_.parentElement.removeChild(this.element_); - container.appendChild(this.element_); - this.container_ = container; - - // Create outline for the menu (shadow and background). - var outline = document.createElement('div'); - outline.classList.add(this.CssClasses_.OUTLINE); - this.outline_ = outline; - container.insertBefore(outline, this.element_); - - // Find the "for" element and bind events to it. - var forElId = this.element_.getAttribute('for'); - var forEl = null; - if (forElId) { - forEl = document.getElementById(forElId); - if (forEl) { - this.forElement_ = forEl; - forEl.addEventListener('click', this.handleForClick_.bind(this)); - forEl.addEventListener('keydown', - this.handleForKeyboardEvent_.bind(this)); - } + * Initialize element. + */ +MaterialMenu.prototype.init = function () { + if (this.element_) { + // Create container for the menu. + var container = document.createElement('div'); + container.classList.add(this.CssClasses_.CONTAINER); + this.element_.parentElement.insertBefore(container, this.element_); + this.element_.parentElement.removeChild(this.element_); + container.appendChild(this.element_); + this.container_ = container; + // Create outline for the menu (shadow and background). + var outline = document.createElement('div'); + outline.classList.add(this.CssClasses_.OUTLINE); + this.outline_ = outline; + container.insertBefore(outline, this.element_); + // Find the "for" element and bind events to it. + var forElId = this.element_.getAttribute('for'); + var forEl = null; + if (forElId) { + forEl = document.getElementById(forElId); + if (forEl) { + this.forElement_ = forEl; + forEl.addEventListener('click', this.handleForClick_.bind(this)); + forEl.addEventListener('keydown', this.handleForKeyboardEvent_.bind(this)); + } + } + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); + this.boundItemKeydown = this.handleItemKeyboardEvent_.bind(this); + this.boundItemClick = this.handleItemClick_.bind(this); + for (var i = 0; i < items.length; i++) { + // Add a listener to each menu item. + items[i].addEventListener('click', this.boundItemClick); + // Add a tab index to each menu item. + items[i].tabIndex = '-1'; + // Add a keyboard listener to each menu item. + items[i].addEventListener('keydown', this.boundItemKeydown); + } + // Add ripple classes to each item, if the user has enabled ripples. + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + for (i = 0; i < items.length; i++) { + var item = items[i]; + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(this.CssClasses_.ITEM_RIPPLE_CONTAINER); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + rippleContainer.appendChild(ripple); + item.appendChild(rippleContainer); + item.classList.add(this.CssClasses_.RIPPLE_EFFECT); + } + } + // Copy alignment classes to the container, so the outline can use them. + if (this.element_.classList.contains(this.CssClasses_.BOTTOM_LEFT)) { + this.outline_.classList.add(this.CssClasses_.BOTTOM_LEFT); + } + if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { + this.outline_.classList.add(this.CssClasses_.BOTTOM_RIGHT); + } + if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { + this.outline_.classList.add(this.CssClasses_.TOP_LEFT); + } + if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { + this.outline_.classList.add(this.CssClasses_.TOP_RIGHT); + } + if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { + this.outline_.classList.add(this.CssClasses_.UNALIGNED); + } + container.classList.add(this.CssClasses_.IS_UPGRADED); } - - var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); - - for (var i = 0; i < items.length; i++) { - // Add a listener to each menu item. - items[i].addEventListener('click', this.handleItemClick_.bind(this)); - // Add a tab index to each menu item. - items[i].tabIndex = '-1'; - // Add a keyboard listener to each menu item. - items[i].addEventListener('keydown', - this.handleItemKeyboardEvent_.bind(this)); +}; +/** + * Handles a click on the "for" element, by positioning the menu and then + * toggling it. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleForClick_ = function (evt) { + if (this.element_ && this.forElement_) { + var rect = this.forElement_.getBoundingClientRect(); + var forRect = this.forElement_.parentElement.getBoundingClientRect(); + if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { + } else if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { + // Position below the "for" element, aligned to its right. + this.container_.style.right = forRect.right - rect.right + 'px'; + this.container_.style.top = this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px'; + } else if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { + // Position above the "for" element, aligned to its left. + this.container_.style.left = this.forElement_.offsetLeft + 'px'; + this.container_.style.bottom = forRect.bottom - rect.top + 'px'; + } else if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { + // Position above the "for" element, aligned to its right. + this.container_.style.right = forRect.right - rect.right + 'px'; + this.container_.style.bottom = forRect.bottom - rect.top + 'px'; + } else { + // Default: position below the "for" element, aligned to its left. + this.container_.style.left = this.forElement_.offsetLeft + 'px'; + this.container_.style.top = this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px'; + } } - - // Add ripple classes to each item, if the user has enabled ripples. - if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { - this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); - - for (i = 0; i < items.length; i++) { - var item = items[i]; - - var rippleContainer = document.createElement('span'); - rippleContainer.classList.add(this.CssClasses_.ITEM_RIPPLE_CONTAINER); - - var ripple = document.createElement('span'); - ripple.classList.add(this.CssClasses_.RIPPLE); - rippleContainer.appendChild(ripple); - - item.appendChild(rippleContainer); - item.classList.add(this.CssClasses_.RIPPLE_EFFECT); - } + this.toggle(evt); +}; +/** + * Handles a keyboard event on the "for" element. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleForKeyboardEvent_ = function (evt) { + if (this.element_ && this.container_ && this.forElement_) { + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + ':not([disabled])'); + if (items && items.length > 0 && this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { + if (evt.keyCode === this.Keycodes_.UP_ARROW) { + evt.preventDefault(); + items[items.length - 1].focus(); + } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) { + evt.preventDefault(); + items[0].focus(); + } + } } - - // Copy alignment classes to the container, so the outline can use them. - if (this.element_.classList.contains(this.CssClasses_.BOTTOM_LEFT)) { - this.outline_.classList.add(this.CssClasses_.BOTTOM_LEFT); +}; +/** + * Handles a keyboard event on an item. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleItemKeyboardEvent_ = function (evt) { + if (this.element_ && this.container_) { + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + ':not([disabled])'); + if (items && items.length > 0 && this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { + var currentIndex = Array.prototype.slice.call(items).indexOf(evt.target); + if (evt.keyCode === this.Keycodes_.UP_ARROW) { + evt.preventDefault(); + if (currentIndex > 0) { + items[currentIndex - 1].focus(); + } else { + items[items.length - 1].focus(); + } + } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) { + evt.preventDefault(); + if (items.length > currentIndex + 1) { + items[currentIndex + 1].focus(); + } else { + items[0].focus(); + } + } else if (evt.keyCode === this.Keycodes_.SPACE || evt.keyCode === this.Keycodes_.ENTER) { + evt.preventDefault(); + // Send mousedown and mouseup to trigger ripple. + var e = new MouseEvent('mousedown'); + evt.target.dispatchEvent(e); + e = new MouseEvent('mouseup'); + evt.target.dispatchEvent(e); + // Send click. + evt.target.click(); + } else if (evt.keyCode === this.Keycodes_.ESCAPE) { + evt.preventDefault(); + this.hide(); + } + } } - if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { - this.outline_.classList.add(this.CssClasses_.BOTTOM_RIGHT); +}; +/** + * Handles a click event on an item. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleItemClick_ = function (evt) { + if (evt.target.getAttribute('disabled') !== null) { + evt.stopPropagation(); + } else { + // Wait some time before closing menu, so the user can see the ripple. + this.closing_ = true; + window.setTimeout(function (evt) { + this.hide(); + this.closing_ = false; + }.bind(this), this.Constant_.CLOSE_TIMEOUT); } - if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { - this.outline_.classList.add(this.CssClasses_.TOP_LEFT); - } - if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { - this.outline_.classList.add(this.CssClasses_.TOP_RIGHT); - } - if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { - this.outline_.classList.add(this.CssClasses_.UNALIGNED); - } - - container.classList.add(this.CssClasses_.IS_UPGRADED); - } }; - /** - * Handles a click on the "for" element, by positioning the menu and then - * toggling it. - * @private - */ -MaterialMenu.prototype.handleForClick_ = function(evt) { - 'use strict'; - - if (this.element_ && this.forElement_) { - var rect = this.forElement_.getBoundingClientRect(); - var forRect = this.forElement_.parentElement.getBoundingClientRect(); - + * Calculates the initial clip (for opening the menu) or final clip (for closing + * it), and applies it. This allows us to animate from or to the correct point, + * that is, the point it's aligned to in the "for" element. + * + * @param {Number} height Height of the clip rectangle + * @param {Number} width Width of the clip rectangle + * @private + */ +MaterialMenu.prototype.applyClip_ = function (height, width) { if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { - // Do not position the menu automatically. Requires the developer to - // manually specify position. - } else if (this.element_.classList.contains( - this.CssClasses_.BOTTOM_RIGHT)) { - // Position below the "for" element, aligned to its right. - this.container_.style.right = (forRect.right - rect.right) + 'px'; - this.container_.style.top = - this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px'; + // Do not clip. + this.element_.style.clip = null; + } else if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { + // Clip to the top right corner of the menu. + this.element_.style.clip = 'rect(0 ' + width + 'px ' + '0 ' + width + 'px)'; } else if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { - // Position above the "for" element, aligned to its left. - this.container_.style.left = this.forElement_.offsetLeft + 'px'; - this.container_.style.bottom = (forRect.bottom - rect.top) + 'px'; + // Clip to the bottom left corner of the menu. + this.element_.style.clip = 'rect(' + height + 'px 0 ' + height + 'px 0)'; } else if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { - // Position above the "for" element, aligned to its right. - this.container_.style.right = (forRect.right - rect.right) + 'px'; - this.container_.style.bottom = (forRect.bottom - rect.top) + 'px'; + // Clip to the bottom right corner of the menu. + this.element_.style.clip = 'rect(' + height + 'px ' + width + 'px ' + height + 'px ' + width + 'px)'; } else { - // Default: position below the "for" element, aligned to its left. - this.container_.style.left = this.forElement_.offsetLeft + 'px'; - this.container_.style.top = - this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px'; + // Default: do not clip (same as clipping to the top left corner). + this.element_.style.clip = null; } - } - - this.toggle(evt); }; - /** - * Handles a keyboard event on the "for" element. - * @private - */ -MaterialMenu.prototype.handleForKeyboardEvent_ = function(evt) { - 'use strict'; - - if (this.element_ && this.container_ && this.forElement_) { - var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + - ':not([disabled])'); - - if (items && items.length > 0 && - this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { - if (evt.keyCode === this.Keycodes_.UP_ARROW) { - evt.preventDefault(); - items[items.length - 1].focus(); - } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) { - evt.preventDefault(); - items[0].focus(); - } - } - } + * Adds an event listener to clean up after the animation ends. + * + * @private + */ +MaterialMenu.prototype.addAnimationEndListener_ = function () { + var cleanup = function () { + this.element_.removeEventListener('transitionend', cleanup); + this.element_.removeEventListener('webkitTransitionEnd', cleanup); + this.element_.classList.remove(this.CssClasses_.IS_ANIMATING); + }.bind(this); + // Remove animation class once the transition is done. + this.element_.addEventListener('transitionend', cleanup); + this.element_.addEventListener('webkitTransitionEnd', cleanup); }; - /** - * Handles a keyboard event on an item. - * @private - */ -MaterialMenu.prototype.handleItemKeyboardEvent_ = function(evt) { - 'use strict'; - - if (this.element_ && this.container_) { - var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + - ':not([disabled])'); - - if (items && items.length > 0 && - this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { - var currentIndex = Array.prototype.slice.call(items).indexOf(evt.target); - - if (evt.keyCode === this.Keycodes_.UP_ARROW) { - evt.preventDefault(); - if (currentIndex > 0) { - items[currentIndex - 1].focus(); - } else { - items[items.length - 1].focus(); + * Displays the menu. + * + * @public + */ +MaterialMenu.prototype.show = function (evt) { + if (this.element_ && this.container_ && this.outline_) { + // Measure the inner element. + var height = this.element_.getBoundingClientRect().height; + var width = this.element_.getBoundingClientRect().width; + // Apply the inner element's size to the container and outline. + this.container_.style.width = width + 'px'; + this.container_.style.height = height + 'px'; + this.outline_.style.width = width + 'px'; + this.outline_.style.height = height + 'px'; + var transitionDuration = this.Constant_.TRANSITION_DURATION_SECONDS * this.Constant_.TRANSITION_DURATION_FRACTION; + // Calculate transition delays for individual menu items, so that they fade + // in one at a time. + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); + for (var i = 0; i < items.length; i++) { + var itemDelay = null; + if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT) || this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { + itemDelay = (height - items[i].offsetTop - items[i].offsetHeight) / height * transitionDuration + 's'; + } else { + itemDelay = items[i].offsetTop / height * transitionDuration + 's'; + } + items[i].style.transitionDelay = itemDelay; } - } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) { - evt.preventDefault(); - if (items.length > currentIndex + 1) { - items[currentIndex + 1].focus(); - } else { - items[0].focus(); - } - } else if (evt.keyCode === this.Keycodes_.SPACE || - evt.keyCode === this.Keycodes_.ENTER) { - evt.preventDefault(); - // Send mousedown and mouseup to trigger ripple. - var e = new MouseEvent('mousedown'); - evt.target.dispatchEvent(e); - e = new MouseEvent('mouseup'); - evt.target.dispatchEvent(e); - // Send click. - evt.target.click(); - } else if (evt.keyCode === this.Keycodes_.ESCAPE) { - evt.preventDefault(); - this.hide(); - } + // Apply the initial clip to the text before we start animating. + this.applyClip_(height, width); + // Wait for the next frame, turn on animation, and apply the final clip. + // Also make it visible. This triggers the transitions. + window.requestAnimationFrame(function () { + this.element_.classList.add(this.CssClasses_.IS_ANIMATING); + this.element_.style.clip = 'rect(0 ' + width + 'px ' + height + 'px 0)'; + this.container_.classList.add(this.CssClasses_.IS_VISIBLE); + }.bind(this)); + // Clean up after the animation is complete. + this.addAnimationEndListener_(); + // Add a click listener to the document, to close the menu. + var callback = function (e) { + // Check to see if the document is processing the same event that + // displayed the menu in the first place. If so, do nothing. + // Also check to see if the menu is in the process of closing itself, and + // do nothing in that case. + if (e !== evt && !this.closing_) { + document.removeEventListener('click', callback); + this.hide(); + } + }.bind(this); + document.addEventListener('click', callback); } - } }; - /** - * Handles a click event on an item. - * @private - */ -MaterialMenu.prototype.handleItemClick_ = function(evt) { - 'use strict'; - - if (evt.target.getAttribute('disabled') !== null) { - evt.stopPropagation(); - } else { - // Wait some time before closing menu, so the user can see the ripple. - this.closing_ = true; - window.setTimeout(function(evt) { - this.hide(); - this.closing_ = false; - }.bind(this), this.Constant_.CLOSE_TIMEOUT); - } + * Hides the menu. + * + * @public + */ +MaterialMenu.prototype.hide = function () { + if (this.element_ && this.container_ && this.outline_) { + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); + // Remove all transition delays; menu items fade out concurrently. + for (var i = 0; i < items.length; i++) { + items[i].style.transitionDelay = null; + } + // Measure the inner element. + var height = this.element_.getBoundingClientRect().height; + var width = this.element_.getBoundingClientRect().width; + // Turn on animation, and apply the final clip. Also make invisible. + // This triggers the transitions. + this.element_.classList.add(this.CssClasses_.IS_ANIMATING); + this.applyClip_(height, width); + this.container_.classList.remove(this.CssClasses_.IS_VISIBLE); + // Clean up after the animation is complete. + this.addAnimationEndListener_(); + } }; - /** - * Calculates the initial clip (for opening the menu) or final clip (for closing - * it), and applies it. This allows us to animate from or to the correct point, - * that is, the point it's aligned to in the "for" element. - * @private - */ -MaterialMenu.prototype.applyClip_ = function(height, width) { - 'use strict'; - - if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { - // Do not clip. - this.element_.style.clip = null; - } else if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { - // Clip to the top right corner of the menu. - this.element_.style.clip = - 'rect(0 ' + width + 'px ' + '0 ' + width + 'px)'; - } else if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { - // Clip to the bottom left corner of the menu. - this.element_.style.clip = - 'rect(' + height + 'px 0 ' + height + 'px 0)'; - } else if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { - // Clip to the bottom right corner of the menu. - this.element_.style.clip = 'rect(' + height + 'px ' + width + 'px ' + - height + 'px ' + width + 'px)'; - } else { - // Default: do not clip (same as clipping to the top left corner). - this.element_.style.clip = null; - } -}; - -/** - * Adds an event listener to clean up after the animation ends. - * @private - */ -MaterialMenu.prototype.addAnimationEndListener_ = function() { - 'use strict'; - - var cleanup = function () { - this.element_.removeEventListener('transitionend', cleanup); - this.element_.removeEventListener('webkitTransitionEnd', cleanup); - this.element_.classList.remove(this.CssClasses_.IS_ANIMATING); - }.bind(this); - - // Remove animation class once the transition is done. - this.element_.addEventListener('transitionend', cleanup); - this.element_.addEventListener('webkitTransitionEnd', cleanup); -}; - -/** - * Displays the menu. - * @public - */ -MaterialMenu.prototype.show = function(evt) { - 'use strict'; - - if (this.element_ && this.container_ && this.outline_) { - // Measure the inner element. - var height = this.element_.getBoundingClientRect().height; - var width = this.element_.getBoundingClientRect().width; - - // Apply the inner element's size to the container and outline. - this.container_.style.width = width + 'px'; - this.container_.style.height = height + 'px'; - this.outline_.style.width = width + 'px'; - this.outline_.style.height = height + 'px'; - - var transitionDuration = this.Constant_.TRANSITION_DURATION_SECONDS * - this.Constant_.TRANSITION_DURATION_FRACTION; - - // Calculate transition delays for individual menu items, so that they fade - // in one at a time. - var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); - for (var i = 0; i < items.length; i++) { - var itemDelay = null; - if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT) || - this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { - itemDelay = ((height - items[i].offsetTop - items[i].offsetHeight) / - height * transitionDuration) + 's'; - } else { - itemDelay = (items[i].offsetTop / height * transitionDuration) + 's'; - } - items[i].style.transitionDelay = itemDelay; - } - - // Apply the initial clip to the text before we start animating. - this.applyClip_(height, width); - - // Wait for the next frame, turn on animation, and apply the final clip. - // Also make it visible. This triggers the transitions. - window.requestAnimationFrame(function() { - this.element_.classList.add(this.CssClasses_.IS_ANIMATING); - this.element_.style.clip = 'rect(0 ' + width + 'px ' + height + 'px 0)'; - this.container_.classList.add(this.CssClasses_.IS_VISIBLE); - }.bind(this)); - - // Clean up after the animation is complete. - this.addAnimationEndListener_(); - - // Add a click listener to the document, to close the menu. - var callback = function(e) { - // Check to see if the document is processing the same event that - // displayed the menu in the first place. If so, do nothing. - // Also check to see if the menu is in the process of closing itself, and - // do nothing in that case. - if (e !== evt && !this.closing_) { - document.removeEventListener('click', callback); + * Displays or hides the menu, depending on current state. + * + * @public + */ +MaterialMenu.prototype.toggle = function (evt) { + if (this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { this.hide(); - } - }.bind(this); - document.addEventListener('click', callback); - } + } else { + this.show(evt); + } }; - /** - * Hides the menu. - * @public - */ -MaterialMenu.prototype.hide = function() { - 'use strict'; - - if (this.element_ && this.container_ && this.outline_) { + * Downgrade the component. + * + * @private + */ +MaterialMenu.prototype.mdlDowngrade_ = function () { var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); - - // Remove all transition delays; menu items fade out concurrently. for (var i = 0; i < items.length; i++) { - items[i].style.transitionDelay = null; + items[i].removeEventListener('click', this.boundItemClick); + items[i].removeEventListener('keydown', this.boundItemKeydown); } - - // Measure the inner element. - var height = this.element_.getBoundingClientRect().height; - var width = this.element_.getBoundingClientRect().width; - - // Turn on animation, and apply the final clip. Also make invisible. - // This triggers the transitions. - this.element_.classList.add(this.CssClasses_.IS_ANIMATING); - this.applyClip_(height, width); - this.container_.classList.remove(this.CssClasses_.IS_VISIBLE); - - // Clean up after the animation is complete. - this.addAnimationEndListener_(); - } }; - -/** - * Displays or hides the menu, depending on current state. - * @public - */ -MaterialMenu.prototype.toggle = function(evt) { - 'use strict'; - - if (this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { - this.hide(); - } else { - this.show(evt); - } -}; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialMenu, - classAsString: 'MaterialMenu', - cssClass: 'mdl-js-menu', - widget: true + constructor: MaterialMenu, + classAsString: 'MaterialMenu', + cssClass: 'mdl-js-menu', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1547,111 +1438,102 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Progress MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialProgress(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - + * Class constructor for Progress MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialProgress = function MaterialProgress(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window.MaterialProgress = MaterialProgress; /** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialProgress.prototype.Constant_ = { + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialProgress.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ +MaterialProgress.prototype.CssClasses_ = { INDETERMINATE_CLASS: 'mdl-progress__indeterminate' }; +/** + * Set the current progress of the progressbar. + * + * @param {Number} p Percentage of the progress (0-100) + * @public + */ +MaterialProgress.prototype.setProgress = function (p) { + if (this.element_.classList.contains(this.CssClasses_.INDETERMINATE_CLASS)) { + return; + } + this.progressbar_.style.width = p + '%'; }; - /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ -MaterialProgress.prototype.CssClasses_ = { - INDETERMINATE_CLASS: 'mdl-progress__indeterminate' + * Set the current progress of the buffer. + * + * @param {Number} p Percentage of the buffer (0-100) + * @public + */ +MaterialProgress.prototype.setBuffer = function (p) { + this.bufferbar_.style.width = p + '%'; + this.auxbar_.style.width = 100 - p + '%'; }; - -MaterialProgress.prototype.setProgress = function(p) { - 'use strict'; - - if (this.element_.classList.contains(this.CssClasses_.INDETERMINATE_CLASS)) { - return; - } - - this.progressbar_.style.width = p + '%'; +/** + * Initialize element. + */ +MaterialProgress.prototype.init = function () { + if (this.element_) { + var el = document.createElement('div'); + el.className = 'progressbar bar bar1'; + this.element_.appendChild(el); + this.progressbar_ = el; + el = document.createElement('div'); + el.className = 'bufferbar bar bar2'; + this.element_.appendChild(el); + this.bufferbar_ = el; + el = document.createElement('div'); + el.className = 'auxbar bar bar3'; + this.element_.appendChild(el); + this.auxbar_ = el; + this.progressbar_.style.width = '0%'; + this.bufferbar_.style.width = '100%'; + this.auxbar_.style.width = '0%'; + this.element_.classList.add('is-upgraded'); + } }; - -MaterialProgress.prototype.setBuffer = function(p) { - 'use strict'; - - this.bufferbar_.style.width = p + '%'; - this.auxbar_.style.width = (100 - p) + '%'; -}; - /** - * Initialize element. - */ -MaterialProgress.prototype.init = function() { - 'use strict'; - - if (this.element_) { - var el = document.createElement('div'); - el.className = 'progressbar bar bar1'; - this.element_.appendChild(el); - this.progressbar_ = el; - - el = document.createElement('div'); - el.className = 'bufferbar bar bar2'; - this.element_.appendChild(el); - this.bufferbar_ = el; - - el = document.createElement('div'); - el.className = 'auxbar bar bar3'; - this.element_.appendChild(el); - this.auxbar_ = el; - - this.progressbar_.style.width = '0%'; - this.bufferbar_.style.width = '100%'; - this.auxbar_.style.width = '0%'; - - this.element_.classList.add('is-upgraded'); - } + * Downgrade the component + * + * @private + */ +MaterialProgress.prototype.mdlDowngrade_ = function () { + while (this.element_.firstChild) { + this.element_.removeChild(this.element_.firstChild); + } }; - -/* -* Downgrade the component -*/ -MaterialProgress.prototype.mdlDowngrade_ = function() { - 'use strict'; - while (this.element_.firstChild) { - this.element_.removeChild(this.element_.firstChild); - } -}; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialProgress, - classAsString: 'MaterialProgress', - cssClass: 'mdl-js-progress', - widget: true + constructor: MaterialProgress, + classAsString: 'MaterialProgress', + cssClass: 'mdl-js-progress', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1664,264 +1546,222 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Radio MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialRadio(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialRadio.prototype.Constant_ = { - TINY_TIMEOUT: 0.001 + * Class constructor for Radio MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialRadio = function MaterialRadio(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialRadio = MaterialRadio; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialRadio.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialRadio.prototype.CssClasses_ = { - IS_FOCUSED: 'is-focused', - IS_DISABLED: 'is-disabled', - IS_CHECKED: 'is-checked', - IS_UPGRADED: 'is-upgraded', - JS_RADIO: 'mdl-js-radio', - RADIO_BTN: 'mdl-radio__button', - RADIO_OUTER_CIRCLE: 'mdl-radio__outer-circle', - RADIO_INNER_CIRCLE: 'mdl-radio__inner-circle', - RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', - RIPPLE_CONTAINER: 'mdl-radio__ripple-container', - RIPPLE_CENTER: 'mdl-ripple--center', - RIPPLE: 'mdl-ripple' + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked', + IS_UPGRADED: 'is-upgraded', + JS_RADIO: 'mdl-js-radio', + RADIO_BTN: 'mdl-radio__button', + RADIO_OUTER_CIRCLE: 'mdl-radio__outer-circle', + RADIO_INNER_CIRCLE: 'mdl-radio__inner-circle', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-radio__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple' }; - /** - * Handle change of state. - * @param {Event} event The event that fired. - * @private - */ -MaterialRadio.prototype.onChange_ = function(event) { - 'use strict'; - - // Since other radio buttons don't get change events, we need to look for - // them to update their classes. - var radios = document.getElementsByClassName(this.CssClasses_.JS_RADIO); - for (var i = 0; i < radios.length; i++) { - var button = radios[i].querySelector('.' + this.CssClasses_.RADIO_BTN); - // Different name == different group, so no point updating those. - if (button.getAttribute('name') === this.btnElement_.getAttribute('name')) { - radios[i].MaterialRadio.updateClasses_(); + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onChange_ = function (event) { + // Since other radio buttons don't get change events, we need to look for + // them to update their classes. + var radios = document.getElementsByClassName(this.CssClasses_.JS_RADIO); + for (var i = 0; i < radios.length; i++) { + var button = radios[i].querySelector('.' + this.CssClasses_.RADIO_BTN); + // Different name == different group, so no point updating those. + if (button.getAttribute('name') === this.btnElement_.getAttribute('name')) { + radios[i].MaterialRadio.updateClasses_(); + } } - } }; - /** - * Handle focus. - * @param {Event} event The event that fired. - * @private - */ -MaterialRadio.prototype.onFocus_ = function(event) { - 'use strict'; - - this.element_.classList.add(this.CssClasses_.IS_FOCUSED); + * Handle focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle lost focus. - * @param {Event} event The event that fired. - * @private - */ -MaterialRadio.prototype.onBlur_ = function(event) { - 'use strict'; - - this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); + * Handle lost focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle mouseup. - * @param {Event} event The event that fired. - * @private - */ -MaterialRadio.prototype.onMouseup_ = function(event) { - 'use strict'; - - this.blur_(); + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onMouseup_ = function (event) { + this.blur_(); }; - /** - * Update classes. - * @private - */ -MaterialRadio.prototype.updateClasses_ = function() { - 'use strict'; - this.checkDisabled(); - this.checkToggleState(); + * Update classes. + * + * @private + */ +MaterialRadio.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); }; - /** - * Add blur. - * @private - */ -MaterialRadio.prototype.blur_ = function(event) { - 'use strict'; - - // TODO: figure out why there's a focus event being fired after our blur, - // so that we can avoid this hack. - window.setTimeout(function() { - this.btnElement_.blur(); - }.bind(this), this.Constant_.TINY_TIMEOUT); + * Add blur. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.blur_ = function (event) { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.btnElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); }; - // Public methods. - /** -* Check the components disabled state. -* @public -*/ -MaterialRadio.prototype.checkDisabled = function() { - 'use strict'; - if (this.btnElement_.disabled) { - this.element_.classList.add(this.CssClasses_.IS_DISABLED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_DISABLED); - } + * Check the components disabled state. + * + * @public + */ +MaterialRadio.prototype.checkDisabled = function () { + if (this.btnElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } }; - /** -* Check the components toggled state. -* @public -*/ -MaterialRadio.prototype.checkToggleState = function() { - 'use strict'; - if (this.btnElement_.checked) { - this.element_.classList.add(this.CssClasses_.IS_CHECKED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_CHECKED); - } + * Check the components toggled state. + * + * @public + */ +MaterialRadio.prototype.checkToggleState = function () { + if (this.btnElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } }; - /** - * Disable radio. - * @public - */ -MaterialRadio.prototype.disable = function() { - 'use strict'; - - this.btnElement_.disabled = true; - this.updateClasses_(); + * Disable radio. + * + * @public + */ +MaterialRadio.prototype.disable = function () { + this.btnElement_.disabled = true; + this.updateClasses_(); }; - /** - * Enable radio. - * @public - */ -MaterialRadio.prototype.enable = function() { - 'use strict'; - - this.btnElement_.disabled = false; - this.updateClasses_(); + * Enable radio. + * + * @public + */ +MaterialRadio.prototype.enable = function () { + this.btnElement_.disabled = false; + this.updateClasses_(); }; - /** - * Check radio. - * @public - */ -MaterialRadio.prototype.check = function() { - 'use strict'; - - this.btnElement_.checked = true; - this.updateClasses_(); + * Check radio. + * + * @public + */ +MaterialRadio.prototype.check = function () { + this.btnElement_.checked = true; + this.updateClasses_(); }; - /** - * Uncheck radio. - * @public - */ -MaterialRadio.prototype.uncheck = function() { - 'use strict'; - - this.btnElement_.checked = false; - this.updateClasses_(); + * Uncheck radio. + * + * @public + */ +MaterialRadio.prototype.uncheck = function () { + this.btnElement_.checked = false; + this.updateClasses_(); }; - /** - * Initialize element. - */ -MaterialRadio.prototype.init = function() { - 'use strict'; - - if (this.element_) { - this.btnElement_ = this.element_.querySelector('.' + - this.CssClasses_.RADIO_BTN); - - var outerCircle = document.createElement('span'); - outerCircle.classList.add(this.CssClasses_.RADIO_OUTER_CIRCLE); - - var innerCircle = document.createElement('span'); - innerCircle.classList.add(this.CssClasses_.RADIO_INNER_CIRCLE); - - this.element_.appendChild(outerCircle); - this.element_.appendChild(innerCircle); - - var rippleContainer; - if (this.element_.classList.contains( - this.CssClasses_.RIPPLE_EFFECT)) { - this.element_.classList.add( - this.CssClasses_.RIPPLE_IGNORE_EVENTS); - rippleContainer = document.createElement('span'); - rippleContainer.classList.add( - this.CssClasses_.RIPPLE_CONTAINER); - rippleContainer.classList.add(this.CssClasses_.RIPPLE_EFFECT); - rippleContainer.classList.add(this.CssClasses_.RIPPLE_CENTER); - rippleContainer.addEventListener('mouseup', this.onMouseup_.bind(this)); - - var ripple = document.createElement('span'); - ripple.classList.add(this.CssClasses_.RIPPLE); - - rippleContainer.appendChild(ripple); - this.element_.appendChild(rippleContainer); + * Initialize element. + */ +MaterialRadio.prototype.init = function () { + if (this.element_) { + this.btnElement_ = this.element_.querySelector('.' + this.CssClasses_.RADIO_BTN); + var outerCircle = document.createElement('span'); + outerCircle.classList.add(this.CssClasses_.RADIO_OUTER_CIRCLE); + var innerCircle = document.createElement('span'); + innerCircle.classList.add(this.CssClasses_.RADIO_INNER_CIRCLE); + this.element_.appendChild(outerCircle); + this.element_.appendChild(innerCircle); + var rippleContainer; + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + rippleContainer = document.createElement('span'); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_EFFECT); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_CENTER); + rippleContainer.addEventListener('mouseup', this.onMouseup_.bind(this)); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + rippleContainer.appendChild(ripple); + this.element_.appendChild(rippleContainer); + } + this.btnElement_.addEventListener('change', this.onChange_.bind(this)); + this.btnElement_.addEventListener('focus', this.onFocus_.bind(this)); + this.btnElement_.addEventListener('blur', this.onBlur_.bind(this)); + this.element_.addEventListener('mouseup', this.onMouseup_.bind(this)); + this.updateClasses_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); } - - this.btnElement_.addEventListener('change', this.onChange_.bind(this)); - this.btnElement_.addEventListener('focus', this.onFocus_.bind(this)); - this.btnElement_.addEventListener('blur', this.onBlur_.bind(this)); - this.element_.addEventListener('mouseup', this.onMouseup_.bind(this)); - - this.updateClasses_(); - this.element_.classList.add(this.CssClasses_.IS_UPGRADED); - } }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialRadio, - classAsString: 'MaterialRadio', - cssClass: 'mdl-js-radio', - widget: true + constructor: MaterialRadio, + classAsString: 'MaterialRadio', + cssClass: 'mdl-js-radio', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1934,247 +1774,216 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Slider MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialSlider(element) { - 'use strict'; - - this.element_ = element; - // Browser feature detection. - this.isIE_ = window.navigator.msPointerEnabled; - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialSlider.prototype.Constant_ = { - // None for now. + * Class constructor for Slider MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialSlider = function MaterialSlider(element) { + this.element_ = element; + // Browser feature detection. + this.isIE_ = window.navigator.msPointerEnabled; + // Initialize instance. + this.init(); }; - +window.MaterialSlider = MaterialSlider; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialSlider.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialSlider.prototype.CssClasses_ = { - IE_CONTAINER: 'mdl-slider__ie-container', - SLIDER_CONTAINER: 'mdl-slider__container', - BACKGROUND_FLEX: 'mdl-slider__background-flex', - BACKGROUND_LOWER: 'mdl-slider__background-lower', - BACKGROUND_UPPER: 'mdl-slider__background-upper', - IS_LOWEST_VALUE: 'is-lowest-value', - IS_UPGRADED: 'is-upgraded' + IE_CONTAINER: 'mdl-slider__ie-container', + SLIDER_CONTAINER: 'mdl-slider__container', + BACKGROUND_FLEX: 'mdl-slider__background-flex', + BACKGROUND_LOWER: 'mdl-slider__background-lower', + BACKGROUND_UPPER: 'mdl-slider__background-upper', + IS_LOWEST_VALUE: 'is-lowest-value', + IS_UPGRADED: 'is-upgraded' }; - /** - * Handle input on element. - * @param {Event} event The event that fired. - * @private - */ -MaterialSlider.prototype.onInput_ = function(event) { - 'use strict'; - - this.updateValueStyles_(); + * Handle input on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.onInput_ = function (event) { + this.updateValueStyles_(); }; - /** - * Handle change on element. - * @param {Event} event The event that fired. - * @private - */ -MaterialSlider.prototype.onChange_ = function(event) { - 'use strict'; - - this.updateValueStyles_(); + * Handle change on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.onChange_ = function (event) { + this.updateValueStyles_(); }; - /** - * Handle mouseup on element. - * @param {Event} event The event that fired. - * @private - */ -MaterialSlider.prototype.onMouseUp_ = function(event) { - 'use strict'; - - event.target.blur(); + * Handle mouseup on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.onMouseUp_ = function (event) { + event.target.blur(); }; - /** - * Handle mousedown on container element. - * This handler is purpose is to not require the use to click - * exactly on the 2px slider element, as FireFox seems to be very - * strict about this. - * @param {Event} event The event that fired. - * @private - */ -MaterialSlider.prototype.onContainerMouseDown_ = function(event) { - 'use strict'; - - // If this click is not on the parent element (but rather some child) - // ignore. It may still bubble up. - if (event.target !== this.element_.parentElement) { - return; - } - - // Discard the original event and create a new event that - // is on the slider element. - event.preventDefault(); - var newEvent = new MouseEvent('mousedown', { - target: event.target, - buttons: event.buttons, - clientX: event.clientX, - clientY: this.element_.getBoundingClientRect().y - }); - this.element_.dispatchEvent(newEvent); + * Handle mousedown on container element. + * This handler is purpose is to not require the use to click + * exactly on the 2px slider element, as FireFox seems to be very + * strict about this. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.onContainerMouseDown_ = function (event) { + // If this click is not on the parent element (but rather some child) + // ignore. It may still bubble up. + if (event.target !== this.element_.parentElement) { + return; + } + // Discard the original event and create a new event that + // is on the slider element. + event.preventDefault(); + var newEvent = new MouseEvent('mousedown', { + target: event.target, + buttons: event.buttons, + clientX: event.clientX, + clientY: this.element_.getBoundingClientRect().y + }); + this.element_.dispatchEvent(newEvent); }; - /** - * Handle updating of values. - * @param {Event} event The event that fired. - * @private - */ -MaterialSlider.prototype.updateValueStyles_ = function(event) { - 'use strict'; - - // Calculate and apply percentages to div structure behind slider. - var fraction = (this.element_.value - this.element_.min) / - (this.element_.max - this.element_.min); - - if (fraction === 0) { - this.element_.classList.add(this.CssClasses_.IS_LOWEST_VALUE); - } else { - this.element_.classList.remove(this.CssClasses_.IS_LOWEST_VALUE); - } - - if (!this.isIE_) { - this.backgroundLower_.style.flex = fraction; - this.backgroundLower_.style.webkitFlex = fraction; - this.backgroundUpper_.style.flex = 1 - fraction; - this.backgroundUpper_.style.webkitFlex = 1 - fraction; - } + * Handle updating of values. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.updateValueStyles_ = function (event) { + // Calculate and apply percentages to div structure behind slider. + var fraction = (this.element_.value - this.element_.min) / (this.element_.max - this.element_.min); + if (fraction === 0) { + this.element_.classList.add(this.CssClasses_.IS_LOWEST_VALUE); + } else { + this.element_.classList.remove(this.CssClasses_.IS_LOWEST_VALUE); + } + if (!this.isIE_) { + this.backgroundLower_.style.flex = fraction; + this.backgroundLower_.style.webkitFlex = fraction; + this.backgroundUpper_.style.flex = 1 - fraction; + this.backgroundUpper_.style.webkitFlex = 1 - fraction; + } }; - // Public methods. - /** - * Disable slider. - * @public - */ -MaterialSlider.prototype.disable = function() { - 'use strict'; - - this.element_.disabled = true; + * Disable slider. + * + * @public + */ +MaterialSlider.prototype.disable = function () { + this.element_.disabled = true; }; - /** - * Enable slider. - * @public - */ -MaterialSlider.prototype.enable = function() { - 'use strict'; - - this.element_.disabled = false; + * Enable slider. + * + * @public + */ +MaterialSlider.prototype.enable = function () { + this.element_.disabled = false; }; - /** - * Update slider value. - * @param {Number} value The value to which to set the control (optional). - * @public - */ -MaterialSlider.prototype.change = function(value) { - 'use strict'; - - if (value) { - this.element_.value = value; - } - this.updateValueStyles_(); + * Update slider value. + * + * @param {Number} value The value to which to set the control (optional). + * @public + */ +MaterialSlider.prototype.change = function (value) { + if (typeof value !== 'undefined') { + this.element_.value = value; + } + this.updateValueStyles_(); }; - /** - * Initialize element. - */ -MaterialSlider.prototype.init = function() { - 'use strict'; - - if (this.element_) { - if (this.isIE_) { - // Since we need to specify a very large height in IE due to - // implementation limitations, we add a parent here that trims it down to - // a reasonable size. - var containerIE = document.createElement('div'); - containerIE.classList.add(this.CssClasses_.IE_CONTAINER); - this.element_.parentElement.insertBefore(containerIE, this.element_); - this.element_.parentElement.removeChild(this.element_); - containerIE.appendChild(this.element_); - } else { - // For non-IE browsers, we need a div structure that sits behind the - // slider and allows us to style the left and right sides of it with - // different colors. - var container = document.createElement('div'); - container.classList.add(this.CssClasses_.SLIDER_CONTAINER); - this.element_.parentElement.insertBefore(container, this.element_); - this.element_.parentElement.removeChild(this.element_); - container.appendChild(this.element_); - var backgroundFlex = document.createElement('div'); - backgroundFlex.classList.add(this.CssClasses_.BACKGROUND_FLEX); - container.appendChild(backgroundFlex); - this.backgroundLower_ = document.createElement('div'); - this.backgroundLower_.classList.add(this.CssClasses_.BACKGROUND_LOWER); - backgroundFlex.appendChild(this.backgroundLower_); - this.backgroundUpper_ = document.createElement('div'); - this.backgroundUpper_.classList.add(this.CssClasses_.BACKGROUND_UPPER); - backgroundFlex.appendChild(this.backgroundUpper_); + * Initialize element. + */ +MaterialSlider.prototype.init = function () { + if (this.element_) { + if (this.isIE_) { + // Since we need to specify a very large height in IE due to + // implementation limitations, we add a parent here that trims it down to + // a reasonable size. + var containerIE = document.createElement('div'); + containerIE.classList.add(this.CssClasses_.IE_CONTAINER); + this.element_.parentElement.insertBefore(containerIE, this.element_); + this.element_.parentElement.removeChild(this.element_); + containerIE.appendChild(this.element_); + } else { + // For non-IE browsers, we need a div structure that sits behind the + // slider and allows us to style the left and right sides of it with + // different colors. + var container = document.createElement('div'); + container.classList.add(this.CssClasses_.SLIDER_CONTAINER); + this.element_.parentElement.insertBefore(container, this.element_); + this.element_.parentElement.removeChild(this.element_); + container.appendChild(this.element_); + var backgroundFlex = document.createElement('div'); + backgroundFlex.classList.add(this.CssClasses_.BACKGROUND_FLEX); + container.appendChild(backgroundFlex); + this.backgroundLower_ = document.createElement('div'); + this.backgroundLower_.classList.add(this.CssClasses_.BACKGROUND_LOWER); + backgroundFlex.appendChild(this.backgroundLower_); + this.backgroundUpper_ = document.createElement('div'); + this.backgroundUpper_.classList.add(this.CssClasses_.BACKGROUND_UPPER); + backgroundFlex.appendChild(this.backgroundUpper_); + } + this.boundInputHandler = this.onInput_.bind(this); + this.boundChangeHandler = this.onChange_.bind(this); + this.boundMouseUpHandler = this.onMouseUp_.bind(this); + this.boundContainerMouseDownHandler = this.onContainerMouseDown_.bind(this); + this.element_.addEventListener('input', this.boundInputHandler); + this.element_.addEventListener('change', this.boundChangeHandler); + this.element_.addEventListener('mouseup', this.boundMouseUpHandler); + this.element_.parentElement.addEventListener('mousedown', this.boundContainerMouseDownHandler); + this.updateValueStyles_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); } - - this.boundInputHandler = this.onInput_.bind(this); - this.boundChangeHandler = this.onChange_.bind(this); - this.boundMouseUpHandler = this.onMouseUp_.bind(this); - this.boundContainerMouseDownHandler = this.onContainerMouseDown_.bind(this); - this.element_.addEventListener('input', this.boundInputHandler); - this.element_.addEventListener('change', this.boundChangeHandler); - this.element_.addEventListener('mouseup', this.boundMouseUpHandler); - this.element_.parentElement.addEventListener('mousedown', this.boundContainerMouseDownHandler); - - this.updateValueStyles_(); - this.element_.classList.add(this.CssClasses_.IS_UPGRADED); - } }; - -/* -* Downgrade the component -*/ -MaterialSlider.prototype.mdlDowngrade_ = function() { - 'use strict'; - this.element_.removeEventListener('input', this.boundInputHandler); - this.element_.removeEventListener('change', this.boundChangeHandler); - this.element_.removeEventListener('mouseup', this.boundMouseUpHandler); - this.element_.parentElement.removeEventListener('mousedown', this.boundContainerMouseDownHandler); +/** + * Downgrade the component + * + * @private + */ +MaterialSlider.prototype.mdlDowngrade_ = function () { + this.element_.removeEventListener('input', this.boundInputHandler); + this.element_.removeEventListener('change', this.boundChangeHandler); + this.element_.removeEventListener('mouseup', this.boundMouseUpHandler); + this.element_.parentElement.removeEventListener('mousedown', this.boundContainerMouseDownHandler); }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialSlider, - classAsString: 'MaterialSlider', - cssClass: 'mdl-js-slider', - widget: true + constructor: MaterialSlider, + classAsString: 'MaterialSlider', + cssClass: 'mdl-js-slider', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -2187,135 +1996,118 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Spinner MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - * @constructor - */ -function MaterialSpinner(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialSpinner.prototype.Constant_ = { - MDL_SPINNER_LAYER_COUNT: 4 + * Class constructor for Spinner MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + * @constructor + */ +var MaterialSpinner = function MaterialSpinner(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialSpinner = MaterialSpinner; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialSpinner.prototype.Constant_ = { MDL_SPINNER_LAYER_COUNT: 4 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialSpinner.prototype.CssClasses_ = { - MDL_SPINNER_LAYER: 'mdl-spinner__layer', - MDL_SPINNER_CIRCLE_CLIPPER: 'mdl-spinner__circle-clipper', - MDL_SPINNER_CIRCLE: 'mdl-spinner__circle', - MDL_SPINNER_GAP_PATCH: 'mdl-spinner__gap-patch', - MDL_SPINNER_LEFT: 'mdl-spinner__left', - MDL_SPINNER_RIGHT: 'mdl-spinner__right' + MDL_SPINNER_LAYER: 'mdl-spinner__layer', + MDL_SPINNER_CIRCLE_CLIPPER: 'mdl-spinner__circle-clipper', + MDL_SPINNER_CIRCLE: 'mdl-spinner__circle', + MDL_SPINNER_GAP_PATCH: 'mdl-spinner__gap-patch', + MDL_SPINNER_LEFT: 'mdl-spinner__left', + MDL_SPINNER_RIGHT: 'mdl-spinner__right' }; - /** -* Auxiliary method to create a spinner layer. -*/ -MaterialSpinner.prototype.createLayer = function(index) { - 'use strict'; - - var layer = document.createElement('div'); - layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER); - layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER + '-' + index); - - var leftClipper = document.createElement('div'); - leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER); - leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_LEFT); - - var gapPatch = document.createElement('div'); - gapPatch.classList.add(this.CssClasses_.MDL_SPINNER_GAP_PATCH); - - var rightClipper = document.createElement('div'); - rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER); - rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_RIGHT); - - var circleOwners = [leftClipper, gapPatch, rightClipper]; - - for (var i = 0; i < circleOwners.length; i++) { - var circle = document.createElement('div'); - circle.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE); - circleOwners[i].appendChild(circle); - } - - layer.appendChild(leftClipper); - layer.appendChild(gapPatch); - layer.appendChild(rightClipper); - - this.element_.appendChild(layer); + * Auxiliary method to create a spinner layer. + * + * @param {Number} index Index of the layer to be created. + * @public + */ +MaterialSpinner.prototype.createLayer = function (index) { + var layer = document.createElement('div'); + layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER); + layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER + '-' + index); + var leftClipper = document.createElement('div'); + leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER); + leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_LEFT); + var gapPatch = document.createElement('div'); + gapPatch.classList.add(this.CssClasses_.MDL_SPINNER_GAP_PATCH); + var rightClipper = document.createElement('div'); + rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER); + rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_RIGHT); + var circleOwners = [ + leftClipper, + gapPatch, + rightClipper + ]; + for (var i = 0; i < circleOwners.length; i++) { + var circle = document.createElement('div'); + circle.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE); + circleOwners[i].appendChild(circle); + } + layer.appendChild(leftClipper); + layer.appendChild(gapPatch); + layer.appendChild(rightClipper); + this.element_.appendChild(layer); }; - /** -* Stops the spinner animation. -* Public method for users who need to stop the spinner for any reason. -* @public -*/ -MaterialSpinner.prototype.stop = function() { - 'use strict'; - - this.element_.classList.remove('is-active'); + * Stops the spinner animation. + * Public method for users who need to stop the spinner for any reason. + * + * @public + */ +MaterialSpinner.prototype.stop = function () { + this.element_.classList.remove('is-active'); }; - /** -* Starts the spinner animation. -* Public method for users who need to manually start the spinner for any reason -* (instead of just adding the 'is-active' class to their markup). -* @public -*/ -MaterialSpinner.prototype.start = function() { - 'use strict'; - - this.element_.classList.add('is-active'); + * Starts the spinner animation. + * Public method for users who need to manually start the spinner for any reason + * (instead of just adding the 'is-active' class to their markup). + * + * @public + */ +MaterialSpinner.prototype.start = function () { + this.element_.classList.add('is-active'); }; - /** - * Initialize element. - */ -MaterialSpinner.prototype.init = function() { - 'use strict'; - - if (this.element_) { - for (var i = 1; i <= this.Constant_.MDL_SPINNER_LAYER_COUNT; i++) { - this.createLayer(i); + * Initialize element. + */ +MaterialSpinner.prototype.init = function () { + if (this.element_) { + for (var i = 1; i <= this.Constant_.MDL_SPINNER_LAYER_COUNT; i++) { + this.createLayer(i); + } + this.element_.classList.add('is-upgraded'); } - - this.element_.classList.add('is-upgraded'); - } }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialSpinner, - classAsString: 'MaterialSpinner', - cssClass: 'mdl-js-spinner', - widget: true + constructor: MaterialSpinner, + classAsString: 'MaterialSpinner', + cssClass: 'mdl-js-spinner', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -2328,278 +2120,231 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Checkbox MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialSwitch(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialSwitch.prototype.Constant_ = { - TINY_TIMEOUT: 0.001 + * Class constructor for Checkbox MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialSwitch = function MaterialSwitch(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialSwitch = MaterialSwitch; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialSwitch.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialSwitch.prototype.CssClasses_ = { - INPUT: 'mdl-switch__input', - TRACK: 'mdl-switch__track', - THUMB: 'mdl-switch__thumb', - FOCUS_HELPER: 'mdl-switch__focus-helper', - RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', - RIPPLE_CONTAINER: 'mdl-switch__ripple-container', - RIPPLE_CENTER: 'mdl-ripple--center', - RIPPLE: 'mdl-ripple', - IS_FOCUSED: 'is-focused', - IS_DISABLED: 'is-disabled', - IS_CHECKED: 'is-checked' + INPUT: 'mdl-switch__input', + TRACK: 'mdl-switch__track', + THUMB: 'mdl-switch__thumb', + FOCUS_HELPER: 'mdl-switch__focus-helper', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-switch__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked' }; - /** - * Handle change of state. - * @param {Event} event The event that fired. - * @private - */ -MaterialSwitch.prototype.onChange_ = function(event) { - 'use strict'; - - this.updateClasses_(); + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onChange_ = function (event) { + this.updateClasses_(); }; - /** - * Handle focus of element. - * @param {Event} event The event that fired. - * @private - */ -MaterialSwitch.prototype.onFocus_ = function(event) { - 'use strict'; - - this.element_.classList.add(this.CssClasses_.IS_FOCUSED); + * Handle focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle lost focus of element. - * @param {Event} event The event that fired. - * @private - */ -MaterialSwitch.prototype.onBlur_ = function(event) { - 'use strict'; - - this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); + * Handle lost focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle mouseup. - * @param {Event} event The event that fired. - * @private - */ -MaterialSwitch.prototype.onMouseUp_ = function(event) { - 'use strict'; - - this.blur_(); + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onMouseUp_ = function (event) { + this.blur_(); }; - /** - * Handle class updates. - * @private - */ -MaterialSwitch.prototype.updateClasses_ = function() { - 'use strict'; - this.checkDisabled(); - this.checkToggleState(); + * Handle class updates. + * + * @private + */ +MaterialSwitch.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); }; - /** - * Add blur. - * @private - */ -MaterialSwitch.prototype.blur_ = function(event) { - 'use strict'; - - // TODO: figure out why there's a focus event being fired after our blur, - // so that we can avoid this hack. - window.setTimeout(function() { - this.inputElement_.blur(); - }.bind(this), this.Constant_.TINY_TIMEOUT); + * Add blur. + * + * @private + */ +MaterialSwitch.prototype.blur_ = function (event) { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.inputElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); }; - // Public methods. - /** -* Check the components disabled state. -* @public -*/ -MaterialSwitch.prototype.checkDisabled = function() { - 'use strict'; - if (this.inputElement_.disabled) { - this.element_.classList.add(this.CssClasses_.IS_DISABLED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_DISABLED); - } + * Check the components disabled state. + * + * @public + */ +MaterialSwitch.prototype.checkDisabled = function () { + if (this.inputElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } }; - /** -* Check the components toggled state. -* @public -*/ -MaterialSwitch.prototype.checkToggleState = function() { - 'use strict'; - if (this.inputElement_.checked) { - this.element_.classList.add(this.CssClasses_.IS_CHECKED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_CHECKED); - } + * Check the components toggled state. + * + * @public + */ +MaterialSwitch.prototype.checkToggleState = function () { + if (this.inputElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } }; - /** - * Disable switch. - * @public - */ -MaterialSwitch.prototype.disable = function() { - 'use strict'; - - this.inputElement_.disabled = true; - this.updateClasses_(); + * Disable switch. + * + * @public + */ +MaterialSwitch.prototype.disable = function () { + this.inputElement_.disabled = true; + this.updateClasses_(); }; - /** - * Enable switch. - * @public - */ -MaterialSwitch.prototype.enable = function() { - 'use strict'; - - this.inputElement_.disabled = false; - this.updateClasses_(); + * Enable switch. + * + * @public + */ +MaterialSwitch.prototype.enable = function () { + this.inputElement_.disabled = false; + this.updateClasses_(); }; - /** - * Activate switch. - * @public - */ -MaterialSwitch.prototype.on = function() { - 'use strict'; - - this.inputElement_.checked = true; - this.updateClasses_(); + * Activate switch. + * + * @public + */ +MaterialSwitch.prototype.on = function () { + this.inputElement_.checked = true; + this.updateClasses_(); }; - /** - * Deactivate switch. - * @public - */ -MaterialSwitch.prototype.off = function() { - 'use strict'; - - this.inputElement_.checked = false; - this.updateClasses_(); + * Deactivate switch. + * + * @public + */ +MaterialSwitch.prototype.off = function () { + this.inputElement_.checked = false; + this.updateClasses_(); }; - /** - * Initialize element. - */ -MaterialSwitch.prototype.init = function() { - 'use strict'; - - if (this.element_) { - this.inputElement_ = this.element_.querySelector('.' + - this.CssClasses_.INPUT); - - var track = document.createElement('div'); - track.classList.add(this.CssClasses_.TRACK); - - var thumb = document.createElement('div'); - thumb.classList.add(this.CssClasses_.THUMB); - - var focusHelper = document.createElement('span'); - focusHelper.classList.add(this.CssClasses_.FOCUS_HELPER); - - thumb.appendChild(focusHelper); - - this.element_.appendChild(track); - this.element_.appendChild(thumb); - - this.boundMouseUpHandler = this.onMouseUp_.bind(this); - - if (this.element_.classList.contains( - this.CssClasses_.RIPPLE_EFFECT)) { - this.element_.classList.add( - this.CssClasses_.RIPPLE_IGNORE_EVENTS); - this.rippleContainerElement_ = document.createElement('span'); - this.rippleContainerElement_.classList.add( - this.CssClasses_.RIPPLE_CONTAINER); - this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT); - this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); - this.rippleContainerElement_.addEventListener('mouseup', this.boundMouseUpHandler); - - var ripple = document.createElement('span'); - ripple.classList.add(this.CssClasses_.RIPPLE); - - this.rippleContainerElement_.appendChild(ripple); - this.element_.appendChild(this.rippleContainerElement_); + * Initialize element. + */ +MaterialSwitch.prototype.init = function () { + if (this.element_) { + this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + var track = document.createElement('div'); + track.classList.add(this.CssClasses_.TRACK); + var thumb = document.createElement('div'); + thumb.classList.add(this.CssClasses_.THUMB); + var focusHelper = document.createElement('span'); + focusHelper.classList.add(this.CssClasses_.FOCUS_HELPER); + thumb.appendChild(focusHelper); + this.element_.appendChild(track); + this.element_.appendChild(thumb); + this.boundMouseUpHandler = this.onMouseUp_.bind(this); + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + this.rippleContainerElement_ = document.createElement('span'); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); + this.rippleContainerElement_.addEventListener('mouseup', this.boundMouseUpHandler); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + this.rippleContainerElement_.appendChild(ripple); + this.element_.appendChild(this.rippleContainerElement_); + } + this.boundChangeHandler = this.onChange_.bind(this); + this.boundFocusHandler = this.onFocus_.bind(this); + this.boundBlurHandler = this.onBlur_.bind(this); + this.inputElement_.addEventListener('change', this.boundChangeHandler); + this.inputElement_.addEventListener('focus', this.boundFocusHandler); + this.inputElement_.addEventListener('blur', this.boundBlurHandler); + this.element_.addEventListener('mouseup', this.boundMouseUpHandler); + this.updateClasses_(); + this.element_.classList.add('is-upgraded'); } - - this.boundChangeHandler = this.onChange_.bind(this); - this.boundFocusHandler = this.onFocus_.bind(this); - this.boundBlurHandler = this.onBlur_.bind(this); - - this.inputElement_.addEventListener('change', this.boundChangeHandler); - this.inputElement_.addEventListener('focus', this.boundFocusHandler); - this.inputElement_.addEventListener('blur', this.boundBlurHandler); - this.element_.addEventListener('mouseup', this.boundMouseUpHandler); - - this.updateClasses_(); - this.element_.classList.add('is-upgraded'); - } }; - -/* -* Downgrade the component. -*/ -MaterialSwitch.prototype.mdlDowngrade_ = function() { - 'use strict'; - if (this.rippleContainerElement_) { - this.rippleContainerElement_.removeEventListener('mouseup', this.boundMouseUpHandler); - } - this.inputElement_.removeEventListener('change', this.boundChangeHandler); - this.inputElement_.removeEventListener('focus', this.boundFocusHandler); - this.inputElement_.removeEventListener('blur', this.boundBlurHandler); - this.element_.removeEventListener('mouseup', this.boundMouseUpHandler); +/** + * Downgrade the component. + * + * @private + */ +MaterialSwitch.prototype.mdlDowngrade_ = function () { + if (this.rippleContainerElement_) { + this.rippleContainerElement_.removeEventListener('mouseup', this.boundMouseUpHandler); + } + this.inputElement_.removeEventListener('change', this.boundChangeHandler); + this.inputElement_.removeEventListener('focus', this.boundFocusHandler); + this.inputElement_.removeEventListener('blur', this.boundBlurHandler); + this.element_.removeEventListener('mouseup', this.boundMouseUpHandler); }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialSwitch, - classAsString: 'MaterialSwitch', - cssClass: 'mdl-js-switch', - widget: true + constructor: MaterialSwitch, + classAsString: 'MaterialSwitch', + cssClass: 'mdl-js-switch', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -2612,147 +2357,124 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Tabs MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialTabs(element) { - 'use strict'; - - // Stores the HTML element. - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string} - * @private - */ -MaterialTabs.prototype.Constant_ = { - // None at the moment. + * Class constructor for Tabs MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialTabs = function MaterialTabs(element) { + // Stores the HTML element. + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialTabs = MaterialTabs; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String} + * @private + */ +MaterialTabs.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialTabs.prototype.CssClasses_ = { - TAB_CLASS: 'mdl-tabs__tab', - PANEL_CLASS: 'mdl-tabs__panel', - ACTIVE_CLASS: 'is-active', - UPGRADED_CLASS: 'is-upgraded', - - MDL_JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', - MDL_RIPPLE_CONTAINER: 'mdl-tabs__ripple-container', - MDL_RIPPLE: 'mdl-ripple', - MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events' + TAB_CLASS: 'mdl-tabs__tab', + PANEL_CLASS: 'mdl-tabs__panel', + ACTIVE_CLASS: 'is-active', + UPGRADED_CLASS: 'is-upgraded', + MDL_JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', + MDL_RIPPLE_CONTAINER: 'mdl-tabs__ripple-container', + MDL_RIPPLE: 'mdl-ripple', + MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events' }; - /** - * Handle clicks to a tabs component - * @private - */ -MaterialTabs.prototype.initTabs_ = function(e) { - 'use strict'; - - if (this.element_.classList.contains(this.CssClasses_.MDL_JS_RIPPLE_EFFECT)) { - this.element_.classList.add( - this.CssClasses_.MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS); - } - - // Select element tabs, document panels - this.tabs_ = this.element_.querySelectorAll('.' + this.CssClasses_.TAB_CLASS); - this.panels_ = - this.element_.querySelectorAll('.' + this.CssClasses_.PANEL_CLASS); - - // Create new tabs for each tab element - for (var i = 0; i < this.tabs_.length; i++) { - new MaterialTab(this.tabs_[i], this); - } - - this.element_.classList.add(this.CssClasses_.UPGRADED_CLASS); + * Handle clicks to a tabs component + * + * @private + */ +MaterialTabs.prototype.initTabs_ = function () { + if (this.element_.classList.contains(this.CssClasses_.MDL_JS_RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS); + } + // Select element tabs, document panels + this.tabs_ = this.element_.querySelectorAll('.' + this.CssClasses_.TAB_CLASS); + this.panels_ = this.element_.querySelectorAll('.' + this.CssClasses_.PANEL_CLASS); + // Create new tabs for each tab element + for (var i = 0; i < this.tabs_.length; i++) { + new MaterialTab(this.tabs_[i], this); + } + this.element_.classList.add(this.CssClasses_.UPGRADED_CLASS); }; - /** - * Reset tab state, dropping active classes - * @private - */ -MaterialTabs.prototype.resetTabState_ = function() { - 'use strict'; - - for (var k = 0; k < this.tabs_.length; k++) { - this.tabs_[k].classList.remove(this.CssClasses_.ACTIVE_CLASS); - } + * Reset tab state, dropping active classes + * + * @private + */ +MaterialTabs.prototype.resetTabState_ = function () { + for (var k = 0; k < this.tabs_.length; k++) { + this.tabs_[k].classList.remove(this.CssClasses_.ACTIVE_CLASS); + } }; - /** - * Reset panel state, droping active classes - * @private - */ -MaterialTabs.prototype.resetPanelState_ = function() { - 'use strict'; - - for (var j = 0; j < this.panels_.length; j++) { - this.panels_[j].classList.remove(this.CssClasses_.ACTIVE_CLASS); - } + * Reset panel state, droping active classes + * + * @private + */ +MaterialTabs.prototype.resetPanelState_ = function () { + for (var j = 0; j < this.panels_.length; j++) { + this.panels_[j].classList.remove(this.CssClasses_.ACTIVE_CLASS); + } }; - -MaterialTabs.prototype.init = function() { - 'use strict'; - - if (this.element_) { - this.initTabs_(); - } +/** + * Initialize element. + */ +MaterialTabs.prototype.init = function () { + if (this.element_) { + this.initTabs_(); + } }; - function MaterialTab(tab, ctx) { - 'use strict'; - - if (tab) { - if (ctx.element_.classList.contains(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT)) { - var rippleContainer = document.createElement('span'); - rippleContainer.classList.add(ctx.CssClasses_.MDL_RIPPLE_CONTAINER); - rippleContainer.classList.add(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT); - var ripple = document.createElement('span'); - ripple.classList.add(ctx.CssClasses_.MDL_RIPPLE); - rippleContainer.appendChild(ripple); - tab.appendChild(rippleContainer); + if (tab) { + if (ctx.element_.classList.contains(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT)) { + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(ctx.CssClasses_.MDL_RIPPLE_CONTAINER); + rippleContainer.classList.add(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT); + var ripple = document.createElement('span'); + ripple.classList.add(ctx.CssClasses_.MDL_RIPPLE); + rippleContainer.appendChild(ripple); + tab.appendChild(rippleContainer); + } + tab.addEventListener('click', function (e) { + e.preventDefault(); + var href = tab.href.split('#')[1]; + var panel = ctx.element_.querySelector('#' + href); + ctx.resetTabState_(); + ctx.resetPanelState_(); + tab.classList.add(ctx.CssClasses_.ACTIVE_CLASS); + panel.classList.add(ctx.CssClasses_.ACTIVE_CLASS); + }); } - - tab.addEventListener('click', function(e) { - e.preventDefault(); - var href = tab.href.split('#')[1]; - var panel = ctx.element_.querySelector('#' + href); - ctx.resetTabState_(); - ctx.resetPanelState_(); - tab.classList.add(ctx.CssClasses_.ACTIVE_CLASS); - panel.classList.add(ctx.CssClasses_.ACTIVE_CLASS); - }); - - } } - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialTabs, - classAsString: 'MaterialTabs', - cssClass: 'mdl-js-tabs' + constructor: MaterialTabs, + classAsString: 'MaterialTabs', + cssClass: 'mdl-js-tabs' }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -2765,242 +2487,212 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Textfield MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialTextfield(element) { - 'use strict'; - - this.element_ = element; - this.maxRows = this.Constant_.NO_MAX_ROWS; - // Initialize instance. - this.init(); -} - + * Class constructor for Textfield MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialTextfield = function MaterialTextfield(element) { + this.element_ = element; + this.maxRows = this.Constant_.NO_MAX_ROWS; + // Initialize instance. + this.init(); +}; +window.MaterialTextfield = MaterialTextfield; /** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ MaterialTextfield.prototype.Constant_ = { - NO_MAX_ROWS: -1, - MAX_ROWS_ATTRIBUTE: 'maxrows' + NO_MAX_ROWS: -1, + MAX_ROWS_ATTRIBUTE: 'maxrows' }; - /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialTextfield.prototype.CssClasses_ = { - LABEL: 'mdl-textfield__label', - INPUT: 'mdl-textfield__input', - IS_DIRTY: 'is-dirty', - IS_FOCUSED: 'is-focused', - IS_DISABLED: 'is-disabled', - IS_INVALID: 'is-invalid', - IS_UPGRADED: 'is-upgraded' + LABEL: 'mdl-textfield__label', + INPUT: 'mdl-textfield__input', + IS_DIRTY: 'is-dirty', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_INVALID: 'is-invalid', + IS_UPGRADED: 'is-upgraded' }; - /** - * Handle input being entered. - * @param {Event} event The event that fired. - * @private - */ -MaterialTextfield.prototype.onKeyDown_ = function(event) { - 'use strict'; - - var currentRowCount = event.target.value.split('\n').length; - if (event.keyCode === 13) { - if (currentRowCount >= this.maxRows) { - event.preventDefault(); + * Handle input being entered. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTextfield.prototype.onKeyDown_ = function (event) { + var currentRowCount = event.target.value.split('\n').length; + if (event.keyCode === 13) { + if (currentRowCount >= this.maxRows) { + event.preventDefault(); + } } - } }; - /** - * Handle focus. - * @param {Event} event The event that fired. - * @private - */ -MaterialTextfield.prototype.onFocus_ = function(event) { - 'use strict'; - - this.element_.classList.add(this.CssClasses_.IS_FOCUSED); + * Handle focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTextfield.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle lost focus. - * @param {Event} event The event that fired. - * @private - */ -MaterialTextfield.prototype.onBlur_ = function(event) { - 'use strict'; - - this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); + * Handle lost focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTextfield.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); }; - /** - * Handle class updates. - * @param {HTMLElement} button The button whose classes we should update. - * @param {HTMLElement} label The label whose classes we should update. - * @private - */ -MaterialTextfield.prototype.updateClasses_ = function() { - 'use strict'; - this.checkDisabled(); - this.checkValidity(); - this.checkDirty(); + * Handle class updates. + * + * @private + */ +MaterialTextfield.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkValidity(); + this.checkDirty(); }; - // Public methods. - /** - * Check the disabled state and update field accordingly. - * @public - */ -MaterialTextfield.prototype.checkDisabled = function() { - 'use strict'; - if (this.input_.disabled) { - this.element_.classList.add(this.CssClasses_.IS_DISABLED); - } else { - this.element_.classList.remove(this.CssClasses_.IS_DISABLED); - } + * Check the disabled state and update field accordingly. + * + * @public + */ +MaterialTextfield.prototype.checkDisabled = function () { + if (this.input_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } }; - /** - * Check the validity state and update field accordingly. - * @public - */ -MaterialTextfield.prototype.checkValidity = function() { - 'use strict'; - if (this.input_.validity.valid) { - this.element_.classList.remove(this.CssClasses_.IS_INVALID); - } else { - this.element_.classList.add(this.CssClasses_.IS_INVALID); - } + * Check the validity state and update field accordingly. + * + * @public + */ +MaterialTextfield.prototype.checkValidity = function () { + if (this.input_.validity.valid) { + this.element_.classList.remove(this.CssClasses_.IS_INVALID); + } else { + this.element_.classList.add(this.CssClasses_.IS_INVALID); + } }; - /** -* Check the dirty state and update field accordingly. -* @public -*/ -MaterialTextfield.prototype.checkDirty = function() { - 'use strict'; - if (this.input_.value && this.input_.value.length > 0) { - this.element_.classList.add(this.CssClasses_.IS_DIRTY); - } else { - this.element_.classList.remove(this.CssClasses_.IS_DIRTY); - } + * Check the dirty state and update field accordingly. + * + * @public + */ +MaterialTextfield.prototype.checkDirty = function () { + if (this.input_.value && this.input_.value.length > 0) { + this.element_.classList.add(this.CssClasses_.IS_DIRTY); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DIRTY); + } }; - /** - * Disable text field. - * @public - */ -MaterialTextfield.prototype.disable = function() { - 'use strict'; - - this.input_.disabled = true; - this.updateClasses_(); + * Disable text field. + * + * @public + */ +MaterialTextfield.prototype.disable = function () { + this.input_.disabled = true; + this.updateClasses_(); }; - /** - * Enable text field. - * @public - */ -MaterialTextfield.prototype.enable = function() { - 'use strict'; - - this.input_.disabled = false; - this.updateClasses_(); + * Enable text field. + * + * @public + */ +MaterialTextfield.prototype.enable = function () { + this.input_.disabled = false; + this.updateClasses_(); }; - /** - * Update text field value. - * @param {String} value The value to which to set the control (optional). - * @public - */ -MaterialTextfield.prototype.change = function(value) { - 'use strict'; - - if (value) { - this.input_.value = value; - } - this.updateClasses_(); + * Update text field value. + * + * @param {String} value The value to which to set the control (optional). + * @public + */ +MaterialTextfield.prototype.change = function (value) { + if (value) { + this.input_.value = value; + } + this.updateClasses_(); }; - /** - * Initialize element. - */ -MaterialTextfield.prototype.init = function() { - 'use strict'; - - if (this.element_) { - this.label_ = this.element_.querySelector('.' + this.CssClasses_.LABEL); - this.input_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); - - if (this.input_) { - if (this.input_.hasAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE)) { - this.maxRows = parseInt(this.input_.getAttribute( - this.Constant_.MAX_ROWS_ATTRIBUTE), 10); - if (isNaN(this.maxRows)) { - this.maxRows = this.Constant_.NO_MAX_ROWS; + * Initialize element. + */ +MaterialTextfield.prototype.init = function () { + if (this.element_) { + this.label_ = this.element_.querySelector('.' + this.CssClasses_.LABEL); + this.input_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + if (this.input_) { + if (this.input_.hasAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE)) { + this.maxRows = parseInt(this.input_.getAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE), 10); + if (isNaN(this.maxRows)) { + this.maxRows = this.Constant_.NO_MAX_ROWS; + } + } + this.boundUpdateClassesHandler = this.updateClasses_.bind(this); + this.boundFocusHandler = this.onFocus_.bind(this); + this.boundBlurHandler = this.onBlur_.bind(this); + this.input_.addEventListener('input', this.boundUpdateClassesHandler); + this.input_.addEventListener('focus', this.boundFocusHandler); + this.input_.addEventListener('blur', this.boundBlurHandler); + if (this.maxRows !== this.Constant_.NO_MAX_ROWS) { + // TODO: This should handle pasting multi line text. + // Currently doesn't. + this.boundKeyDownHandler = this.onKeyDown_.bind(this); + this.input_.addEventListener('keydown', this.boundKeyDownHandler); + } + this.updateClasses_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); } - } - - this.boundUpdateClassesHandler = this.updateClasses_.bind(this); - this.boundFocusHandler = this.onFocus_.bind(this); - this.boundBlurHandler = this.onBlur_.bind(this); - this.input_.addEventListener('input', this.boundUpdateClassesHandler); - this.input_.addEventListener('focus', this.boundFocusHandler); - this.input_.addEventListener('blur', this.boundBlurHandler); - - if (this.maxRows !== this.Constant_.NO_MAX_ROWS) { - // TODO: This should handle pasting multi line text. - // Currently doesn't. - this.boundKeyDownHandler = this.onKeyDown_.bind(this); - this.input_.addEventListener('keydown', this.boundKeyDownHandler); - } - - this.updateClasses_(); - this.element_.classList.add(this.CssClasses_.IS_UPGRADED); } - } }; - -/* -* Downgrade the component -*/ -MaterialTextfield.prototype.mdlDowngrade_ = function() { - 'use strict'; - this.input_.removeEventListener('input', this.boundUpdateClassesHandler); - this.input_.removeEventListener('focus', this.boundFocusHandler); - this.input_.removeEventListener('blur', this.boundBlurHandler); - if (this.boundKeyDownHandler) { - this.input_.removeEventListener('keydown', this.boundKeyDownHandler); - } +/** + * Downgrade the component + * + * @private + */ +MaterialTextfield.prototype.mdlDowngrade_ = function () { + this.input_.removeEventListener('input', this.boundUpdateClassesHandler); + this.input_.removeEventListener('focus', this.boundFocusHandler); + this.input_.removeEventListener('blur', this.boundBlurHandler); + if (this.boundKeyDownHandler) { + this.input_.removeEventListener('keydown', this.boundKeyDownHandler); + } }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialTextfield, - classAsString: 'MaterialTextfield', - cssClass: 'mdl-js-textfield', - widget: true + constructor: MaterialTextfield, + classAsString: 'MaterialTextfield', + cssClass: 'mdl-js-textfield', + widget: true }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -3013,141 +2705,118 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Tooltip MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialTooltip(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialTooltip.prototype.Constant_ = { - // None for now. + * Class constructor for Tooltip MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialTooltip = function MaterialTooltip(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialTooltip = MaterialTooltip; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ -MaterialTooltip.prototype.CssClasses_ = { - IS_ACTIVE: 'is-active' -}; - + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialTooltip.prototype.Constant_ = {}; /** - * Handle mouseenter for tooltip. - * @param {Event} event The event that fired. - * @private - */ -MaterialTooltip.prototype.handleMouseEnter_ = function(event) { - 'use strict'; - - event.stopPropagation(); - var props = event.target.getBoundingClientRect(); - var left = props.left + (props.width / 2); - var marginLeft = -1 * (this.element_.offsetWidth / 2); - - if (left + marginLeft < 0) { - this.element_.style.left = 0; - this.element_.style.marginLeft = 0; - } else { - this.element_.style.left = left + 'px'; - this.element_.style.marginLeft = marginLeft + 'px'; - } - - this.element_.style.top = props.top + props.height + 10 + 'px'; - this.element_.classList.add(this.CssClasses_.IS_ACTIVE); - window.addEventListener('scroll', this.boundMouseLeaveHandler, false); - window.addEventListener('touchmove', this.boundMouseLeaveHandler, false); + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ +MaterialTooltip.prototype.CssClasses_ = { IS_ACTIVE: 'is-active' }; +/** + * Handle mouseenter for tooltip. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTooltip.prototype.handleMouseEnter_ = function (event) { + event.stopPropagation(); + var props = event.target.getBoundingClientRect(); + var left = props.left + props.width / 2; + var marginLeft = -1 * (this.element_.offsetWidth / 2); + if (left + marginLeft < 0) { + this.element_.style.left = 0; + this.element_.style.marginLeft = 0; + } else { + this.element_.style.left = left + 'px'; + this.element_.style.marginLeft = marginLeft + 'px'; + } + this.element_.style.top = props.top + props.height + 10 + 'px'; + this.element_.classList.add(this.CssClasses_.IS_ACTIVE); + window.addEventListener('scroll', this.boundMouseLeaveHandler, false); + window.addEventListener('touchmove', this.boundMouseLeaveHandler, false); }; - /** - * Handle mouseleave for tooltip. - * @param {Event} event The event that fired. - * @private - */ -MaterialTooltip.prototype.handleMouseLeave_ = function(event) { - 'use strict'; - - event.stopPropagation(); - this.element_.classList.remove(this.CssClasses_.IS_ACTIVE); - window.removeEventListener('scroll', this.boundMouseLeaveHandler); - window.removeEventListener('touchmove', this.boundMouseLeaveHandler, false); + * Handle mouseleave for tooltip. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTooltip.prototype.handleMouseLeave_ = function (event) { + event.stopPropagation(); + this.element_.classList.remove(this.CssClasses_.IS_ACTIVE); + window.removeEventListener('scroll', this.boundMouseLeaveHandler); + window.removeEventListener('touchmove', this.boundMouseLeaveHandler, false); }; - /** - * Initialize element. - */ -MaterialTooltip.prototype.init = function() { - 'use strict'; - - if (this.element_) { - var forElId = this.element_.getAttribute('for'); - - if (forElId) { - this.forElement_ = document.getElementById(forElId); + * Initialize element. + */ +MaterialTooltip.prototype.init = function () { + if (this.element_) { + var forElId = this.element_.getAttribute('for'); + if (forElId) { + this.forElement_ = document.getElementById(forElId); + } + if (this.forElement_) { + // Tabindex needs to be set for `blur` events to be emitted + if (!this.forElement_.getAttribute('tabindex')) { + this.forElement_.setAttribute('tabindex', '0'); + } + this.boundMouseEnterHandler = this.handleMouseEnter_.bind(this); + this.boundMouseLeaveHandler = this.handleMouseLeave_.bind(this); + this.forElement_.addEventListener('mouseenter', this.boundMouseEnterHandler, false); + this.forElement_.addEventListener('click', this.boundMouseEnterHandler, false); + this.forElement_.addEventListener('blur', this.boundMouseLeaveHandler); + this.forElement_.addEventListener('touchstart', this.boundMouseEnterHandler, false); + this.forElement_.addEventListener('mouseleave', this.boundMouseLeaveHandler); + } } - +}; +/** + * Downgrade the component + * + * @private + */ +MaterialTooltip.prototype.mdlDowngrade_ = function () { if (this.forElement_) { - // Tabindex needs to be set for `blur` events to be emitted - if (!this.forElement_.getAttribute('tabindex')) { - this.forElement_.setAttribute('tabindex', '0'); - } - - this.boundMouseEnterHandler = this.handleMouseEnter_.bind(this); - this.boundMouseLeaveHandler = this.handleMouseLeave_.bind(this); - this.forElement_.addEventListener('mouseenter', this.boundMouseEnterHandler, - false); - this.forElement_.addEventListener('click', this.boundMouseEnterHandler, - false); - this.forElement_.addEventListener('blur', this.boundMouseLeaveHandler); - this.forElement_.addEventListener('touchstart', this.boundMouseEnterHandler, - false); - this.forElement_.addEventListener('mouseleave', this.boundMouseLeaveHandler); + this.forElement_.removeEventListener('mouseenter', this.boundMouseEnterHandler, false); + this.forElement_.removeEventListener('click', this.boundMouseEnterHandler, false); + this.forElement_.removeEventListener('touchstart', this.boundMouseEnterHandler, false); + this.forElement_.removeEventListener('mouseleave', this.boundMouseLeaveHandler); } - } }; - -/* -* Downgrade the component -*/ -MaterialTooltip.prototype.mdlDowngrade_ = function() { - 'use strict'; - if (this.forElement_) { - this.forElement_.removeEventListener('mouseenter', this.boundMouseEnterHandler, false); - this.forElement_.removeEventListener('click', this.boundMouseEnterHandler, false); - this.forElement_.removeEventListener('touchstart', this.boundMouseEnterHandler, false); - this.forElement_.removeEventListener('mouseleave', this.boundMouseLeaveHandler); - } -}; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialTooltip, - classAsString: 'MaterialTooltip', - cssClass: 'mdl-tooltip' + constructor: MaterialTooltip, + classAsString: 'MaterialTooltip', + cssClass: 'mdl-tooltip' }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -3160,429 +2829,360 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Layout MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialLayout(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - + * Class constructor for Layout MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialLayout = function MaterialLayout(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window.MaterialLayout = MaterialLayout; /** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ MaterialLayout.prototype.Constant_ = { - MAX_WIDTH: '(max-width: 1024px)', - TAB_SCROLL_PIXELS: 100, - - MENU_ICON: 'menu', - CHEVRON_LEFT: 'chevron_left', - CHEVRON_RIGHT: 'chevron_right' + MAX_WIDTH: '(max-width: 1024px)', + TAB_SCROLL_PIXELS: 100, + MENU_ICON: 'menu', + CHEVRON_LEFT: 'chevron_left', + CHEVRON_RIGHT: 'chevron_right' }; - /** - * Modes. - * @enum {number} - * @private - */ + * Modes. + * + * @enum {Number} + * @private + */ MaterialLayout.prototype.Mode_ = { - STANDARD: 0, - SEAMED: 1, - WATERFALL: 2, - SCROLL: 3 + STANDARD: 0, + SEAMED: 1, + WATERFALL: 2, + SCROLL: 3 }; - /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialLayout.prototype.CssClasses_ = { - CONTAINER: 'mdl-layout__container', - HEADER: 'mdl-layout__header', - DRAWER: 'mdl-layout__drawer', - CONTENT: 'mdl-layout__content', - DRAWER_BTN: 'mdl-layout__drawer-button', - - ICON: 'material-icons', - - JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', - RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container', - RIPPLE: 'mdl-ripple', - RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', - - HEADER_SEAMED: 'mdl-layout__header--seamed', - HEADER_WATERFALL: 'mdl-layout__header--waterfall', - HEADER_SCROLL: 'mdl-layout__header--scroll', - - FIXED_HEADER: 'mdl-layout--fixed-header', - OBFUSCATOR: 'mdl-layout__obfuscator', - - TAB_BAR: 'mdl-layout__tab-bar', - TAB_CONTAINER: 'mdl-layout__tab-bar-container', - TAB: 'mdl-layout__tab', - TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button', - TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button', - TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button', - PANEL: 'mdl-layout__tab-panel', - - HAS_DRAWER: 'has-drawer', - HAS_TABS: 'has-tabs', - HAS_SCROLLING_HEADER: 'has-scrolling-header', - CASTING_SHADOW: 'is-casting-shadow', - IS_COMPACT: 'is-compact', - IS_SMALL_SCREEN: 'is-small-screen', - IS_DRAWER_OPEN: 'is-visible', - IS_ACTIVE: 'is-active', - IS_UPGRADED: 'is-upgraded', - IS_ANIMATING: 'is-animating', - - ON_LARGE_SCREEN : 'mdl-layout--large-screen-only', - ON_SMALL_SCREEN : 'mdl-layout--small-screen-only' - + CONTAINER: 'mdl-layout__container', + HEADER: 'mdl-layout__header', + DRAWER: 'mdl-layout__drawer', + CONTENT: 'mdl-layout__content', + DRAWER_BTN: 'mdl-layout__drawer-button', + ICON: 'material-icons', + JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container', + RIPPLE: 'mdl-ripple', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + HEADER_SEAMED: 'mdl-layout__header--seamed', + HEADER_WATERFALL: 'mdl-layout__header--waterfall', + HEADER_SCROLL: 'mdl-layout__header--scroll', + FIXED_HEADER: 'mdl-layout--fixed-header', + OBFUSCATOR: 'mdl-layout__obfuscator', + TAB_BAR: 'mdl-layout__tab-bar', + TAB_CONTAINER: 'mdl-layout__tab-bar-container', + TAB: 'mdl-layout__tab', + TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button', + TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button', + TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button', + PANEL: 'mdl-layout__tab-panel', + HAS_DRAWER: 'has-drawer', + HAS_TABS: 'has-tabs', + HAS_SCROLLING_HEADER: 'has-scrolling-header', + CASTING_SHADOW: 'is-casting-shadow', + IS_COMPACT: 'is-compact', + IS_SMALL_SCREEN: 'is-small-screen', + IS_DRAWER_OPEN: 'is-visible', + IS_ACTIVE: 'is-active', + IS_UPGRADED: 'is-upgraded', + IS_ANIMATING: 'is-animating', + ON_LARGE_SCREEN: 'mdl-layout--large-screen-only', + ON_SMALL_SCREEN: 'mdl-layout--small-screen-only' }; - /** - * Handles scrolling on the content. - * @private - */ -MaterialLayout.prototype.contentScrollHandler_ = function() { - 'use strict'; - - if (this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)) { - return; - } - - if (this.content_.scrollTop > 0 && - !this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { - this.header_.classList.add(this.CssClasses_.CASTING_SHADOW); - this.header_.classList.add(this.CssClasses_.IS_COMPACT); - this.header_.classList.add(this.CssClasses_.IS_ANIMATING); - } else if (this.content_.scrollTop <= 0 && - this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { - this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW); - this.header_.classList.remove(this.CssClasses_.IS_COMPACT); - this.header_.classList.add(this.CssClasses_.IS_ANIMATING); - } + * Handles scrolling on the content. + * + * @private + */ +MaterialLayout.prototype.contentScrollHandler_ = function () { + if (this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)) { + return; + } + if (this.content_.scrollTop > 0 && !this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { + this.header_.classList.add(this.CssClasses_.CASTING_SHADOW); + this.header_.classList.add(this.CssClasses_.IS_COMPACT); + this.header_.classList.add(this.CssClasses_.IS_ANIMATING); + } else if (this.content_.scrollTop <= 0 && this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { + this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW); + this.header_.classList.remove(this.CssClasses_.IS_COMPACT); + this.header_.classList.add(this.CssClasses_.IS_ANIMATING); + } }; - /** - * Handles changes in screen size. - * @private - */ -MaterialLayout.prototype.screenSizeHandler_ = function() { - 'use strict'; - - if (this.screenSizeMediaQuery_.matches) { - this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN); - } else { - this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN); - // Collapse drawer (if any) when moving to a large screen size. - if (this.drawer_) { - this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); + * Handles changes in screen size. + * + * @private + */ +MaterialLayout.prototype.screenSizeHandler_ = function () { + if (this.screenSizeMediaQuery_.matches) { + this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN); + } else { + this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN); + // Collapse drawer (if any) when moving to a large screen size. + if (this.drawer_) { + this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); + } } - } }; - /** - * Handles toggling of the drawer. - * @param {Element} drawer The drawer container element. - * @private - */ -MaterialLayout.prototype.drawerToggleHandler_ = function() { - 'use strict'; - - this.drawer_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN); + * Handles toggling of the drawer. + * + * @private + */ +MaterialLayout.prototype.drawerToggleHandler_ = function () { + this.drawer_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN); }; - /** - * Handles (un)setting the `is-animating` class - */ -MaterialLayout.prototype.headerTransitionEndHandler = function() { - 'use strict'; - - this.header_.classList.remove(this.CssClasses_.IS_ANIMATING); + * Handles (un)setting the `is-animating` class + * + * @private + */ +MaterialLayout.prototype.headerTransitionEndHandler_ = function () { + this.header_.classList.remove(this.CssClasses_.IS_ANIMATING); }; - /** - * Handles expanding the header on click - */ -MaterialLayout.prototype.headerClickHandler = function() { - 'use strict'; - - if (this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { - this.header_.classList.remove(this.CssClasses_.IS_COMPACT); - this.header_.classList.add(this.CssClasses_.IS_ANIMATING); - } + * Handles expanding the header on click + * + * @private + */ +MaterialLayout.prototype.headerClickHandler_ = function () { + if (this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { + this.header_.classList.remove(this.CssClasses_.IS_COMPACT); + this.header_.classList.add(this.CssClasses_.IS_ANIMATING); + } }; - /** - * Reset tab state, dropping active classes - * @private - */ -MaterialLayout.prototype.resetTabState_ = function(tabBar) { - 'use strict'; - - for (var k = 0; k < tabBar.length; k++) { - tabBar[k].classList.remove(this.CssClasses_.IS_ACTIVE); - } + * Reset tab state, dropping active classes + * + * @private + */ +MaterialLayout.prototype.resetTabState_ = function (tabBar) { + for (var k = 0; k < tabBar.length; k++) { + tabBar[k].classList.remove(this.CssClasses_.IS_ACTIVE); + } }; - /** - * Reset panel state, droping active classes - * @private - */ -MaterialLayout.prototype.resetPanelState_ = function(panels) { - 'use strict'; - - for (var j = 0; j < panels.length; j++) { - panels[j].classList.remove(this.CssClasses_.IS_ACTIVE); - } + * Reset panel state, droping active classes + * + * @private + */ +MaterialLayout.prototype.resetPanelState_ = function (panels) { + for (var j = 0; j < panels.length; j++) { + panels[j].classList.remove(this.CssClasses_.IS_ACTIVE); + } }; - /** - * Initialize element. - */ -MaterialLayout.prototype.init = function() { - 'use strict'; - - if (this.element_) { - var container = document.createElement('div'); - container.classList.add(this.CssClasses_.CONTAINER); - this.element_.parentElement.insertBefore(container, this.element_); - this.element_.parentElement.removeChild(this.element_); - container.appendChild(this.element_); - - var directChildren = this.element_.childNodes; - for (var c = 0; c < directChildren.length; c++) { - var child = directChildren[c]; - if (child.classList && - child.classList.contains(this.CssClasses_.HEADER)) { - this.header_ = child; - } - - if (child.classList && - child.classList.contains(this.CssClasses_.DRAWER)) { - this.drawer_ = child; - } - - if (child.classList && - child.classList.contains(this.CssClasses_.CONTENT)) { - this.content_ = child; - } - } - - if (this.header_) { - this.tabBar_ = this.header_.querySelector('.' + this.CssClasses_.TAB_BAR); - } - - var mode = this.Mode_.STANDARD; - - // Keep an eye on screen size, and add/remove auxiliary class for styling - // of small screens. - this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH); - this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this)); - this.screenSizeHandler_(); - - if (this.header_) { - if (this.header_.classList.contains(this.CssClasses_.HEADER_SEAMED)) { - mode = this.Mode_.SEAMED; - } else if (this.header_.classList.contains( - this.CssClasses_.HEADER_WATERFALL)) { - mode = this.Mode_.WATERFALL; - this.header_.addEventListener('transitionend', - this.headerTransitionEndHandler.bind(this)); - this.header_.addEventListener('click', - this.headerClickHandler.bind(this)); - } else if (this.header_.classList.contains( - this.CssClasses_.HEADER_SCROLL)) { - mode = this.Mode_.SCROLL; - container.classList.add(this.CssClasses_.HAS_SCROLLING_HEADER); - } - - if (mode === this.Mode_.STANDARD) { - this.header_.classList.add(this.CssClasses_.CASTING_SHADOW); - if (this.tabBar_) { - this.tabBar_.classList.add(this.CssClasses_.CASTING_SHADOW); + * Initialize element. + */ +MaterialLayout.prototype.init = function () { + if (this.element_) { + var container = document.createElement('div'); + container.classList.add(this.CssClasses_.CONTAINER); + this.element_.parentElement.insertBefore(container, this.element_); + this.element_.parentElement.removeChild(this.element_); + container.appendChild(this.element_); + var directChildren = this.element_.childNodes; + for (var c = 0; c < directChildren.length; c++) { + var child = directChildren[c]; + if (child.classList && child.classList.contains(this.CssClasses_.HEADER)) { + this.header_ = child; + } + if (child.classList && child.classList.contains(this.CssClasses_.DRAWER)) { + this.drawer_ = child; + } + if (child.classList && child.classList.contains(this.CssClasses_.CONTENT)) { + this.content_ = child; + } } - } else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) { - this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW); - if (this.tabBar_) { - this.tabBar_.classList.remove(this.CssClasses_.CASTING_SHADOW); + if (this.header_) { + this.tabBar_ = this.header_.querySelector('.' + this.CssClasses_.TAB_BAR); } - } else if (mode === this.Mode_.WATERFALL) { - // Add and remove shadows depending on scroll position. - // Also add/remove auxiliary class for styling of the compact version of - // the header. - this.content_.addEventListener('scroll', - this.contentScrollHandler_.bind(this)); - this.contentScrollHandler_(); - } - } - - // Add drawer toggling button to our layout, if we have an openable drawer. - if (this.drawer_) { - var drawerButton = document.createElement('div'); - drawerButton.classList.add(this.CssClasses_.DRAWER_BTN); - - if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) { - //If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well. - drawerButton.classList.add(this.CssClasses_.ON_LARGE_SCREEN); - } else if (this.drawer_.classList.contains(this.CssClasses_.ON_SMALL_SCREEN)) { - //If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well. - drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN); - } - var drawerButtonIcon = document.createElement('i'); - drawerButtonIcon.classList.add(this.CssClasses_.ICON); - drawerButtonIcon.textContent = this.Constant_.MENU_ICON; - drawerButton.appendChild(drawerButtonIcon); - drawerButton.addEventListener('click', - this.drawerToggleHandler_.bind(this)); - - // Add a class if the layout has a drawer, for altering the left padding. - // Adds the HAS_DRAWER to the elements since this.header_ may or may - // not be present. - this.element_.classList.add(this.CssClasses_.HAS_DRAWER); - - // If we have a fixed header, add the button to the header rather than - // the layout. - if (this.element_.classList.contains(this.CssClasses_.FIXED_HEADER)) { - this.header_.insertBefore(drawerButton, this.header_.firstChild); - } else { - this.element_.insertBefore(drawerButton, this.content_); - } - - var obfuscator = document.createElement('div'); - obfuscator.classList.add(this.CssClasses_.OBFUSCATOR); - this.element_.appendChild(obfuscator); - obfuscator.addEventListener('click', - this.drawerToggleHandler_.bind(this)); - } - - // Initialize tabs, if any. - if (this.header_ && this.tabBar_) { - this.element_.classList.add(this.CssClasses_.HAS_TABS); - - var tabContainer = document.createElement('div'); - tabContainer.classList.add(this.CssClasses_.TAB_CONTAINER); - this.header_.insertBefore(tabContainer, this.tabBar_); - this.header_.removeChild(this.tabBar_); - - var leftButton = document.createElement('div'); - leftButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON); - leftButton.classList.add(this.CssClasses_.TAB_BAR_LEFT_BUTTON); - var leftButtonIcon = document.createElement('i'); - leftButtonIcon.classList.add(this.CssClasses_.ICON); - leftButtonIcon.textContent = this.Constant_.CHEVRON_LEFT; - leftButton.appendChild(leftButtonIcon); - leftButton.addEventListener('click', function() { - this.tabBar_.scrollLeft -= this.Constant_.TAB_SCROLL_PIXELS; - }.bind(this)); - - var rightButton = document.createElement('div'); - rightButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON); - rightButton.classList.add(this.CssClasses_.TAB_BAR_RIGHT_BUTTON); - var rightButtonIcon = document.createElement('i'); - rightButtonIcon.classList.add(this.CssClasses_.ICON); - rightButtonIcon.textContent = this.Constant_.CHEVRON_RIGHT; - rightButton.appendChild(rightButtonIcon); - rightButton.addEventListener('click', function() { - this.tabBar_.scrollLeft += this.Constant_.TAB_SCROLL_PIXELS; - }.bind(this)); - - tabContainer.appendChild(leftButton); - tabContainer.appendChild(this.tabBar_); - tabContainer.appendChild(rightButton); - - // Add and remove buttons depending on scroll position. - var tabScrollHandler = function() { - if (this.tabBar_.scrollLeft > 0) { - leftButton.classList.add(this.CssClasses_.IS_ACTIVE); - } else { - leftButton.classList.remove(this.CssClasses_.IS_ACTIVE); + var mode = this.Mode_.STANDARD; + // Keep an eye on screen size, and add/remove auxiliary class for styling + // of small screens. + this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH); + this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this)); + this.screenSizeHandler_(); + if (this.header_) { + if (this.header_.classList.contains(this.CssClasses_.HEADER_SEAMED)) { + mode = this.Mode_.SEAMED; + } else if (this.header_.classList.contains(this.CssClasses_.HEADER_WATERFALL)) { + mode = this.Mode_.WATERFALL; + this.header_.addEventListener('transitionend', this.headerTransitionEndHandler_.bind(this)); + this.header_.addEventListener('click', this.headerClickHandler_.bind(this)); + } else if (this.header_.classList.contains(this.CssClasses_.HEADER_SCROLL)) { + mode = this.Mode_.SCROLL; + container.classList.add(this.CssClasses_.HAS_SCROLLING_HEADER); + } + if (mode === this.Mode_.STANDARD) { + this.header_.classList.add(this.CssClasses_.CASTING_SHADOW); + if (this.tabBar_) { + this.tabBar_.classList.add(this.CssClasses_.CASTING_SHADOW); + } + } else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) { + this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW); + if (this.tabBar_) { + this.tabBar_.classList.remove(this.CssClasses_.CASTING_SHADOW); + } + } else if (mode === this.Mode_.WATERFALL) { + // Add and remove shadows depending on scroll position. + // Also add/remove auxiliary class for styling of the compact version of + // the header. + this.content_.addEventListener('scroll', this.contentScrollHandler_.bind(this)); + this.contentScrollHandler_(); + } } - - if (this.tabBar_.scrollLeft < - this.tabBar_.scrollWidth - this.tabBar_.offsetWidth) { - rightButton.classList.add(this.CssClasses_.IS_ACTIVE); - } else { - rightButton.classList.remove(this.CssClasses_.IS_ACTIVE); + var eatEvent = function (ev) { + ev.preventDefault(); + }; + // Add drawer toggling button to our layout, if we have an openable drawer. + if (this.drawer_) { + var drawerButton = document.createElement('div'); + drawerButton.classList.add(this.CssClasses_.DRAWER_BTN); + if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) { + //If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well. + drawerButton.classList.add(this.CssClasses_.ON_LARGE_SCREEN); + } else if (this.drawer_.classList.contains(this.CssClasses_.ON_SMALL_SCREEN)) { + //If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well. + drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN); + } + var drawerButtonIcon = document.createElement('i'); + drawerButtonIcon.classList.add(this.CssClasses_.ICON); + drawerButtonIcon.textContent = this.Constant_.MENU_ICON; + drawerButton.appendChild(drawerButtonIcon); + drawerButton.addEventListener('click', this.drawerToggleHandler_.bind(this)); + // Add a class if the layout has a drawer, for altering the left padding. + // Adds the HAS_DRAWER to the elements since this.header_ may or may + // not be present. + this.element_.classList.add(this.CssClasses_.HAS_DRAWER); + this.drawer_.addEventListener('mousewheel', eatEvent); + // If we have a fixed header, add the button to the header rather than + // the layout. + if (this.element_.classList.contains(this.CssClasses_.FIXED_HEADER)) { + this.header_.insertBefore(drawerButton, this.header_.firstChild); + } else { + this.element_.insertBefore(drawerButton, this.content_); + } + var obfuscator = document.createElement('div'); + obfuscator.classList.add(this.CssClasses_.OBFUSCATOR); + this.element_.appendChild(obfuscator); + obfuscator.addEventListener('click', this.drawerToggleHandler_.bind(this)); + obfuscator.addEventListener('mousewheel', eatEvent); } - }.bind(this); - - this.tabBar_.addEventListener('scroll', tabScrollHandler); - tabScrollHandler(); - - if (this.tabBar_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) { - this.tabBar_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); - } - - // Select element tabs, document panels - var tabs = this.tabBar_.querySelectorAll('.' + this.CssClasses_.TAB); - var panels = this.content_.querySelectorAll('.' + this.CssClasses_.PANEL); - - // Create new tabs for each tab element - for (var i = 0; i < tabs.length; i++) { - new MaterialLayoutTab(tabs[i], tabs, panels, this); - } + // Initialize tabs, if any. + if (this.header_ && this.tabBar_) { + this.element_.classList.add(this.CssClasses_.HAS_TABS); + var tabContainer = document.createElement('div'); + tabContainer.classList.add(this.CssClasses_.TAB_CONTAINER); + this.header_.insertBefore(tabContainer, this.tabBar_); + this.header_.removeChild(this.tabBar_); + var leftButton = document.createElement('div'); + leftButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON); + leftButton.classList.add(this.CssClasses_.TAB_BAR_LEFT_BUTTON); + var leftButtonIcon = document.createElement('i'); + leftButtonIcon.classList.add(this.CssClasses_.ICON); + leftButtonIcon.textContent = this.Constant_.CHEVRON_LEFT; + leftButton.appendChild(leftButtonIcon); + leftButton.addEventListener('click', function () { + this.tabBar_.scrollLeft -= this.Constant_.TAB_SCROLL_PIXELS; + }.bind(this)); + var rightButton = document.createElement('div'); + rightButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON); + rightButton.classList.add(this.CssClasses_.TAB_BAR_RIGHT_BUTTON); + var rightButtonIcon = document.createElement('i'); + rightButtonIcon.classList.add(this.CssClasses_.ICON); + rightButtonIcon.textContent = this.Constant_.CHEVRON_RIGHT; + rightButton.appendChild(rightButtonIcon); + rightButton.addEventListener('click', function () { + this.tabBar_.scrollLeft += this.Constant_.TAB_SCROLL_PIXELS; + }.bind(this)); + tabContainer.appendChild(leftButton); + tabContainer.appendChild(this.tabBar_); + tabContainer.appendChild(rightButton); + // Add and remove buttons depending on scroll position. + var tabScrollHandler = function () { + if (this.tabBar_.scrollLeft > 0) { + leftButton.classList.add(this.CssClasses_.IS_ACTIVE); + } else { + leftButton.classList.remove(this.CssClasses_.IS_ACTIVE); + } + if (this.tabBar_.scrollLeft < this.tabBar_.scrollWidth - this.tabBar_.offsetWidth) { + rightButton.classList.add(this.CssClasses_.IS_ACTIVE); + } else { + rightButton.classList.remove(this.CssClasses_.IS_ACTIVE); + } + }.bind(this); + this.tabBar_.addEventListener('scroll', tabScrollHandler); + tabScrollHandler(); + if (this.tabBar_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) { + this.tabBar_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + } + // Select element tabs, document panels + var tabs = this.tabBar_.querySelectorAll('.' + this.CssClasses_.TAB); + var panels = this.content_.querySelectorAll('.' + this.CssClasses_.PANEL); + // Create new tabs for each tab element + for (var i = 0; i < tabs.length; i++) { + new MaterialLayoutTab(tabs[i], tabs, panels, this); + } + } + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); } - - this.element_.classList.add(this.CssClasses_.IS_UPGRADED); - } }; - function MaterialLayoutTab(tab, tabs, panels, layout) { - 'use strict'; - - if (tab) { - if (layout.tabBar_.classList.contains( - layout.CssClasses_.JS_RIPPLE_EFFECT)) { - var rippleContainer = document.createElement('span'); - rippleContainer.classList.add(layout.CssClasses_.RIPPLE_CONTAINER); - rippleContainer.classList.add(layout.CssClasses_.JS_RIPPLE_EFFECT); - var ripple = document.createElement('span'); - ripple.classList.add(layout.CssClasses_.RIPPLE); - rippleContainer.appendChild(ripple); - tab.appendChild(rippleContainer); + if (tab) { + if (layout.tabBar_.classList.contains(layout.CssClasses_.JS_RIPPLE_EFFECT)) { + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(layout.CssClasses_.RIPPLE_CONTAINER); + rippleContainer.classList.add(layout.CssClasses_.JS_RIPPLE_EFFECT); + var ripple = document.createElement('span'); + ripple.classList.add(layout.CssClasses_.RIPPLE); + rippleContainer.appendChild(ripple); + tab.appendChild(rippleContainer); + } + tab.addEventListener('click', function (e) { + e.preventDefault(); + var href = tab.href.split('#')[1]; + var panel = layout.content_.querySelector('#' + href); + layout.resetTabState_(tabs); + layout.resetPanelState_(panels); + tab.classList.add(layout.CssClasses_.IS_ACTIVE); + panel.classList.add(layout.CssClasses_.IS_ACTIVE); + }); } - - tab.addEventListener('click', function(e) { - e.preventDefault(); - var href = tab.href.split('#')[1]; - var panel = layout.content_.querySelector('#' + href); - layout.resetTabState_(tabs); - layout.resetPanelState_(panels); - tab.classList.add(layout.CssClasses_.IS_ACTIVE); - panel.classList.add(layout.CssClasses_.IS_ACTIVE); - }); - - } } - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialLayout, - classAsString: 'MaterialLayout', - cssClass: 'mdl-js-layout' + constructor: MaterialLayout, + classAsString: 'MaterialLayout', + cssClass: 'mdl-js-layout' }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -3595,144 +3195,141 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Data Table Card MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialDataTable(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - -/** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ -MaterialDataTable.prototype.Constant_ = { - // None at the moment. + * Class constructor for Data Table Card MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialDataTable = function MaterialDataTable(element) { + this.element_ = element; + // Initialize instance. + this.init(); }; - +window.MaterialDataTable = MaterialDataTable; /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ +MaterialDataTable.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialDataTable.prototype.CssClasses_ = { - DATA_TABLE: 'mdl-data-table', - SELECTABLE: 'mdl-data-table--selectable', - IS_SELECTED: 'is-selected', - IS_UPGRADED: 'is-upgraded' + DATA_TABLE: 'mdl-data-table', + SELECTABLE: 'mdl-data-table--selectable', + IS_SELECTED: 'is-selected', + IS_UPGRADED: 'is-upgraded' }; - -MaterialDataTable.prototype.selectRow_ = function(checkbox, row, rows) { - 'use strict'; - - if (row) { - return function() { - if (checkbox.checked) { - row.classList.add(this.CssClasses_.IS_SELECTED); - } else { - row.classList.remove(this.CssClasses_.IS_SELECTED); - } - }.bind(this); - } - - if (rows) { - return function() { - var i; - var el; - if (checkbox.checked) { - for (i = 0; i < rows.length; i++) { - el = rows[i].querySelector('td').querySelector('.mdl-checkbox'); - el.MaterialCheckbox.check(); - rows[i].classList.add(this.CssClasses_.IS_SELECTED); - } - } else { - for (i = 0; i < rows.length; i++) { - el = rows[i].querySelector('td').querySelector('.mdl-checkbox'); - el.MaterialCheckbox.uncheck(); - rows[i].classList.remove(this.CssClasses_.IS_SELECTED); - } - } - }.bind(this); - } +/** + * Generates and returns a function that toggles the selection state of a + * single row (or multiple rows). + * + * @param {HTMLElement} checkbox Checkbox that toggles the selection state. + * @param {HTMLElement} row Row to toggle when checkbox changes. + * @param {HTMLElement[]} rows Rows to toggle when checkbox changes. + * @private + */ +MaterialDataTable.prototype.selectRow_ = function (checkbox, row, rows) { + if (row) { + return function () { + if (checkbox.checked) { + row.classList.add(this.CssClasses_.IS_SELECTED); + } else { + row.classList.remove(this.CssClasses_.IS_SELECTED); + } + }.bind(this); + } + if (rows) { + return function () { + var i; + var el; + if (checkbox.checked) { + for (i = 0; i < rows.length; i++) { + el = rows[i].querySelector('td').querySelector('.mdl-checkbox'); + el.MaterialCheckbox.check(); + rows[i].classList.add(this.CssClasses_.IS_SELECTED); + } + } else { + for (i = 0; i < rows.length; i++) { + el = rows[i].querySelector('td').querySelector('.mdl-checkbox'); + el.MaterialCheckbox.uncheck(); + rows[i].classList.remove(this.CssClasses_.IS_SELECTED); + } + } + }.bind(this); + } }; - -MaterialDataTable.prototype.createCheckbox_ = function(row, rows) { - 'use strict'; - - var label = document.createElement('label'); - label.classList.add('mdl-checkbox'); - label.classList.add('mdl-js-checkbox'); - label.classList.add('mdl-js-ripple-effect'); - label.classList.add('mdl-data-table__select'); - var checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.classList.add('mdl-checkbox__input'); - if (row) { - checkbox.addEventListener('change', this.selectRow_(checkbox, row)); - } else if (rows) { - checkbox.addEventListener('change', this.selectRow_(checkbox, null, rows)); - } - label.appendChild(checkbox); - componentHandler.upgradeElement(label, 'MaterialCheckbox'); - return label; +/** + * Creates a checkbox for a single or or multiple rows and hooks up the + * event handling. + * + * @param {HTMLElement} row Row to toggle when checkbox changes. + * @param {HTMLElement[]} rows Rows to toggle when checkbox changes. + * @private + */ +MaterialDataTable.prototype.createCheckbox_ = function (row, rows) { + var label = document.createElement('label'); + label.classList.add('mdl-checkbox'); + label.classList.add('mdl-js-checkbox'); + label.classList.add('mdl-js-ripple-effect'); + label.classList.add('mdl-data-table__select'); + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.classList.add('mdl-checkbox__input'); + if (row) { + checkbox.addEventListener('change', this.selectRow_(checkbox, row)); + } else if (rows) { + checkbox.addEventListener('change', this.selectRow_(checkbox, null, rows)); + } + label.appendChild(checkbox); + componentHandler.upgradeElement(label, 'MaterialCheckbox'); + return label; }; - /** - * Initialize element. - */ -MaterialDataTable.prototype.init = function() { - 'use strict'; - - if (this.element_) { - - var firstHeader = this.element_.querySelector('th'); - var rows = this.element_.querySelector('tbody').querySelectorAll('tr'); - - if (this.element_.classList.contains(this.CssClasses_.SELECTABLE)) { - var th = document.createElement('th'); - var headerCheckbox = this.createCheckbox_(null, rows); - th.appendChild(headerCheckbox); - firstHeader.parentElement.insertBefore(th, firstHeader); - - for (var i = 0; i < rows.length; i++) { - var firstCell = rows[i].querySelector('td'); - if (firstCell) { - var td = document.createElement('td'); - var rowCheckbox = this.createCheckbox_(rows[i]); - td.appendChild(rowCheckbox); - rows[i].insertBefore(td, firstCell); + * Initialize element. + */ +MaterialDataTable.prototype.init = function () { + if (this.element_) { + var firstHeader = this.element_.querySelector('th'); + var rows = this.element_.querySelector('tbody').querySelectorAll('tr'); + if (this.element_.classList.contains(this.CssClasses_.SELECTABLE)) { + var th = document.createElement('th'); + var headerCheckbox = this.createCheckbox_(null, rows); + th.appendChild(headerCheckbox); + firstHeader.parentElement.insertBefore(th, firstHeader); + for (var i = 0; i < rows.length; i++) { + var firstCell = rows[i].querySelector('td'); + if (firstCell) { + var td = document.createElement('td'); + var rowCheckbox = this.createCheckbox_(rows[i]); + td.appendChild(rowCheckbox); + rows[i].insertBefore(td, firstCell); + } + } } - } + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); } - - this.element_.classList.add(this.CssClasses_.IS_UPGRADED); - } }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialDataTable, - classAsString: 'MaterialDataTable', - cssClass: 'mdl-js-data-table' + constructor: MaterialDataTable, + classAsString: 'MaterialDataTable', + cssClass: 'mdl-js-data-table' }); - /** * @license * Copyright 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -3745,233 +3342,205 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - /** - * Class constructor for Ripple MDL component. - * Implements MDL component design pattern defined at: - * https://github.com/jasonmayes/mdl-component-design-pattern - * @param {HTMLElement} element The element that will be upgraded. - */ -function MaterialRipple(element) { - 'use strict'; - - this.element_ = element; - - // Initialize instance. - this.init(); -} - + * Class constructor for Ripple MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialRipple = function MaterialRipple(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window.MaterialRipple = MaterialRipple; /** - * Store constants in one place so they can be updated easily. - * @enum {string | number} - * @private - */ + * Store constants in one place so they can be updated easily. + * + * @enum {String | Number} + * @private + */ MaterialRipple.prototype.Constant_ = { - INITIAL_SCALE: 'scale(0.0001, 0.0001)', - INITIAL_SIZE: '1px', - INITIAL_OPACITY: '0.4', - FINAL_OPACITY: '0', - FINAL_SCALE: '' + INITIAL_SCALE: 'scale(0.0001, 0.0001)', + INITIAL_SIZE: '1px', + INITIAL_OPACITY: '0.4', + FINAL_OPACITY: '0', + FINAL_SCALE: '' }; - /** - * Store strings for class names defined by this component that are used in - * JavaScript. This allows us to simply change it in one place should we - * decide to modify at a later date. - * @enum {string} - * @private - */ + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {String} + * @private + */ MaterialRipple.prototype.CssClasses_ = { - RIPPLE_CENTER: 'mdl-ripple--center', - RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', - RIPPLE: 'mdl-ripple', - IS_ANIMATING: 'is-animating', - IS_VISIBLE: 'is-visible' + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE: 'mdl-ripple', + IS_ANIMATING: 'is-animating', + IS_VISIBLE: 'is-visible' }; - /** - * Handle mouse / finger down on element. - * @param {Event} event The event that fired. - * @private - */ -MaterialRipple.prototype.downHandler_ = function(event) { - 'use strict'; - - if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) { - var rect = this.element_.getBoundingClientRect(); - this.boundHeight = rect.height; - this.boundWidth = rect.width; - this.rippleSize_ = Math.sqrt(rect.width * rect.width + - rect.height * rect.height) * 2 + 2; - this.rippleElement_.style.width = this.rippleSize_ + 'px'; - this.rippleElement_.style.height = this.rippleSize_ + 'px'; - } - - this.rippleElement_.classList.add(this.CssClasses_.IS_VISIBLE); - - if (event.type === 'mousedown' && this.ignoringMouseDown_) { - this.ignoringMouseDown_ = false; - } else { - if (event.type === 'touchstart') { - this.ignoringMouseDown_ = true; + * Handle mouse / finger down on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRipple.prototype.downHandler_ = function (event) { + if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) { + var rect = this.element_.getBoundingClientRect(); + this.boundHeight = rect.height; + this.boundWidth = rect.width; + this.rippleSize_ = Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2; + this.rippleElement_.style.width = this.rippleSize_ + 'px'; + this.rippleElement_.style.height = this.rippleSize_ + 'px'; } - var frameCount = this.getFrameCount(); - if (frameCount > 0) { - return; - } - this.setFrameCount(1); - var bound = event.currentTarget.getBoundingClientRect(); - var x; - var y; - // Check if we are handling a keyboard click. - if (event.clientX === 0 && event.clientY === 0) { - x = Math.round(bound.width / 2); - y = Math.round(bound.height / 2); + this.rippleElement_.classList.add(this.CssClasses_.IS_VISIBLE); + if (event.type === 'mousedown' && this.ignoringMouseDown_) { + this.ignoringMouseDown_ = false; } else { - var clientX = event.clientX ? event.clientX : event.touches[0].clientX; - var clientY = event.clientY ? event.clientY : event.touches[0].clientY; - x = Math.round(clientX - bound.left); - y = Math.round(clientY - bound.top); + if (event.type === 'touchstart') { + this.ignoringMouseDown_ = true; + } + var frameCount = this.getFrameCount(); + if (frameCount > 0) { + return; + } + this.setFrameCount(1); + var bound = event.currentTarget.getBoundingClientRect(); + var x; + var y; + // Check if we are handling a keyboard click. + if (event.clientX === 0 && event.clientY === 0) { + x = Math.round(bound.width / 2); + y = Math.round(bound.height / 2); + } else { + var clientX = event.clientX ? event.clientX : event.touches[0].clientX; + var clientY = event.clientY ? event.clientY : event.touches[0].clientY; + x = Math.round(clientX - bound.left); + y = Math.round(clientY - bound.top); + } + this.setRippleXY(x, y); + this.setRippleStyles(true); + window.requestAnimationFrame(this.animFrameHandler.bind(this)); } - this.setRippleXY(x, y); - this.setRippleStyles(true); - window.requestAnimationFrame(this.animFrameHandler.bind(this)); - } }; - /** - * Handle mouse / finger up on element. - * @param {Event} event The event that fired. - * @private - */ -MaterialRipple.prototype.upHandler_ = function(event) { - 'use strict'; - - // Don't fire for the artificial "mouseup" generated by a double-click. - if (event && event.detail !== 2) { - this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE); - } + * Handle mouse / finger up on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRipple.prototype.upHandler_ = function (event) { + // Don't fire for the artificial "mouseup" generated by a double-click. + if (event && event.detail !== 2) { + this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE); + } + // Allow a repaint to occur before removing this class, so the animation + // shows for tap events, which seem to trigger a mouseup too soon after + // mousedown. + window.setTimeout(function () { + this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE); + }.bind(this), 0); }; - /** - * Initialize element. - */ -MaterialRipple.prototype.init = function() { - 'use strict'; - - if (this.element_) { - var recentering = - this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER); - if (!this.element_.classList.contains( - this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)) { - this.rippleElement_ = this.element_.querySelector('.' + - this.CssClasses_.RIPPLE); - this.frameCount_ = 0; - this.rippleSize_ = 0; - this.x_ = 0; - this.y_ = 0; - - // Touch start produces a compat mouse down event, which would cause a - // second ripples. To avoid that, we use this property to ignore the first - // mouse down after a touch start. - this.ignoringMouseDown_ = false; - - this.boundDownHandler = this.downHandler_.bind(this); - this.element_.addEventListener('mousedown', - this.boundDownHandler); - this.element_.addEventListener('touchstart', - this.boundDownHandler); - - this.boundUpHandler = this.upHandler_.bind(this); - this.element_.addEventListener('mouseup', this.boundUpHandler); - this.element_.addEventListener('mouseleave', this.boundUpHandler); - this.element_.addEventListener('touchend', this.boundUpHandler); - this.element_.addEventListener('blur', this.boundUpHandler); - - this.getFrameCount = function() { - return this.frameCount_; - }; - - this.setFrameCount = function(fC) { - this.frameCount_ = fC; - }; - - this.getRippleElement = function() { - return this.rippleElement_; - }; - - this.setRippleXY = function(newX, newY) { - this.x_ = newX; - this.y_ = newY; - }; - - this.setRippleStyles = function(start) { - if (this.rippleElement_ !== null) { - var transformString; - var scale; - var size; - var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)'; - - if (start) { - scale = this.Constant_.INITIAL_SCALE; - size = this.Constant_.INITIAL_SIZE; - } else { - scale = this.Constant_.FINAL_SCALE; - size = this.rippleSize_ + 'px'; - if (recentering) { - offset = 'translate(' + this.boundWidth / 2 + 'px, ' + - this.boundHeight / 2 + 'px)'; - } - } - - transformString = 'translate(-50%, -50%) ' + offset + scale; - - this.rippleElement_.style.webkitTransform = transformString; - this.rippleElement_.style.msTransform = transformString; - this.rippleElement_.style.transform = transformString; - - if (start) { - this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING); - } else { - this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING); - } + * Initialize element. + */ +MaterialRipple.prototype.init = function () { + if (this.element_) { + var recentering = this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER); + if (!this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)) { + this.rippleElement_ = this.element_.querySelector('.' + this.CssClasses_.RIPPLE); + this.frameCount_ = 0; + this.rippleSize_ = 0; + this.x_ = 0; + this.y_ = 0; + // Touch start produces a compat mouse down event, which would cause a + // second ripples. To avoid that, we use this property to ignore the first + // mouse down after a touch start. + this.ignoringMouseDown_ = false; + this.boundDownHandler = this.downHandler_.bind(this); + this.element_.addEventListener('mousedown', this.boundDownHandler); + this.element_.addEventListener('touchstart', this.boundDownHandler); + this.boundUpHandler = this.upHandler_.bind(this); + this.element_.addEventListener('mouseup', this.boundUpHandler); + this.element_.addEventListener('mouseleave', this.boundUpHandler); + this.element_.addEventListener('touchend', this.boundUpHandler); + this.element_.addEventListener('blur', this.boundUpHandler); + this.getFrameCount = function () { + return this.frameCount_; + }; + this.setFrameCount = function (fC) { + this.frameCount_ = fC; + }; + this.getRippleElement = function () { + return this.rippleElement_; + }; + this.setRippleXY = function (newX, newY) { + this.x_ = newX; + this.y_ = newY; + }; + this.setRippleStyles = function (start) { + if (this.rippleElement_ !== null) { + var transformString; + var scale; + var size; + var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)'; + if (start) { + scale = this.Constant_.INITIAL_SCALE; + size = this.Constant_.INITIAL_SIZE; + } else { + scale = this.Constant_.FINAL_SCALE; + size = this.rippleSize_ + 'px'; + if (recentering) { + offset = 'translate(' + this.boundWidth / 2 + 'px, ' + this.boundHeight / 2 + 'px)'; + } + } + transformString = 'translate(-50%, -50%) ' + offset + scale; + this.rippleElement_.style.webkitTransform = transformString; + this.rippleElement_.style.msTransform = transformString; + this.rippleElement_.style.transform = transformString; + if (start) { + this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING); + } else { + this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING); + } + } + }; + this.animFrameHandler = function () { + if (this.frameCount_-- > 0) { + window.requestAnimationFrame(this.animFrameHandler.bind(this)); + } else { + this.setRippleStyles(false); + } + }; } - }; - - this.animFrameHandler = function() { - if (this.frameCount_-- > 0) { - window.requestAnimationFrame(this.animFrameHandler.bind(this)); - } else { - this.setRippleStyles(false); - } - }; } - } }; - -/* -* Downgrade the component -*/ -MaterialRipple.prototype.mdlDowngrade_ = function() { - 'use strict'; - this.element_.removeEventListener('mousedown', - this.boundDownHandler); - this.element_.removeEventListener('touchstart', - this.boundDownHandler); - - this.element_.removeEventListener('mouseup', this.boundUpHandler); - this.element_.removeEventListener('mouseleave', this.boundUpHandler); - this.element_.removeEventListener('touchend', this.boundUpHandler); - this.element_.removeEventListener('blur', this.boundUpHandler); +/** + * Downgrade the component + * + * @private + */ +MaterialRipple.prototype.mdlDowngrade_ = function () { + this.element_.removeEventListener('mousedown', this.boundDownHandler); + this.element_.removeEventListener('touchstart', this.boundDownHandler); + this.element_.removeEventListener('mouseup', this.boundUpHandler); + this.element_.removeEventListener('mouseleave', this.boundUpHandler); + this.element_.removeEventListener('touchend', this.boundUpHandler); + this.element_.removeEventListener('blur', this.boundUpHandler); }; - // The component registers itself. It can assume componentHandler is available // in the global scope. componentHandler.register({ - constructor: MaterialRipple, - classAsString: 'MaterialRipple', - cssClass: 'mdl-js-ripple-effect', - widget: false + constructor: MaterialRipple, + classAsString: 'MaterialRipple', + cssClass: 'mdl-js-ripple-effect', + widget: false }); +}());