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