Project import generated by Copybara.

GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/node_modules/mdl-ext/src/formatfield/formatfield.js b/node_modules/mdl-ext/src/formatfield/formatfield.js
new file mode 100644
index 0000000..0b84819
--- /dev/null
+++ b/node_modules/mdl-ext/src/formatfield/formatfield.js
@@ -0,0 +1,280 @@
+/**
+ * @license
+ * Copyright 2016-2017 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+
+import {jsonStringToObject} from '../utils/json-utils';
+import {
+  IS_UPGRADED,
+} from '../utils/constants';
+
+const JS_FORMAT_FIELD = 'mdlext-js-formatfield';
+const FORMAT_FIELD_COMPONENT = 'MaterialExtFormatfield';
+
+/**
+ * Detect browser locale
+ * @returns {string} the locale
+ * @see http://stackoverflow.com/questions/1043339/javascript-for-detecting-browser-language-preference
+ */
+const browserLanguage = () => {
+  return navigator.languages
+    ? navigator.languages[0]
+    : navigator.language || navigator.userLanguage;
+};
+
+/**
+ * The formatfield  formats an input field  using language sensitive number formatting.
+ */
+
+class FormatField {
+  static timer = null;
+
+  element_;
+  input_;
+  options_ = {};
+  intlGroupSeparator_;
+  intlDecimalSeparator_;
+
+  constructor(element) {
+    this.element_ = element;
+    this.init();
+  }
+
+  clickHandler = () => {
+    clearTimeout(FormatField.timer);
+  };
+
+  focusInHandler = () => {
+    if(!(this.input.readOnly || this.input.disabled)) {
+      this.input.value = this.unformatInput();
+      //setTimeout(() => this.input.setSelectionRange(0, this.input.value.length), 20);
+      FormatField.timer = setTimeout(() => this.input.select(), 200);
+    }
+  };
+
+  focusOutHandler = () => {
+    clearTimeout(FormatField.timer);
+
+    if(!(this.input.readOnly || this.input.disabled)) {
+      this.formatValue();
+    }
+  };
+
+  get element() {
+    return this.element_;
+  }
+
+  get input() {
+    return this.input_;
+  }
+
+  get options() {
+    return this.options_;
+  }
+
+  stripSeparatorsFromValue() {
+    const doReplace = () => this.input.value
+      .replace(/\s/g, '')
+      .replace(new RegExp(this.options.groupSeparator, 'g'), '')
+      .replace(this.options.decimalSeparator, '.');
+      //.replace(this.intlGroupSeparator_, ''),
+      //.replace(this.intlDecimalSeparator_, '.');
+
+    return this.input.value ? doReplace() : this.input.value;
+  }
+
+  fixSeparators(value) {
+    const doReplace = () => value
+      .replace(new RegExp(this.intlGroupSeparator_, 'g'), this.options.groupSeparator)
+      .replace(this.intlDecimalSeparator_, this.options.decimalSeparator);
+
+    return value ? doReplace() : value;
+  }
+
+  formatValue() {
+    if(this.input.value) {
+      const v = new Intl.NumberFormat(this.options.locales, this.options)
+        .format(this.stripSeparatorsFromValue());
+
+      if('NaN' !== v) {
+        this.input.value = this.fixSeparators(v);
+      }
+    }
+  }
+
+  unformat() {
+    const doReplace = () => this.input.value
+      .replace(/\s/g, '')
+      .replace(new RegExp(this.options.groupSeparator, 'g'), '')
+      .replace(this.options.decimalSeparator, '.');
+
+    return this.input.value ? doReplace() : this.input.value;
+  }
+
+  unformatInput() {
+    const doReplace = () => this.input.value
+      .replace(/\s/g, '')
+      .replace(new RegExp(this.options.groupSeparator, 'g'), '');
+
+    return this.input.value ? doReplace() : this.input.value;
+  }
+
+  removeListeners() {
+    this.input.removeEventListener('click', this.clickHandler);
+    this.input.removeEventListener('focusin', this.focusInHandler);
+    this.input.removeEventListener('focusout', this.focusOutHandler);
+  }
+
+  init() {
+    const addListeners = () => {
+      this.input.addEventListener('click', this.clickHandler);
+      this.input.addEventListener('focusin', this.focusInHandler);
+      this.input.addEventListener('focusout', this.focusOutHandler);
+    };
+
+    const addOptions = () => {
+      const opts = this.element.getAttribute('data-formatfield-options') ||
+        this.input.getAttribute('data-formatfield-options');
+      if(opts) {
+        this.options_ = jsonStringToObject(opts, this.options);
+      }
+    };
+
+    const addLocale = () => {
+      if(!this.options.locales) {
+        this.options.locales = browserLanguage() || 'en-US'; //'nb-NO', //'en-US',
+      }
+    };
+
+    const addGrouping = () => {
+      const s = (1234.5).toLocaleString(this.options.locales, {
+        style: 'decimal',
+        useGrouping: true,
+        minimumFractionDigits: 1,
+        maximumFractionDigits: 1
+      });
+
+      this.intlGroupSeparator_ = s.charAt(1);
+      this.intlDecimalSeparator_ = s.charAt(s.length-2);
+      this.options.groupSeparator = this.options.groupSeparator || this.intlGroupSeparator_;
+      this.options.decimalSeparator = this.options.decimalSeparator || this.intlDecimalSeparator_;
+
+      if(this.options.groupSeparator === this.options.decimalSeparator) {
+        const e = `Error! options.groupSeparator, "${this.options.groupSeparator}" ` +
+          'and options.decimalSeparator, ' +
+          `"${this.options.decimalSeparator}" should not be equal`;
+        throw new Error(e);
+      }
+    };
+
+    this.input_ = this.element.querySelector('input') || this.element;
+
+    addOptions();
+    addLocale();
+    addGrouping();
+    this.formatValue();
+    addListeners();
+  }
+
+  downgrade() {
+    this.removeListeners();
+  }
+
+}
+
+(function() {
+  'use strict';
+
+  /**
+   * @constructor
+   * @param {HTMLElement} element The element that will be upgraded.
+   */
+  const MaterialExtFormatfield = function MaterialExtFormatfield(element) {
+    this.element_ = element;
+    this.formatField_ = null;
+
+    // Initialize instance.
+    this.init();
+  };
+  window['MaterialExtFormatfield'] = MaterialExtFormatfield;
+
+  /**
+   * Initialize component
+   */
+  MaterialExtFormatfield.prototype.init = function() {
+    if (this.element_) {
+      this.element_.classList.add(IS_UPGRADED);
+      this.formatField_ = new FormatField(this.element_);
+
+      // Listen to 'mdl-componentdowngraded' event
+      this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
+    }
+  };
+
+  /**
+   * Get options object
+   *
+   * @public
+   *
+   * @returns {Object} the options object
+   */
+  MaterialExtFormatfield.prototype.getOptions = function() {
+    return this.formatField_.options;
+  };
+  MaterialExtFormatfield.prototype['getOptions'] = MaterialExtFormatfield.prototype.getOptions;
+
+
+  /**
+   * A unformatted value is a string value where the locale specific decimal separator
+   * is replaced with a '.' separator and group separators are stripped.
+   * The returned value is suitable for parsing to a JavaScript numerical value.
+   *
+   * @example
+   * input.value = '1 234,5';
+   * inputElement.MaterialExtFormatfield.getUnformattedValue();
+   * // Returns '1234.5'
+   *
+   * @public
+   *
+   * @returns {String} the unformatted value
+   */
+  MaterialExtFormatfield.prototype.getUnformattedValue = function() {
+    return this.formatField_.unformat();
+  };
+  MaterialExtFormatfield.prototype['getUnformattedValue'] = MaterialExtFormatfield.prototype.getUnformattedValue;
+
+  /*
+   * Downgrade component
+   * E.g remove listeners and clean up resources
+   */
+  MaterialExtFormatfield.prototype.mdlDowngrade_ = function() {
+    this.formatField_.downgrade();
+  };
+
+  // The component registers itself. It can assume componentHandler is available
+  // in the global scope.
+  /* eslint no-undef: 0 */
+  componentHandler.register({
+    constructor: MaterialExtFormatfield,
+    classAsString: FORMAT_FIELD_COMPONENT,
+    cssClass: JS_FORMAT_FIELD,
+    widget: true
+  });
+
+})();
diff --git a/node_modules/mdl-ext/src/formatfield/readme.md b/node_modules/mdl-ext/src/formatfield/readme.md
new file mode 100644
index 0000000..c3737eb
--- /dev/null
+++ b/node_modules/mdl-ext/src/formatfield/readme.md
@@ -0,0 +1,103 @@
+#Formatfield
+![Formatfield](../../etc/formatfield.png)
+
+The formatfield component formats an input field using language sensitive 
+**number formatting**. It acts as a "pluggable" component and can be added to a 
+`mdl-textfield` component or to a `<input>` element.
+
+## To include a MDLEXT formatfield component:
+&nbsp;1. Code a [single-line `mdl-textfield`](https://getmdl.io/components/index.html#textfields-section) 
+component.
+```html
+<div class="mdl-textfield mdl-js-textfield">
+  <input class="mdl-textfield__input" type="text" 
+    pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+  <label class="mdl-textfield__label">Number...</label>
+  <span class="mdl-textfield__error">Input is not a number!</span>
+</div>
+```
+
+&nbsp;2. Add the `mdlext-js-formatfield` class to define the element as a formatfield component.
+```html
+<div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+  <input class="mdl-textfield__input" type="text" 
+    pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+  <label class="mdl-textfield__label">Number...</label>
+  <span class="mdl-textfield__error">Input is not a number!</span>
+</div>
+```
+
+&nbsp;3. Optionally add a `data-formatfield-options` attribute with the given 
+[locale](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation). 
+If this step is omitted, the formatfield component uses the browser language as it's locale.
+```html
+<div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield"
+  data-formatfield-options="{'locales': 'nb-NO'}">
+  <input class="mdl-textfield__input" type="text" 
+    pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+  <label class="mdl-textfield__label">Number...</label>
+  <span class="mdl-textfield__error">Input is not a number!</span>
+</div>
+```
+
+### Examples
+* The [snippets/formatfield.html](./snippets/formatfield.html) and the 
+[tests](../../test/formatfield/formatfield.spec.js) provides more detailed examples.
+* Try out the [live demo](http://leifoolsen.github.io/mdl-ext/demo/formatfield.html)
+
+## Public methods
+
+### getOptions()
+Get component configuration options object.
+```
+var options = inputElement.MaterialExtFormatfield.getOptions();
+console.log('locales', options.locales);
+```
+
+### getUnformattedValue()
+An unformatted value is a string value where the locale specific decimal separator
+is replaced with a '.' separator and group separators are stripped.
+The returned value is suitable for parsing to a JavaScript numerical value.
+
+Example
+```javascript
+input.value = '1 234,5';
+inputElement.MaterialExtFormatfield.getUnformattedValue();
+// Returns '1234.5'
+```
+
+## Configuration options
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements 
+to the formatfield. 
+
+### Available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+|`mdlext-js-formatfield`| Assigns basic MDL behavior to formatfield. | Required. |
+
+
+### Options
+The component can be configured using the `data-formatfield-options` attribute. 
+The attribute value is a JSON string with properties defined by the 
+[Intl.NumberFormat object](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat).
+
+The `data-formatfield-options` attribute must be a valid JSON string. 
+You can use single or double quotes for the JSON properties.
+
+Example 1, single quotes in JSON options string:
+```html
+<input class=" mdlext-js-formatfield" type="text"
+  data-formatfield-options="{'locales': 'nb-NO', 'minimumFractionDigits': 0, 'maximumFractionDigits': 0}">
+```
+
+Example 2, double quotes in JSON options string:
+```html
+<input class=" mdlext-js-formatfield" type="text"
+  data-formatfield-options='{"locales": "nb-NO", "minimumFractionDigits": 0, "maximumFractionDigits": 0}'>
+```
+
+## How to use the component programmatically
+The [tests](../../test/formatfield/formatfield.spec.js) and the 
+[snippets/formatfield.html](./snippets/formatfield.html) 
+provides examples on how to use the component programmatically.
diff --git a/node_modules/mdl-ext/src/formatfield/snippets/formatfield.html b/node_modules/mdl-ext/src/formatfield/snippets/formatfield.html
new file mode 100644
index 0000000..177a367
--- /dev/null
+++ b/node_modules/mdl-ext/src/formatfield/snippets/formatfield.html
@@ -0,0 +1,114 @@
+<p>The formatfield component formats an input field using
+  language sensitive number formatting. It acts as a "pluggable"
+  component. It can be added to a <code>mdl-textfield</code> component or to
+  a <code>&lt;input&gt</code> element.
+</p>
+
+<style>
+  .mdl-data-table .mdl-textfield {
+    width: auto;
+  }
+</style>
+<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp" style="margin-top: 16px;">
+<thead>
+<tr>
+  <th class="mdl-data-table__cell--non-numeric">Language</th>
+  <th class="mdl-data-table__cell--non-numeric">Input</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+  <td class="mdl-data-table__cell--non-numeric" id="browser-lang">Browser language</td>
+  <td class="mdl-data-table__cell--non-numeric">
+    <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield" id="sample2-component">
+      <input class="mdl-textfield__input" type="text" pattern="-?[0-9, ]*([\.,][0-9]+)?"
+             id="sample2-input" value="1234.5">
+      <label class="mdl-textfield__label" for="sample2-input">Number...</label>
+      <span class="mdl-textfield__error">Input is not a number!</span>
+    </div>
+    <div id="sample2-unformatted"></div>
+  </td>
+</tr>
+<tr>
+  <td class="mdl-data-table__cell--non-numeric">nb-NO</td>
+  <td class="mdl-data-table__cell--non-numeric">
+    <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield"
+      data-formatfield-options="{'locales': 'nb-NO'}">
+
+      <input class="mdl-textfield__input" type="text" pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+      <label class="mdl-textfield__label">Number...</label>
+      <span class="mdl-textfield__error">Input is not a number!</span>
+    </div>
+  </td>
+</tr>
+<tr>
+  <td class="mdl-data-table__cell--non-numeric">en-GB</td>
+  <td class="mdl-data-table__cell--non-numeric">
+    <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield" data-formatfield-options="{'locales': 'en-GB'}">
+      <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" value="1234.5">
+      <label class="mdl-textfield__label">Number...</label>
+      <span class="mdl-textfield__error">Input is not a number!</span>
+    </div>
+  </td>
+</tr>
+<tr>
+  <td class="mdl-data-table__cell--non-numeric">nb-NO, integer</td>
+  <td class="mdl-data-table__cell--non-numeric">
+    <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+      <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?"
+        data-formatfield-options="{'locales': 'nb-NO', 'minimumFractionDigits': 0,'maximumFractionDigits': 0}" value="1234.5">
+
+      <label class="mdl-textfield__label">Number...</label>
+      <span class="mdl-textfield__error">Input is not a number!</span>
+    </div>
+  </td>
+</tr>
+<tr>
+  <td class="mdl-data-table__cell--non-numeric">Percent. Input not supported</td>
+  <td class="mdl-data-table__cell--non-numeric">
+    <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+      <input class="mdl-textfield__input" type="text" readonly
+        data-formatfield-options="{'locales': 'en-GB', 'style': 'percent'}" value="0.20">
+      <label class="mdl-textfield__label">Number...</label>
+    </div>
+  </td>
+</tr>
+<tr>
+  <td class="mdl-data-table__cell--non-numeric">Currency. Input not supported</td>
+  <td class="mdl-data-table__cell--non-numeric">
+    <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+      <input class="mdl-textfield__input" type="text" readonly
+        data-formatfield-options="{'locales': 'nb-NO', 'style': 'currency', 'currency': 'NOK'}" value="1234.5">
+      <label class="mdl-textfield__label">Number...</label>
+    </div>
+  </td>
+</tr>
+<tr>
+  <td class="mdl-data-table__cell--non-numeric">Input</td>
+  <td class="mdl-data-table__cell--non-numeric">
+    <input class=" mdlext-js-formatfield" type="text"
+      data-formatfield-options="{'locales': 'nb-NO'}" value="1234.5">
+  </td>
+</tr>
+</tbody>
+</table>
+
+<script>
+  (function() {
+    'use strict';
+    window.addEventListener('load', function() {
+      var lang = navigator.languages
+        ? navigator.languages[0]
+        : navigator.language || navigator.userLanguage;
+
+      document.querySelector('#browser-lang').innerText = 'Browser language (' + lang + ')';
+
+      var formatfieldComponent = document.querySelector('#sample2-component');
+      formatfieldComponent.querySelector('input').addEventListener('blur', function () {
+        var unformatted = document.querySelector('#sample2-unformatted');
+        unformatted.innerText = 'Unformatted: ' + formatfieldComponent.MaterialExtFormatfield.getUnformattedValue();
+      });
+    });
+  }());
+</script>
+