Project import generated by Copybara.
GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/node_modules/material-design-lite/src/mdlComponentHandler.js b/node_modules/material-design-lite/src/mdlComponentHandler.js
new file mode 100644
index 0000000..f532a98
--- /dev/null
+++ b/node_modules/material-design-lite/src/mdlComponentHandler.js
@@ -0,0 +1,503 @@
+/**
+ * @license
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * 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.
+ */
+
+/**
+ * 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 */
+
+// Pre-defining the componentHandler interface, for closure documentation and
+// static verification.
+var componentHandler = {
+ /**
+ * 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
+ * need to create a new instance of.
+ * @param {string=} optCssClass the name of the CSS class elements of this
+ * type will have.
+ */
+ upgradeDom: function(optJsClass, optCssClass) {},
+ /**
+ * Upgrades a specific element rather than all in the DOM.
+ *
+ * @param {!Element} element The element we wish to upgrade.
+ * @param {string=} optJsClass Optional name of the class we want to upgrade
+ * the element to.
+ */
+ upgradeElement: function(element, optJsClass) {},
+ /**
+ * Upgrades a specific list of elements rather than all in the DOM.
+ *
+ * @param {!Element|!Array<!Element>|!NodeList|!HTMLCollection} elements
+ * The elements we wish to upgrade.
+ */
+ upgradeElements: function(elements) {},
+ /**
+ * Upgrades all registered components found in the current DOM. This is
+ * automatically called on window load.
+ */
+ upgradeAllRegistered: function() {},
+ /**
+ * 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
+ * to hook into for any upgrades performed.
+ * @param {function(!HTMLElement)} callback The function to call upon an
+ * upgrade. This function should expect 1 parameter - the HTMLElement which
+ * got upgraded.
+ */
+ registerUpgradedCallback: function(jsClass, callback) {},
+ /**
+ * Registers a class for future use and attempts to upgrade existing DOM.
+ *
+ * @param {componentHandler.ComponentConfigPublic} config the registration configuration
+ */
+ register: function(config) {},
+ /**
+ * Downgrade either a given node, an array of nodes, or a NodeList.
+ *
+ * @param {!Node|!Array<!Node>|!NodeList} nodes
+ */
+ downgradeElements: function(nodes) {}
+};
+
+componentHandler = (function() {
+ 'use strict';
+
+ /** @type {!Array<componentHandler.ComponentConfig>} */
+ var registeredComponents_ = [];
+
+ /** @type {!Array<componentHandler.Component>} */
+ var createdComponents_ = [];
+
+ 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 {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) {
+ if (typeof optReplace !== 'undefined') {
+ registeredComponents_[i] = optReplace;
+ }
+ return registeredComponents_[i];
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an array of the classNames of the upgraded classes on the element.
+ *
+ * @param {!Element} 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.
+ return dataUpgraded === null ? [''] : dataUpgraded.split(',');
+ }
+
+ /**
+ * Returns true if the given element has already been upgraded for the given
+ * class.
+ *
+ * @param {!Element} 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;
+ }
+
+ /**
+ * Create an event object.
+ *
+ * @param {string} eventType The type name of the event.
+ * @param {boolean} bubbles Whether the event should bubble up the DOM.
+ * @param {boolean} cancelable Whether the event can be canceled.
+ * @returns {!Event}
+ */
+ function createEvent_(eventType, bubbles, cancelable) {
+ if ('CustomEvent' in window && typeof window.CustomEvent === 'function') {
+ return new CustomEvent(eventType, {
+ bubbles: bubbles,
+ cancelable: cancelable
+ });
+ } else {
+ var ev = document.createEvent('Events');
+ ev.initEvent(eventType, bubbles, cancelable);
+ return ev;
+ }
+ }
+
+ /**
+ * 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
+ * need to create a new instance of.
+ * @param {string=} optCssClass the name of the CSS class elements of this
+ * type will have.
+ */
+ function upgradeDomInternal(optJsClass, optCssClass) {
+ if (typeof optJsClass === 'undefined' &&
+ typeof optCssClass === 'undefined') {
+ for (var i = 0; i < registeredComponents_.length; i++) {
+ upgradeDomInternal(registeredComponents_[i].className,
+ registeredComponents_[i].cssClass);
+ }
+ } else {
+ var jsClass = /** @type {string} */ (optJsClass);
+ if (typeof optCssClass === 'undefined') {
+ var registeredClass = findRegisteredClass_(jsClass);
+ if (registeredClass) {
+ optCssClass = registeredClass.cssClass;
+ }
+ }
+
+ var elements = document.querySelectorAll('.' + optCssClass);
+ for (var n = 0; n < elements.length; n++) {
+ upgradeElementInternal(elements[n], jsClass);
+ }
+ }
+ }
+
+ /**
+ * Upgrades a specific element rather than all in the DOM.
+ *
+ * @param {!Element} 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)) {
+ throw new Error('Invalid argument provided to upgrade MDL element.');
+ }
+ // Allow upgrade to be canceled by canceling emitted event.
+ var upgradingEv = createEvent_('mdl-componentupgrading', true, true);
+ element.dispatchEvent(upgradingEv);
+ if (upgradingEv.defaultPrevented) {
+ return;
+ }
+
+ var upgradedList = getUpgradedListOfElement_(element);
+ 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) {
+ // Match CSS & Not to be upgraded & Not upgraded.
+ if (classList.contains(component.cssClass) &&
+ classesToUpgrade.indexOf(component) === -1 &&
+ !isElementUpgraded_(element, component.className)) {
+ classesToUpgrade.push(component);
+ }
+ });
+ } else if (!isElementUpgraded_(element, optJsClass)) {
+ classesToUpgrade.push(findRegisteredClass_(optJsClass));
+ }
+
+ // Upgrade the element for each classes.
+ for (var i = 0, n = classesToUpgrade.length, registeredClass; i < n; i++) {
+ registeredClass = classesToUpgrade[i];
+ if (registeredClass) {
+ // Mark element as upgraded.
+ upgradedList.push(registeredClass.className);
+ element.setAttribute('data-upgraded', upgradedList.join(','));
+ var instance = new registeredClass.classConstructor(element);
+ instance[componentConfigProperty_] = registeredClass;
+ createdComponents_.push(instance);
+ // Call any callbacks the user has registered with this component type.
+ for (var j = 0, m = registeredClass.callbacks.length; j < m; j++) {
+ registeredClass.callbacks[j](element);
+ }
+
+ if (registeredClass.widget) {
+ // Assign per element instance for control over API
+ element[registeredClass.className] = instance;
+ }
+ } else {
+ throw new Error(
+ 'Unable to find a registered component for the given class.');
+ }
+
+ var upgradedEv = createEvent_('mdl-componentupgraded', true, false);
+ element.dispatchEvent(upgradedEv);
+ }
+ }
+
+ /**
+ * Upgrades a specific list of elements rather than all in the DOM.
+ *
+ * @param {!Element|!Array<!Element>|!NodeList|!HTMLCollection} elements
+ * The elements we wish to upgrade.
+ */
+ function upgradeElementsInternal(elements) {
+ if (!Array.isArray(elements)) {
+ if (elements instanceof Element) {
+ elements = [elements];
+ } else {
+ elements = Array.prototype.slice.call(elements);
+ }
+ }
+ for (var i = 0, n = elements.length, element; i < n; i++) {
+ element = elements[i];
+ if (element instanceof HTMLElement) {
+ upgradeElementInternal(element);
+ if (element.children.length > 0) {
+ upgradeElementsInternal(element.children);
+ }
+ }
+ }
+ }
+
+ /**
+ * Registers a class for future use and attempts to upgrade existing DOM.
+ *
+ * @param {componentHandler.ComponentConfigPublic} config
+ */
+ function registerInternal(config) {
+ // In order to support both Closure-compiled and uncompiled code accessing
+ // this method, we need to allow for both the dot and array syntax for
+ // property access. You'll therefore see the `foo.bar || foo['bar']`
+ // pattern repeated across this method.
+ var widgetMissing = (typeof config.widget === 'undefined' &&
+ typeof config['widget'] === 'undefined');
+ var widget = true;
+
+ if (!widgetMissing) {
+ widget = config.widget || config['widget'];
+ }
+
+ var newConfig = /** @type {componentHandler.ComponentConfig} */ ({
+ classConstructor: config.constructor || config['constructor'],
+ className: config.classAsString || config['classAsString'],
+ cssClass: config.cssClass || config['cssClass'],
+ widget: widget,
+ callbacks: []
+ });
+
+ registeredComponents_.forEach(function(item) {
+ if (item.cssClass === newConfig.cssClass) {
+ throw new Error('The provided cssClass has already been registered: ' + item.cssClass);
+ }
+ if (item.className === newConfig.className) {
+ throw new Error('The provided className has already been registered');
+ }
+ });
+
+ if (config.constructor.prototype
+ .hasOwnProperty(componentConfigProperty_)) {
+ throw new Error(
+ 'MDL component classes must not have ' + componentConfigProperty_ +
+ ' defined as a property.');
+ }
+
+ var found = findRegisteredClass_(config.classAsString, newConfig);
+
+ if (!found) {
+ registeredComponents_.push(newConfig);
+ }
+ }
+
+ /**
+ * 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
+ * to hook into for any upgrades performed.
+ * @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);
+ }
+ }
+
+ /**
+ * Upgrades all registered components found in the current DOM. This is
+ * automatically called on window load.
+ */
+ function upgradeAllRegisteredInternal() {
+ for (var n = 0; n < registeredComponents_.length; n++) {
+ upgradeDomInternal(registeredComponents_[n].className);
+ }
+ }
+
+ /**
+ * Check the component for the downgrade method.
+ * Execute if found.
+ * Remove component from createdComponents list.
+ *
+ * @param {?componentHandler.Component} component
+ */
+ function deconstructComponentInternal(component) {
+ if (component) {
+ var componentIndex = createdComponents_.indexOf(component);
+ createdComponents_.splice(componentIndex, 1);
+
+ var upgrades = component.element_.getAttribute('data-upgraded').split(',');
+ var componentPlace = upgrades.indexOf(component[componentConfigProperty_].classAsString);
+ upgrades.splice(componentPlace, 1);
+ component.element_.setAttribute('data-upgraded', upgrades.join(','));
+
+ var ev = createEvent_('mdl-componentdowngraded', true, false);
+ component.element_.dispatchEvent(ev);
+ }
+ }
+
+ /**
+ * Downgrade either a given node, an array of nodes, or a NodeList.
+ *
+ * @param {!Node|!Array<!Node>|!NodeList} nodes
+ */
+ function downgradeNodesInternal(nodes) {
+ /**
+ * Auxiliary function to downgrade a single node.
+ * @param {!Node} node the node to be downgraded
+ */
+ var downgradeNode = function(node) {
+ createdComponents_.filter(function(item) {
+ return item.element_ === node;
+ }).forEach(deconstructComponentInternal);
+ };
+ if (nodes instanceof Array || nodes instanceof NodeList) {
+ for (var n = 0; n < nodes.length; n++) {
+ downgradeNode(nodes[n]);
+ }
+ } else if (nodes instanceof Node) {
+ downgradeNode(nodes);
+ } else {
+ throw new Error('Invalid argument provided to downgrade MDL nodes.');
+ }
+ }
+
+ // Now return the functions that should be made public with their publicly
+ // facing names...
+ return {
+ upgradeDom: upgradeDomInternal,
+ upgradeElement: upgradeElementInternal,
+ upgradeElements: upgradeElementsInternal,
+ upgradeAllRegistered: upgradeAllRegisteredInternal,
+ registerUpgradedCallback: registerUpgradedCallbackInternal,
+ register: registerInternal,
+ downgradeElements: downgradeNodesInternal
+ };
+})();
+
+/**
+ * Describes the type of a registered component type managed by
+ * componentHandler. Provided for benefit of the Closure compiler.
+ *
+ * @typedef {{
+ * constructor: Function,
+ * classAsString: string,
+ * cssClass: string,
+ * widget: (string|boolean|undefined)
+ * }}
+ */
+componentHandler.ComponentConfigPublic; // jshint ignore:line
+
+/**
+ * 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|boolean),
+ * 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
+
+// Export all symbols, for the benefit of Closure compiler.
+// No effect on uncompiled code.
+componentHandler['upgradeDom'] = componentHandler.upgradeDom;
+componentHandler['upgradeElement'] = componentHandler.upgradeElement;
+componentHandler['upgradeElements'] = componentHandler.upgradeElements;
+componentHandler['upgradeAllRegistered'] =
+ componentHandler.upgradeAllRegistered;
+componentHandler['registerUpgradedCallback'] =
+ componentHandler.registerUpgradedCallback;
+componentHandler['register'] = componentHandler.register;
+componentHandler['downgradeElements'] = componentHandler.downgradeElements;
+window.componentHandler = componentHandler;
+window['componentHandler'] = componentHandler;
+
+window.addEventListener('load', function() {
+ 'use strict';
+
+ /**
+ * Performs a "Cutting the mustard" test. If the browser supports the features
+ * tested, adds a mdl-js class to the <html> element. It then upgrades all MDL
+ * components requiring JavaScript.
+ */
+ if ('classList' in document.createElement('div') &&
+ 'querySelector' in document &&
+ 'addEventListener' in window && Array.prototype.forEach) {
+ document.documentElement.classList.add('mdl-js');
+ componentHandler.upgradeAllRegistered();
+ } else {
+ /**
+ * Dummy function to avoid JS errors.
+ */
+ componentHandler.upgradeElement = function() {};
+ /**
+ * Dummy function to avoid JS errors.
+ */
+ componentHandler.register = function() {};
+ }
+});