aboutsummaryrefslogtreecommitdiff
path: root/catapult/third_party/polymer/components/paper-input
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/third_party/polymer/components/paper-input')
-rw-r--r--catapult/third_party/polymer/components/paper-input/.bower.json60
-rw-r--r--catapult/third_party/polymer/components/paper-input/.github/ISSUE_TEMPLATE.md33
-rw-r--r--catapult/third_party/polymer/components/paper-input/.gitignore1
-rw-r--r--catapult/third_party/polymer/components/paper-input/.travis.yml24
-rw-r--r--catapult/third_party/polymer/components/paper-input/CONTRIBUTING.md77
-rw-r--r--catapult/third_party/polymer/components/paper-input/README.md38
-rw-r--r--catapult/third_party/polymer/components/paper-input/all-imports.html12
-rw-r--r--catapult/third_party/polymer/components/paper-input/bower.json51
-rw-r--r--catapult/third_party/polymer/components/paper-input/demo/index.html155
-rw-r--r--catapult/third_party/polymer/components/paper-input/demo/ssn-input.html96
-rw-r--r--catapult/third_party/polymer/components/paper-input/demo/ssn-validator.html27
-rwxr-xr-xcatapult/third_party/polymer/components/paper-input/hero.svg19
-rw-r--r--catapult/third_party/polymer/components/paper-input/index.html28
-rw-r--r--catapult/third_party/polymer/components/paper-input/paper-input-addon-behavior.html47
-rw-r--r--catapult/third_party/polymer/components/paper-input/paper-input-behavior.html569
-rw-r--r--catapult/third_party/polymer/components/paper-input/paper-input-char-counter.html99
-rw-r--r--catapult/third_party/polymer/components/paper-input/paper-input-container.html653
-rw-r--r--catapult/third_party/polymer/components/paper-input/paper-input-error.html94
-rw-r--r--catapult/third_party/polymer/components/paper-input/paper-input.html183
-rw-r--r--catapult/third_party/polymer/components/paper-input/paper-textarea.html145
-rw-r--r--catapult/third_party/polymer/components/paper-input/test/index.html32
-rw-r--r--catapult/third_party/polymer/components/paper-input/test/letters-only.html30
-rw-r--r--catapult/third_party/polymer/components/paper-input/test/paper-input-char-counter.html109
-rw-r--r--catapult/third_party/polymer/components/paper-input/test/paper-input-container.html333
-rw-r--r--catapult/third_party/polymer/components/paper-input/test/paper-input-error.html68
-rw-r--r--catapult/third_party/polymer/components/paper-input/test/paper-input.html398
-rw-r--r--catapult/third_party/polymer/components/paper-input/test/paper-textarea.html233
27 files changed, 3614 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/paper-input/.bower.json b/catapult/third_party/polymer/components/paper-input/.bower.json
new file mode 100644
index 00000000..cfd146db
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/.bower.json
@@ -0,0 +1,60 @@
+{
+ "name": "paper-input",
+ "version": "1.1.24",
+ "description": "Material design text fields",
+ "authors": [
+ "The Polymer Authors"
+ ],
+ "keywords": [
+ "web-components",
+ "polymer",
+ "input"
+ ],
+ "main": [
+ "paper-input.html",
+ "paper-textarea.html",
+ "paper-input-behavior.html",
+ "paper-input-container.html",
+ "paper-input-error.html",
+ "paper-input-addon-behavior.html",
+ "paper-input-char-counter.html"
+ ],
+ "private": true,
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/PolymerElements/paper-input.git"
+ },
+ "license": "http://polymer.github.io/LICENSE.txt",
+ "homepage": "https://github.com/PolymerElements/paper-input",
+ "ignore": [],
+ "dependencies": {
+ "polymer": "Polymer/polymer#^1.2.0",
+ "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^1.0.0",
+ "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0",
+ "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#^1.0.0",
+ "iron-input": "PolymerElements/iron-input#^1.0.0",
+ "paper-styles": "PolymerElements/paper-styles#^1.1.4",
+ "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0"
+ },
+ "devDependencies": {
+ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
+ "iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.0.0",
+ "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0",
+ "iron-icon": "PolymerElements/iron-icon#^1.0.0",
+ "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0",
+ "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0",
+ "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0",
+ "test-fixture": "PolymerElements/test-fixture#^1.0.0",
+ "web-component-tester": "^4.0.0",
+ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+ },
+ "_release": "1.1.24",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.1.24",
+ "commit": "881f532e82699f1eb93fd1170e0bb7ff4b3db0cd"
+ },
+ "_source": "https://github.com/PolymerElements/paper-input.git",
+ "_target": "^1.0.0",
+ "_originalSource": "PolymerElements/paper-input"
+} \ No newline at end of file
diff --git a/catapult/third_party/polymer/components/paper-input/.github/ISSUE_TEMPLATE.md b/catapult/third_party/polymer/components/paper-input/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000..99b9301c
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,33 @@
+<!-- Instructions: https://github.com/PolymerElements/paper-input/CONTRIBUTING.md#filing-issues -->
+### Description
+<!-- Example: The `paper-foo` element causes the page to turn pink when clicked. -->
+
+### Expected outcome
+
+<!-- Example: The page stays the same color. -->
+
+### Actual outcome
+
+<!-- Example: The page turns pink. -->
+
+### Live Demo
+<!-- Example: https://jsbin.com/cagaye/edit?html,output -->
+
+### Steps to reproduce
+
+<!-- Example
+1. Put a `paper-foo` element in the page.
+2. Open the page in a web browser.
+3. Click the `paper-foo` element.
+-->
+
+### Browsers Affected
+<!-- Check all that apply -->
+- [ ] Chrome
+- [ ] Firefox
+- [ ] Safari 9
+- [ ] Safari 8
+- [ ] Safari 7
+- [ ] Edge
+- [ ] IE 11
+- [ ] IE 10
diff --git a/catapult/third_party/polymer/components/paper-input/.gitignore b/catapult/third_party/polymer/components/paper-input/.gitignore
new file mode 100644
index 00000000..8d4ae253
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/.gitignore
@@ -0,0 +1 @@
+bower_components
diff --git a/catapult/third_party/polymer/components/paper-input/.travis.yml b/catapult/third_party/polymer/components/paper-input/.travis.yml
new file mode 100644
index 00000000..b24d7f73
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/.travis.yml
@@ -0,0 +1,24 @@
+language: node_js
+sudo: required
+before_script:
+ - npm install -g bower polylint web-component-tester
+ - bower install
+ - polylint
+env:
+ global:
+ - secure: >-
+ Hg2KIEhKqOw0J8ZW2C3Pdgp5N4HD/f9jhdluH0tiYRCU4I/jf5grQuA3ohqsbqnJKV5l06gWVIDCdxBDwDEH0h8v9uUG5z/i2diiuLQc94SLQu8kWKkUPDOx+pUyXmfRKj6KnaRTotTLFrwlyuKDi9OfGjQbLZWTvmJUWoFwh4g=
+ - secure: >-
+ U6/Hp/V0ezT/yxeP2bv4S99LSLScKEaOfYwQUbe0+v5dPbN5XZaCUS6iSbNP2K8Mtb1UQUEyL8uN6Zn+khFlJ8/KJshppJ6HJi235CykahBhh9/Cv7EapgDUoss14ntE8EKpm6Ijo4LvVyPVmhgqKk9wP5ykDFtvhoKD4C3guVU=
+node_js: '6'
+addons:
+ firefox: latest
+ apt:
+ sources:
+ - google-chrome
+ packages:
+ - google-chrome-stable
+script:
+ - xvfb-run wct
+ - 'if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then wct -s ''default''; fi'
+dist: trusty
diff --git a/catapult/third_party/polymer/components/paper-input/CONTRIBUTING.md b/catapult/third_party/polymer/components/paper-input/CONTRIBUTING.md
new file mode 100644
index 00000000..093090d4
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/CONTRIBUTING.md
@@ -0,0 +1,77 @@
+<!--
+This file is autogenerated based on
+https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md
+
+If you edit that file, it will get updated everywhere else.
+If you edit this file, your changes will get overridden :)
+
+You can however override the jsbin link with one that's customized to this
+specific element:
+
+jsbin=https://jsbin.com/cagaye/edit?html,output
+-->
+
+# Polymer Elements
+## Guide for Contributors
+
+Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines:
+
+### Filing Issues
+
+**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions:
+
+ 1. **Who will use the feature?** _“As someone filling out a form…”_
+ 2. **When will they use the feature?** _“When I enter an invalid value…”_
+ 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_
+
+**If you are filing an issue to report a bug**, please provide:
+
+ 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug:
+
+ ```markdown
+ The `paper-foo` element causes the page to turn pink when clicked.
+
+ ## Expected outcome
+
+ The page stays the same color.
+
+ ## Actual outcome
+
+ The page turns pink.
+
+ ## Steps to reproduce
+
+ 1. Put a `paper-foo` element in the page.
+ 2. Open the page in a web browser.
+ 3. Click the `paper-foo` element.
+ ```
+
+ 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [https://jsbin.com/cagaye/edit?html,output](https://jsbin.com/cagaye/edit?html,output).
+
+ 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers.
+
+### Submitting Pull Requests
+
+**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request.
+
+When submitting pull requests, please provide:
+
+ 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues in the pull request description using the following syntax:
+
+ ```markdown
+ (For a single issue)
+ Fixes #20
+
+ (For multiple issues)
+ Fixes #32, fixes #40
+ ```
+
+ 2. **A succinct description of the design** used to fix any related issues. For example:
+
+ ```markdown
+ This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked.
+ ```
+
+ 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered.
+
+If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/catapult/third_party/polymer/components/paper-input/README.md b/catapult/third_party/polymer/components/paper-input/README.md
new file mode 100644
index 00000000..80c6bc33
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/README.md
@@ -0,0 +1,38 @@
+[![Build status](https://travis-ci.org/PolymerElements/paper-input.svg?branch=master)](https://travis-ci.org/PolymerElements/paper-input)
+[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://beta.webcomponents.org/element/PolymerElements/paper-input)
+
+## &lt;paper-input&gt;
+
+Material design: [Text fields](https://www.google.com/design/spec/components/text-fields.html)
+
+`<paper-input>` is a single-line text field with Material Design styling.
+
+<!---
+```
+<custom-element-demo>
+ <template>
+ <script src="../webcomponentsjs/webcomponents-lite.js"></script>
+ <link rel="import" href="paper-input.html">
+ <link rel="import" href="../iron-icons/iron-icons.html">
+ <style>
+ paper-input {
+ max-width: 400px;
+ margin: auto;
+ }
+ iron-icon, div[suffix] {
+ color: hsl(0, 0%, 50%);
+ margin-right: 12px;
+ }
+ </style>
+ <next-code-block></next-code-block>
+ </template>
+</custom-element-demo>
+```
+-->
+```html
+<paper-input always-float-label label="Floating label"></paper-input>
+<paper-input label="username">
+ <iron-icon icon="mail" prefix></iron-icon>
+ <div suffix>@email.com</div>
+</paper-input>
+```
diff --git a/catapult/third_party/polymer/components/paper-input/all-imports.html b/catapult/third_party/polymer/components/paper-input/all-imports.html
new file mode 100644
index 00000000..0f457718
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/all-imports.html
@@ -0,0 +1,12 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="paper-input.html">
+<link rel="import" href="paper-textarea.html">
diff --git a/catapult/third_party/polymer/components/paper-input/bower.json b/catapult/third_party/polymer/components/paper-input/bower.json
new file mode 100644
index 00000000..84a2e99d
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/bower.json
@@ -0,0 +1,51 @@
+{
+ "name": "paper-input",
+ "version": "1.1.24",
+ "description": "Material design text fields",
+ "authors": [
+ "The Polymer Authors"
+ ],
+ "keywords": [
+ "web-components",
+ "polymer",
+ "input"
+ ],
+ "main": [
+ "paper-input.html",
+ "paper-textarea.html",
+ "paper-input-behavior.html",
+ "paper-input-container.html",
+ "paper-input-error.html",
+ "paper-input-addon-behavior.html",
+ "paper-input-char-counter.html"
+ ],
+ "private": true,
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/PolymerElements/paper-input.git"
+ },
+ "license": "http://polymer.github.io/LICENSE.txt",
+ "homepage": "https://github.com/PolymerElements/paper-input",
+ "ignore": [],
+ "dependencies": {
+ "polymer": "Polymer/polymer#^1.2.0",
+ "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^1.0.0",
+ "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0",
+ "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#^1.0.0",
+ "iron-input": "PolymerElements/iron-input#^1.0.0",
+ "paper-styles": "PolymerElements/paper-styles#^1.1.4",
+ "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0"
+ },
+ "devDependencies": {
+ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
+ "iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.0.0",
+ "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0",
+ "iron-icon": "PolymerElements/iron-icon#^1.0.0",
+ "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0",
+ "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0",
+ "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0",
+ "test-fixture": "PolymerElements/test-fixture#^1.0.0",
+ "web-component-tester": "^4.0.0",
+ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+ }
+}
diff --git a/catapult/third_party/polymer/components/paper-input/demo/index.html b/catapult/third_party/polymer/components/paper-input/demo/index.html
new file mode 100644
index 00000000..f84799de
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/demo/index.html
@@ -0,0 +1,155 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
+
+ <title>paper-input demo</title>
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+
+ <link rel="import" href="../../iron-demo-helpers/demo-pages-shared-styles.html">
+ <link rel="import" href="../../iron-demo-helpers/demo-snippet.html">
+ <link rel="import" href="../../iron-icon/iron-icon.html">
+ <link rel="import" href="../../iron-icons/iron-icons.html">
+ <link rel="import" href="../../iron-input/iron-input.html">
+ <link rel="import" href="../../paper-icon-button/paper-icon-button.html">
+ <link rel="import" href="../../paper-styles/color.html">
+ <link rel="import" href="../paper-input-container.html">
+ <link rel="import" href="../paper-input-error.html">
+ <link rel="import" href="../paper-input.html">
+ <link rel="import" href="../paper-textarea.html">
+ <link rel="import" href="ssn-input.html">
+
+ <style is="custom-style" include="demo-pages-shared-styles">
+ paper-input {
+ display: block;
+ }
+
+ demo-snippet.horizontal {
+ --demo-snippet-demo: {
+ @apply(--layout-horizontal);
+ @apply(--layout-justified);
+ @apply(--layout-wrap);
+ }
+ }
+ demo-snippet.horizontal paper-input {
+ display: inline-block;
+ }
+
+ button {
+ width: 70px;
+ }
+
+ #inputForValidation {
+ display: inline-block;
+ width: calc(100% - 75px);
+ }
+
+ .vertical-section-container {
+ max-width: 600px;
+ }
+
+ paper-icon-button {
+ color: var(--paper-red-300);
+ --paper-icon-button-ink-color: var(--paper-red-a100);
+ width: 23px; /* 15px + 2*4px for padding */
+ height: 23px;
+ padding: 0px 4px;
+ }
+
+ iron-icon {
+ padding-right: 5px;
+ }
+ </style>
+</head>
+<body unresolved>
+ <div class="vertical-section-container centered">
+ <h3>Inputs can have different types, and be disabled</h3>
+ <demo-snippet>
+ <template>
+ <paper-input label="text input"></paper-input>
+ <paper-textarea label="autoresizing textarea input"></paper-textarea>
+ <paper-input label="password input" type="password"></paper-input>
+ <paper-input label="disabled input" disabled></paper-input>
+ </template>
+ </demo-snippet>
+
+ <h3>Inputs can have character counters</h3>
+ <demo-snippet>
+ <template>
+ <paper-input label="simple character counter" char-counter></paper-input>
+ <paper-input label="input with at most 10 characters" char-counter maxlength="10"></paper-input>
+ </template>
+ </demo-snippet>
+
+ <h3>The label can have different floating states</h3>
+ <demo-snippet>
+ <template>
+ <paper-input label="this label floats after typing"></paper-input>
+ <paper-input label="this label is always floating" always-float-label></paper-input>
+ <paper-input label="this label never floats" no-label-float></paper-input>
+ <paper-input label="this label is always floating" always-float-label placeholder="placeholder text"></paper-input>
+ </template>
+ </demo-snippet>
+
+ <h3>Inputs can validate automatically or on demand, and can have custom error messages</h3>
+ <demo-snippet>
+ <template>
+ <paper-input label="this input requires some text" required auto-validate error-message="needs some text!"></paper-input>
+ <paper-input label="this input requires letters only" auto-validate pattern="[a-zA-Z]*" error-message="letters only!"></paper-input>
+ <paper-input label="this input will only let you type letters" auto-validate allowed-pattern="[a-zA-Z]"></paper-input>
+ <paper-input id="inputForValidation" required label="this input is manually validated" pattern="[a-zA-Z]*" error-message="letters only!"></paper-input>
+ <button onclick="validate()">Validate!</button>
+ </template>
+ </demo-snippet>
+
+ <h3>Inputs can have prefixes and suffixes</h3>
+ <demo-snippet class="horizontal">
+ <template>
+ <paper-input label="total" type="number">
+ <div prefix>$</div>
+ </paper-input>
+ <paper-input label="username" id="inputWithButton">
+ <iron-icon icon="mail" prefix></iron-icon>
+ <div suffix>@email.com</div>
+ <paper-icon-button suffix onclick="clearInput()"
+ icon="clear" alt="clear" title="clear">
+ </paper-icon-button>
+ </paper-input>
+ </template>
+ </demo-snippet>
+
+ <h3>Inputs can have custom logic</h3>
+ <demo-snippet>
+ <template>
+ <paper-input-container always-float-label auto-validate attr-for-value="value">
+ <label>Social Security Number</label>
+ <ssn-input class="paper-input-input"></ssn-input>
+ <paper-input-error>SSN invalid!</paper-input-error>
+ </paper-input-container>
+ </template>
+ </demo-snippet>
+ </div>
+
+ <script>
+ function validate() {
+ document.getElementById('inputForValidation').validate();
+ }
+
+ function clearInput() {
+ document.getElementById('inputWithButton').value = '';
+ }
+ </script>
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/paper-input/demo/ssn-input.html b/catapult/third_party/polymer/components/paper-input/demo/ssn-input.html
new file mode 100644
index 00000000..c7ab51dd
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/demo/ssn-input.html
@@ -0,0 +1,96 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<link rel="import" href="../../polymer/polymer.html">
+<link rel="import" href="../../iron-input/iron-input.html">
+<link rel="import" href="../../iron-flex-layout/iron-flex-layout.html">
+<link rel="import" href="ssn-validator.html">
+
+<dom-module id="ssn-input">
+ <template>
+
+ <style>
+ :host {
+ display: inline-block;
+ }
+
+ :host([hidden]) {
+ display: none !important;
+ }
+
+ input[is="iron-input"] {
+ font: inherit;
+ outline: none;
+ box-shadow: none;
+ border: none;
+ width: auto;
+ text-align: center;
+ }
+
+ .container {
+ @apply(--layout-horizontal);
+ }
+ </style>
+
+ <ssn-validator></ssn-validator>
+
+ <div class="container">
+
+ <input is="iron-input" maxlength="3" bind-value="{{_ssn1}}" size="3" aria-label="First 3 digits of social security number">
+ -
+ <input is="iron-input" maxlength="2" bind-value="{{_ssn2}}" size="2" aria-label="Middle 2 digits of social security number">
+ -
+ <input is="iron-input" maxlength="4" bind-value="{{_ssn3}}" size="4" aria-label="Last 4 digits of social security number">
+
+ </div>
+
+ </template>
+</dom-module>
+
+<script>
+ Polymer({
+ is: 'ssn-input',
+
+ behaviors: [
+ Polymer.IronValidatableBehavior
+ ],
+
+ properties: {
+ value: {
+ notify: true,
+ type: String
+ },
+
+ _ssn1: {
+ type: String
+ },
+
+ _ssn2: {
+ type: String
+ },
+
+ _ssn3: {
+ type: String
+ },
+
+ validator: {
+ type: String,
+ value: 'ssn-validator'
+ }
+ },
+
+ observers: [
+ '_computeValue(_ssn1,_ssn2,_ssn3)'
+ ],
+
+ _computeValue: function(ssn1, ssn2, ssn3) {
+ this.value = ssn1.trim() + '-' + ssn2.trim() + '-' + ssn3.trim();
+ }
+ });
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/demo/ssn-validator.html b/catapult/third_party/polymer/components/paper-input/demo/ssn-validator.html
new file mode 100644
index 00000000..e45365b5
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/demo/ssn-validator.html
@@ -0,0 +1,27 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../../polymer/polymer.html">
+<link rel="import" href="../../iron-validator-behavior/iron-validator-behavior.html">
+
+<script>
+ Polymer({
+ is: 'ssn-validator',
+
+ behaviors: [
+ Polymer.IronValidatorBehavior
+ ],
+
+ validate: function(value) {
+ // this regex validates incomplete ssn's (by design)
+ return !value || value.match(/^[0-9]{0,3}-[0-9]{0,2}-[0-9]{0,4}$/);
+ }
+ });
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/hero.svg b/catapult/third_party/polymer/components/paper-input/hero.svg
new file mode 100755
index 00000000..e72ebd30
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/hero.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 225 126" enable-background="new 0 0 225 126" xml:space="preserve">
+<g id="background" display="none">
+ <rect display="inline" fill="#B0BEC5" width="225" height="126"/>
+</g>
+<g id="label">
+</g>
+<g id="art">
+ <rect x="49" y="53" width="2" height="18"/>
+ <path d="M188,78H37V44h151V78z M39,76h147V46H39V76z"/>
+ <g id="ic_x5F_add_x0D_">
+ </g>
+</g>
+<g id="Guides">
+</g>
+</svg>
diff --git a/catapult/third_party/polymer/components/paper-input/index.html b/catapult/third_party/polymer/components/paper-input/index.html
new file mode 100644
index 00000000..e6c9fadc
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/index.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+ <title>paper-input</title>
+
+ <script src="../webcomponentsjs/webcomponents-lite.js"></script>
+ <link rel="import" href="../iron-component-page/iron-component-page.html">
+
+</head>
+<body>
+
+ <iron-component-page src="all-imports.html"></iron-component-page>
+
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/paper-input/paper-input-addon-behavior.html b/catapult/third_party/polymer/components/paper-input/paper-input-addon-behavior.html
new file mode 100644
index 00000000..41081c71
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/paper-input-addon-behavior.html
@@ -0,0 +1,47 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+
+<script>
+
+ /**
+ * Use `Polymer.PaperInputAddonBehavior` to implement an add-on for `<paper-input-container>`. A
+ * add-on appears below the input, and may display information based on the input value and
+ * validity such as a character counter or an error message.
+ * @polymerBehavior
+ */
+ Polymer.PaperInputAddonBehavior = {
+
+ hostAttributes: {
+ 'add-on': ''
+ },
+
+ attached: function() {
+ this.fire('addon-attached');
+ },
+
+ /**
+ * The function called by `<paper-input-container>` when the input value or validity changes.
+ * @param {{
+ * inputElement: (Element|undefined),
+ * value: (string|undefined),
+ * invalid: boolean
+ * }} state -
+ * inputElement: The input element.
+ * value: The input value.
+ * invalid: True if the input value is invalid.
+ */
+ update: function(state) {
+ }
+
+ };
+
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/paper-input-behavior.html b/catapult/third_party/polymer/components/paper-input/paper-input-behavior.html
new file mode 100644
index 00000000..33e2a2db
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/paper-input-behavior.html
@@ -0,0 +1,569 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
+<link rel="import" href="../iron-behaviors/iron-control-state.html">
+
+<script>
+
+ // Generate unique, monotonically increasing IDs for labels (needed by
+ // aria-labelledby) and add-ons.
+ Polymer.PaperInputHelper = {};
+ Polymer.PaperInputHelper.NextLabelID = 1;
+ Polymer.PaperInputHelper.NextAddonID = 1;
+
+ /**
+ * Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-container>`. This
+ * behavior is implemented by `<paper-input>`. It exposes a number of properties from
+ * `<paper-input-container>` and `<input is="iron-input">` and they should be bound in your
+ * template.
+ *
+ * The input element can be accessed by the `inputElement` property if you need to access
+ * properties or methods that are not exposed.
+ * @polymerBehavior Polymer.PaperInputBehavior
+ */
+ Polymer.PaperInputBehaviorImpl = {
+
+ properties: {
+ /**
+ * Fired when the input changes due to user interaction.
+ *
+ * @event change
+ */
+
+ /**
+ * The label for this input. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * `<label>`'s content and `hidden` property, e.g.
+ * `<label hidden$="[[!label]]">[[label]]</label>` in your `template`
+ */
+ label: {
+ type: String
+ },
+
+ /**
+ * The value for this input. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * the `<input is="iron-input">`'s `bindValue`
+ * property, or the value property of your input that is `notify:true`.
+ */
+ value: {
+ notify: true,
+ type: String
+ },
+
+ /**
+ * Set to true to disable this input. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * both the `<paper-input-container>`'s and the input's `disabled` property.
+ */
+ disabled: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * Returns true if the value is invalid. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to both the
+ * `<paper-input-container>`'s and the input's `invalid` property.
+ *
+ * If `autoValidate` is true, the `invalid` attribute is managed automatically,
+ * which can clobber attempts to manage it manually.
+ */
+ invalid: {
+ type: Boolean,
+ value: false,
+ notify: true
+ },
+
+ /**
+ * Set to true to prevent the user from entering invalid input. If you're
+ * using PaperInputBehavior to implement your own paper-input-like element,
+ * bind this to `<input is="iron-input">`'s `preventInvalidInput` property.
+ */
+ preventInvalidInput: {
+ type: Boolean
+ },
+
+ /**
+ * Set this to specify the pattern allowed by `preventInvalidInput`. If
+ * you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `allowedPattern`
+ * property.
+ */
+ allowedPattern: {
+ type: String
+ },
+
+ /**
+ * The type of the input. The supported types are `text`, `number` and `password`.
+ * If you're using PaperInputBehavior to implement your own paper-input-like element,
+ * bind this to the `<input is="iron-input">`'s `type` property.
+ */
+ type: {
+ type: String
+ },
+
+ /**
+ * The datalist of the input (if any). This should match the id of an existing `<datalist>`.
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `list` property.
+ */
+ list: {
+ type: String
+ },
+
+ /**
+ * A pattern to validate the `input` with. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * the `<input is="iron-input">`'s `pattern` property.
+ */
+ pattern: {
+ type: String
+ },
+
+ /**
+ * Set to true to mark the input as required. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * the `<input is="iron-input">`'s `required` property.
+ */
+ required: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * The error message to display when the input is invalid. If you're using
+ * PaperInputBehavior to implement your own paper-input-like element,
+ * bind this to the `<paper-input-error>`'s content, if using.
+ */
+ errorMessage: {
+ type: String
+ },
+
+ /**
+ * Set to true to show a character counter.
+ */
+ charCounter: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * Set to true to disable the floating label. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * the `<paper-input-container>`'s `noLabelFloat` property.
+ */
+ noLabelFloat: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * Set to true to always float the label. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * the `<paper-input-container>`'s `alwaysFloatLabel` property.
+ */
+ alwaysFloatLabel: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * Set to true to auto-validate the input value. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * the `<paper-input-container>`'s `autoValidate` property.
+ */
+ autoValidate: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * Name of the validator to use. If you're using PaperInputBehavior to
+ * implement your own paper-input-like element, bind this to
+ * the `<input is="iron-input">`'s `validator` property.
+ */
+ validator: {
+ type: String
+ },
+
+ // HTMLInputElement attributes for binding if needed
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `autocomplete` property.
+ */
+ autocomplete: {
+ type: String,
+ value: 'off'
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `autofocus` property.
+ */
+ autofocus: {
+ type: Boolean,
+ observer: '_autofocusChanged'
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `inputmode` property.
+ */
+ inputmode: {
+ type: String
+ },
+
+ /**
+ * The minimum length of the input value.
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `minlength` property.
+ */
+ minlength: {
+ type: Number
+ },
+
+ /**
+ * The maximum length of the input value.
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `maxlength` property.
+ */
+ maxlength: {
+ type: Number
+ },
+
+ /**
+ * The minimum (numeric or date-time) input value.
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `min` property.
+ */
+ min: {
+ type: String
+ },
+
+ /**
+ * The maximum (numeric or date-time) input value.
+ * Can be a String (e.g. `"2000-01-01"`) or a Number (e.g. `2`).
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `max` property.
+ */
+ max: {
+ type: String
+ },
+
+ /**
+ * Limits the numeric or date-time increments.
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `step` property.
+ */
+ step: {
+ type: String
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `name` property.
+ */
+ name: {
+ type: String
+ },
+
+ /**
+ * A placeholder string in addition to the label. If this is set, the label will always float.
+ */
+ placeholder: {
+ type: String,
+ // need to set a default so _computeAlwaysFloatLabel is run
+ value: ''
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `readonly` property.
+ */
+ readonly: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `size` property.
+ */
+ size: {
+ type: Number
+ },
+
+ // Nonstandard attributes for binding if needed
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `autocapitalize` property.
+ */
+ autocapitalize: {
+ type: String,
+ value: 'none'
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `autocorrect` property.
+ */
+ autocorrect: {
+ type: String,
+ value: 'off'
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `autosave` property,
+ * used with type=search.
+ */
+ autosave: {
+ type: String
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `results` property,
+ * used with type=search.
+ */
+ results: {
+ type: Number
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the `<input is="iron-input">`'s `accept` property,
+ * used with type=file.
+ */
+ accept: {
+ type: String
+ },
+
+ /**
+ * If you're using PaperInputBehavior to implement your own paper-input-like
+ * element, bind this to the`<input is="iron-input">`'s `multiple` property,
+ * used with type=file.
+ */
+ multiple: {
+ type: Boolean
+ },
+
+ _ariaDescribedBy: {
+ type: String,
+ value: ''
+ },
+
+ _ariaLabelledBy: {
+ type: String,
+ value: ''
+ }
+
+ },
+
+ listeners: {
+ 'addon-attached': '_onAddonAttached',
+ },
+
+ keyBindings: {
+ 'shift+tab:keydown': '_onShiftTabDown'
+ },
+
+ hostAttributes: {
+ tabindex: 0
+ },
+
+ /**
+ * Returns a reference to the input element.
+ */
+ get inputElement() {
+ return this.$.input;
+ },
+
+ /**
+ * Returns a reference to the focusable element.
+ */
+ get _focusableElement() {
+ return this.inputElement;
+ },
+
+ registered: function() {
+ // These types have some default placeholder text; overlapping
+ // the label on top of it looks terrible. Auto-float the label in this case.
+ this._typesThatHaveText = ["date", "datetime", "datetime-local", "month",
+ "time", "week", "file"];
+ },
+
+ attached: function() {
+ this._updateAriaLabelledBy();
+
+ if (this.inputElement &&
+ this._typesThatHaveText.indexOf(this.inputElement.type) !== -1) {
+ this.alwaysFloatLabel = true;
+ }
+ },
+
+ _appendStringWithSpace: function(str, more) {
+ if (str) {
+ str = str + ' ' + more;
+ } else {
+ str = more;
+ }
+ return str;
+ },
+
+ _onAddonAttached: function(event) {
+ var target = event.path ? event.path[0] : event.target;
+ if (target.id) {
+ this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, target.id);
+ } else {
+ var id = 'paper-input-add-on-' + Polymer.PaperInputHelper.NextAddonID++;
+ target.id = id;
+ this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, id);
+ }
+ },
+
+ /**
+ * Validates the input element and sets an error style if needed.
+ *
+ * @return {boolean}
+ */
+ validate: function() {
+ return this.inputElement.validate();
+ },
+
+ /**
+ * Forward focus to inputElement. Overriden from IronControlState.
+ */
+ _focusBlurHandler: function(event) {
+ Polymer.IronControlState._focusBlurHandler.call(this, event);
+
+ // Forward the focus to the nested input.
+ if (this.focused && !this._shiftTabPressed)
+ this._focusableElement.focus();
+ },
+
+ /**
+ * Handler that is called when a shift+tab keypress is detected by the menu.
+ *
+ * @param {CustomEvent} event A key combination event.
+ */
+ _onShiftTabDown: function(event) {
+ var oldTabIndex = this.getAttribute('tabindex');
+ this._shiftTabPressed = true;
+ this.setAttribute('tabindex', '-1');
+ this.async(function() {
+ this.setAttribute('tabindex', oldTabIndex);
+ this._shiftTabPressed = false;
+ }, 1);
+ },
+
+ /**
+ * If `autoValidate` is true, then validates the element.
+ */
+ _handleAutoValidate: function() {
+ if (this.autoValidate)
+ this.validate();
+ },
+
+ /**
+ * Restores the cursor to its original position after updating the value.
+ * @param {string} newValue The value that should be saved.
+ */
+ updateValueAndPreserveCaret: function(newValue) {
+ // Not all elements might have selection, and even if they have the
+ // right properties, accessing them might throw an exception (like for
+ // <input type=number>)
+ try {
+ var start = this.inputElement.selectionStart;
+ this.value = newValue;
+
+ // The cursor automatically jumps to the end after re-setting the value,
+ // so restore it to its original position.
+ this.inputElement.selectionStart = start;
+ this.inputElement.selectionEnd = start;
+ } catch (e) {
+ // Just set the value and give up on the caret.
+ this.value = newValue;
+ }
+ },
+
+ _computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) {
+ return placeholder || alwaysFloatLabel;
+ },
+
+ _updateAriaLabelledBy: function() {
+ var label = Polymer.dom(this.root).querySelector('label');
+ if (!label) {
+ this._ariaLabelledBy = '';
+ return;
+ }
+ var labelledBy;
+ if (label.id) {
+ labelledBy = label.id;
+ } else {
+ labelledBy = 'paper-input-label-' + Polymer.PaperInputHelper.NextLabelID++;
+ label.id = labelledBy;
+ }
+ this._ariaLabelledBy = labelledBy;
+ },
+
+ _onChange:function(event) {
+ // In the Shadow DOM, the `change` event is not leaked into the
+ // ancestor tree, so we must do this manually.
+ // See https://w3c.github.io/webcomponents/spec/shadow/#events-that-are-not-leaked-into-ancestor-trees.
+ if (this.shadowRoot) {
+ this.fire(event.type, {sourceEvent: event}, {
+ node: this,
+ bubbles: event.bubbles,
+ cancelable: event.cancelable
+ });
+ }
+ },
+
+ _autofocusChanged: function() {
+ // Firefox doesn't respect the autofocus attribute if it's applied after
+ // the page is loaded (Chrome/WebKit do respect it), preventing an
+ // autofocus attribute specified in markup from taking effect when the
+ // element is upgraded. As a workaround, if the autofocus property is set,
+ // and the focus hasn't already been moved elsewhere, we take focus.
+ if (this.autofocus && this._focusableElement) {
+
+ // In IE 11, the default document.activeElement can be the page's
+ // outermost html element, but there are also cases (under the
+ // polyfill?) in which the activeElement is not a real HTMLElement, but
+ // just a plain object. We identify the latter case as having no valid
+ // activeElement.
+ var activeElement = document.activeElement;
+ var isActiveElementValid = activeElement instanceof HTMLElement;
+
+ // Has some other element has already taken the focus?
+ var isSomeElementActive = isActiveElementValid &&
+ activeElement !== document.body &&
+ activeElement !== document.documentElement; /* IE 11 */
+ if (!isSomeElementActive) {
+ // No specific element has taken the focus yet, so we can take it.
+ this._focusableElement.focus();
+ }
+ }
+ }
+ };
+
+ /** @polymerBehavior */
+ Polymer.PaperInputBehavior = [
+ Polymer.IronControlState,
+ Polymer.IronA11yKeysBehavior,
+ Polymer.PaperInputBehaviorImpl
+ ];
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/paper-input-char-counter.html b/catapult/third_party/polymer/components/paper-input/paper-input-char-counter.html
new file mode 100644
index 00000000..1a09a06d
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/paper-input-char-counter.html
@@ -0,0 +1,99 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../paper-styles/typography.html">
+<link rel="import" href="paper-input-addon-behavior.html">
+
+<!--
+`<paper-input-char-counter>` is a character counter for use with `<paper-input-container>`. It
+shows the number of characters entered in the input and the max length if it is specified.
+
+ <paper-input-container>
+ <input is="iron-input" maxlength="20">
+ <paper-input-char-counter></paper-input-char-counter>
+ </paper-input-container>
+
+### Styling
+
+The following mixin is available for styling:
+
+Custom property | Description | Default
+----------------|-------------|----------
+`--paper-input-char-counter` | Mixin applied to the element | `{}`
+-->
+
+<dom-module id="paper-input-char-counter">
+ <template>
+ <style>
+ :host {
+ display: inline-block;
+ float: right;
+
+ @apply(--paper-font-caption);
+ @apply(--paper-input-char-counter);
+ }
+
+ :host([hidden]) {
+ display: none !important;
+ }
+
+ :host-context([dir="rtl"]) {
+ float: left;
+ }
+ </style>
+
+ <span>[[_charCounterStr]]</span>
+ </template>
+</dom-module>
+
+<script>
+ Polymer({
+ is: 'paper-input-char-counter',
+
+ behaviors: [
+ Polymer.PaperInputAddonBehavior
+ ],
+
+ properties: {
+ _charCounterStr: {
+ type: String,
+ value: '0'
+ }
+ },
+
+ /**
+ * This overrides the update function in PaperInputAddonBehavior.
+ * @param {{
+ * inputElement: (Element|undefined),
+ * value: (string|undefined),
+ * invalid: boolean
+ * }} state -
+ * inputElement: The input element.
+ * value: The input value.
+ * invalid: True if the input value is invalid.
+ */
+ update: function(state) {
+ if (!state.inputElement) {
+ return;
+ }
+
+ state.value = state.value || '';
+
+ var counter = state.value.toString().length.toString();
+
+ if (state.inputElement.hasAttribute('maxlength')) {
+ counter += '/' + state.inputElement.getAttribute('maxlength');
+ }
+
+ this._charCounterStr = counter;
+ }
+ });
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/paper-input-container.html b/catapult/third_party/polymer/components/paper-input/paper-input-container.html
new file mode 100644
index 00000000..2ef06efa
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/paper-input-container.html
@@ -0,0 +1,653 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
+<link rel="import" href="../paper-styles/default-theme.html">
+<link rel="import" href="../paper-styles/typography.html">
+
+<!--
+`<paper-input-container>` is a container for a `<label>`, an `<input is="iron-input">` or
+`<textarea>` and optional add-on elements such as an error message or character
+counter, used to implement Material Design text fields.
+
+For example:
+
+ <paper-input-container>
+ <label>Your name</label>
+ <input is="iron-input">
+ </paper-input-container>
+
+Do not wrap `<paper-input-container>` around elements that already include it, such as `<paper-input>`.
+Doing so may cause events to bounce infintely between the container and its contained element.
+
+### Listening for input changes
+
+By default, it listens for changes on the `bind-value` attribute on its children nodes and perform
+tasks such as auto-validating and label styling when the `bind-value` changes. You can configure
+the attribute it listens to with the `attr-for-value` attribute.
+
+### Using a custom input element
+
+You can use a custom input element in a `<paper-input-container>`, for example to implement a
+compound input field like a social security number input. The custom input element should have the
+`paper-input-input` class, have a `notify:true` value property and optionally implements
+`Polymer.IronValidatableBehavior` if it is validatable.
+
+ <paper-input-container attr-for-value="ssn-value">
+ <label>Social security number</label>
+ <ssn-input class="paper-input-input"></ssn-input>
+ </paper-input-container>
+
+
+If you're using a `<paper-input-container>` imperatively, it's important to make sure
+that you attach its children (the `iron-input` and the optional `label`) before you
+attach the `<paper-input-container>` itself, so that it can be set up correctly.
+
+### Validation
+
+If the `auto-validate` attribute is set, the input container will validate the input and update
+the container styling when the input value changes.
+
+### Add-ons
+
+Add-ons are child elements of a `<paper-input-container>` with the `add-on` attribute and
+implements the `Polymer.PaperInputAddonBehavior` behavior. They are notified when the input value
+or validity changes, and may implement functionality such as error messages or character counters.
+They appear at the bottom of the input.
+
+### Prefixes and suffixes
+These are child elements of a `<paper-input-container>` with the `prefix`
+or `suffix` attribute, and are displayed inline with the input, before or after.
+
+ <paper-input-container>
+ <div prefix>$</div>
+ <label>Total</label>
+ <input is="iron-input">
+ <paper-icon-button suffix icon="clear"></paper-icon-button>
+ </paper-input-container>
+
+### Styling
+
+The following custom properties and mixins are available for styling:
+
+Custom property | Description | Default
+----------------|-------------|----------
+`--paper-input-container-color` | Label and underline color when the input is not focused | `--secondary-text-color`
+`--paper-input-container-focus-color` | Label and underline color when the input is focused | `--primary-color`
+`--paper-input-container-invalid-color` | Label and underline color when the input is is invalid | `--error-color`
+`--paper-input-container-input-color` | Input foreground color | `--primary-text-color`
+`--paper-input-container` | Mixin applied to the container | `{}`
+`--paper-input-container-disabled` | Mixin applied to the container when it's disabled | `{}`
+`--paper-input-container-label` | Mixin applied to the label | `{}`
+`--paper-input-container-label-focus` | Mixin applied to the label when the input is focused | `{}`
+`--paper-input-container-label-floating` | Mixin applied to the label when floating | `{}`
+`--paper-input-container-input` | Mixin applied to the input | `{}`
+`--paper-input-container-input-focus` | Mixin applied to the input when focused | `{}`
+`--paper-input-container-input-invalid` | Mixin applied to the input when invalid | `{}`
+`--paper-input-container-input-webkit-spinner` | Mixin applied to the webkit spinner | `{}`
+`--paper-input-container-input-webkit-clear` | Mixin applied to the webkit clear button | `{}`
+`--paper-input-container-ms-clear` | Mixin applied to the Internet Explorer clear button | `{}`
+`--paper-input-container-underline` | Mixin applied to the underline | `{}`
+`--paper-input-container-underline-focus` | Mixin applied to the underline when the input is focused | `{}`
+`--paper-input-container-underline-disabled` | Mixin applied to the underline when the input is disabled | `{}`
+`--paper-input-prefix` | Mixin applied to the input prefix | `{}`
+`--paper-input-suffix` | Mixin applied to the input suffix | `{}`
+
+This element is `display:block` by default, but you can set the `inline` attribute to make it
+`display:inline-block`.
+-->
+
+<dom-module id="paper-input-container">
+ <template>
+ <style>
+ :host {
+ display: block;
+ padding: 8px 0;
+
+ @apply(--paper-input-container);
+ }
+
+ :host([inline]) {
+ display: inline-block;
+ }
+
+ :host([disabled]) {
+ pointer-events: none;
+ opacity: 0.33;
+
+ @apply(--paper-input-container-disabled);
+ }
+
+ :host([hidden]) {
+ display: none !important;
+ }
+
+ .floated-label-placeholder {
+ @apply(--paper-font-caption);
+ }
+
+ .underline {
+ height: 2px;
+ position: relative;
+ }
+
+ .focused-line {
+ @apply(--layout-fit);
+
+ border-bottom: 2px solid var(--paper-input-container-focus-color, --primary-color);
+
+ -webkit-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: scale3d(0,1,1);
+ transform: scale3d(0,1,1);
+
+ @apply(--paper-input-container-underline-focus);
+ }
+
+ .underline.is-highlighted .focused-line {
+ -webkit-transform: none;
+ transform: none;
+ -webkit-transition: -webkit-transform 0.25s;
+ transition: transform 0.25s;
+
+ @apply(--paper-transition-easing);
+ }
+
+ .underline.is-invalid .focused-line {
+ border-color: var(--paper-input-container-invalid-color, --error-color);
+ -webkit-transform: none;
+ transform: none;
+ -webkit-transition: -webkit-transform 0.25s;
+ transition: transform 0.25s;
+
+ @apply(--paper-transition-easing);
+ }
+
+ .unfocused-line {
+ @apply(--layout-fit);
+
+ border-bottom: 1px solid var(--paper-input-container-color, --secondary-text-color);
+
+ @apply(--paper-input-container-underline);
+ }
+
+ :host([disabled]) .unfocused-line {
+ border-bottom: 1px dashed;
+ border-color: var(--paper-input-container-color, --secondary-text-color);
+
+ @apply(--paper-input-container-underline-disabled);
+ }
+
+ .label-and-input-container {
+ @apply(--layout-flex-auto);
+ @apply(--layout-relative);
+
+ width: 100%;
+ max-width: 100%;
+ }
+
+ .input-content {
+ @apply(--layout-horizontal);
+ @apply(--layout-center);
+
+ position: relative;
+ }
+
+ .input-content ::content label,
+ .input-content ::content .paper-input-label {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ width: 100%;
+ font: inherit;
+ color: var(--paper-input-container-color, --secondary-text-color);
+ -webkit-transition: -webkit-transform 0.25s, width 0.25s;
+ transition: transform 0.25s, width 0.25s;
+ -webkit-transform-origin: left top;
+ transform-origin: left top;
+
+ @apply(--paper-font-common-nowrap);
+ @apply(--paper-font-subhead);
+ @apply(--paper-input-container-label);
+ @apply(--paper-transition-easing);
+ }
+
+ .input-content.label-is-floating ::content label,
+ .input-content.label-is-floating ::content .paper-input-label {
+ -webkit-transform: translateY(-75%) scale(0.75);
+ transform: translateY(-75%) scale(0.75);
+
+ /* Since we scale to 75/100 of the size, we actually have 100/75 of the
+ original space now available */
+ width: 133%;
+
+ @apply(--paper-input-container-label-floating);
+ }
+
+ :host-context([dir="rtl"]) .input-content.label-is-floating ::content label,
+ :host-context([dir="rtl"]) .input-content.label-is-floating ::content .paper-input-label {
+ /* TODO(noms): Figure out why leaving the width at 133% before the animation
+ * actually makes
+ * it wider on the right side, not left side, as you would expect in RTL */
+ width: 100%;
+ -webkit-transform-origin: right top;
+ transform-origin: right top;
+ }
+
+ .input-content.label-is-highlighted ::content label,
+ .input-content.label-is-highlighted ::content .paper-input-label {
+ color: var(--paper-input-container-focus-color, --primary-color);
+
+ @apply(--paper-input-container-label-focus);
+ }
+
+ .input-content.is-invalid ::content label,
+ .input-content.is-invalid ::content .paper-input-label {
+ color: var(--paper-input-container-invalid-color, --error-color);
+ }
+
+ .input-content.label-is-hidden ::content label,
+ .input-content.label-is-hidden ::content .paper-input-label {
+ visibility: hidden;
+ }
+
+ .input-content ::content input,
+ .input-content ::content textarea,
+ .input-content ::content iron-autogrow-textarea,
+ .input-content ::content .paper-input-input {
+ position: relative; /* to make a stacking context */
+ outline: none;
+ box-shadow: none;
+ padding: 0;
+ width: 100%;
+ max-width: 100%;
+ background: transparent;
+ border: none;
+ color: var(--paper-input-container-input-color, --primary-text-color);
+ -webkit-appearance: none;
+ text-align: inherit;
+ vertical-align: bottom;
+
+ @apply(--paper-font-subhead);
+ @apply(--paper-input-container-input);
+ }
+
+ .input-content.focused ::content input,
+ .input-content.focused ::content textarea,
+ .input-content.focused ::content iron-autogrow-textarea,
+ .input-content.focused ::content .paper-input-input {
+ @apply(--paper-input-container-input-focus);
+ }
+
+ .input-content.is-invalid ::content input,
+ .input-content.is-invalid ::content textarea,
+ .input-content.is-invalid ::content iron-autogrow-textarea,
+ .input-content.is-invalid ::content .paper-input-input {
+ @apply(--paper-input-container-input-invalid);
+ }
+
+ .input-content ::content input::-webkit-outer-spin-button,
+ .input-content ::content input::-webkit-inner-spin-button {
+ @apply(--paper-input-container-input-webkit-spinner);
+ }
+
+ ::content [prefix] {
+ @apply(--paper-font-subhead);
+
+ @apply(--paper-input-prefix);
+ @apply(--layout-flex-none);
+ }
+
+ ::content [suffix] {
+ @apply(--paper-font-subhead);
+
+ @apply(--paper-input-suffix);
+ @apply(--layout-flex-none);
+ }
+
+ /* Firefox sets a min-width on the input, which can cause layout issues */
+ .input-content ::content input {
+ min-width: 0;
+ }
+
+ .input-content ::content textarea {
+ resize: none;
+ }
+
+ .add-on-content {
+ position: relative;
+ }
+
+ .add-on-content.is-invalid ::content * {
+ color: var(--paper-input-container-invalid-color, --error-color);
+ }
+
+ .add-on-content.is-highlighted ::content * {
+ color: var(--paper-input-container-focus-color, --primary-color);
+ }
+ </style>
+
+ <template is="dom-if" if="[[!noLabelFloat]]">
+ <div class="floated-label-placeholder" aria-hidden="true">&nbsp;</div>
+ </template>
+
+ <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focused,invalid,_inputHasContent)]]">
+ <content select="[prefix]" id="prefix"></content>
+
+ <div class="label-and-input-container" id="labelAndInputContainer">
+ <content select=":not([add-on]):not([prefix]):not([suffix])"></content>
+ </div>
+
+ <content select="[suffix]"></content>
+ </div>
+
+ <div class$="[[_computeUnderlineClass(focused,invalid)]]">
+ <div class="unfocused-line"></div>
+ <div class="focused-line"></div>
+ </div>
+
+ <div class$="[[_computeAddOnContentClass(focused,invalid)]]">
+ <content id="addOnContent" select="[add-on]"></content>
+ </div>
+ </template>
+</dom-module>
+
+<script>
+ Polymer({
+ is: 'paper-input-container',
+
+ properties: {
+ /**
+ * Set to true to disable the floating label. The label disappears when the input value is
+ * not null.
+ */
+ noLabelFloat: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * Set to true to always float the floating label.
+ */
+ alwaysFloatLabel: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * The attribute to listen for value changes on.
+ */
+ attrForValue: {
+ type: String,
+ value: 'bind-value'
+ },
+
+ /**
+ * Set to true to auto-validate the input value when it changes.
+ */
+ autoValidate: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * True if the input is invalid. This property is set automatically when the input value
+ * changes if auto-validating, or when the `iron-input-validate` event is heard from a child.
+ */
+ invalid: {
+ observer: '_invalidChanged',
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * True if the input has focus.
+ */
+ focused: {
+ readOnly: true,
+ type: Boolean,
+ value: false,
+ notify: true
+ },
+
+ _addons: {
+ type: Array
+ // do not set a default value here intentionally - it will be initialized lazily when a
+ // distributed child is attached, which may occur before configuration for this element
+ // in polyfill.
+ },
+
+ _inputHasContent: {
+ type: Boolean,
+ value: false
+ },
+
+ _inputSelector: {
+ type: String,
+ value: 'input,textarea,.paper-input-input'
+ },
+
+ _boundOnFocus: {
+ type: Function,
+ value: function() {
+ return this._onFocus.bind(this);
+ }
+ },
+
+ _boundOnBlur: {
+ type: Function,
+ value: function() {
+ return this._onBlur.bind(this);
+ }
+ },
+
+ _boundOnInput: {
+ type: Function,
+ value: function() {
+ return this._onInput.bind(this);
+ }
+ },
+
+ _boundValueChanged: {
+ type: Function,
+ value: function() {
+ return this._onValueChanged.bind(this);
+ }
+ }
+ },
+
+ listeners: {
+ 'addon-attached': '_onAddonAttached',
+ 'iron-input-validate': '_onIronInputValidate'
+ },
+
+ get _valueChangedEvent() {
+ return this.attrForValue + '-changed';
+ },
+
+ get _propertyForValue() {
+ return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
+ },
+
+ get _inputElement() {
+ return Polymer.dom(this).querySelector(this._inputSelector);
+ },
+
+ get _inputElementValue() {
+ return this._inputElement[this._propertyForValue] || this._inputElement.value;
+ },
+
+ ready: function() {
+ if (!this._addons) {
+ this._addons = [];
+ }
+ this.addEventListener('focus', this._boundOnFocus, true);
+ this.addEventListener('blur', this._boundOnBlur, true);
+ },
+
+ attached: function() {
+ if (this.attrForValue) {
+ this._inputElement.addEventListener(this._valueChangedEvent, this._boundValueChanged);
+ } else {
+ this.addEventListener('input', this._onInput);
+ }
+
+ // Only validate when attached if the input already has a value.
+ if (this._inputElementValue != '') {
+ this._handleValueAndAutoValidate(this._inputElement);
+ } else {
+ this._handleValue(this._inputElement);
+ }
+ },
+
+ _onAddonAttached: function(event) {
+ if (!this._addons) {
+ this._addons = [];
+ }
+ var target = event.target;
+ if (this._addons.indexOf(target) === -1) {
+ this._addons.push(target);
+ if (this.isAttached) {
+ this._handleValue(this._inputElement);
+ }
+ }
+ },
+
+ _onFocus: function() {
+ this._setFocused(true);
+ },
+
+ _onBlur: function() {
+ this._setFocused(false);
+ this._handleValueAndAutoValidate(this._inputElement);
+ },
+
+ _onInput: function(event) {
+ this._handleValueAndAutoValidate(event.target);
+ },
+
+ _onValueChanged: function(event) {
+ this._handleValueAndAutoValidate(event.target);
+ },
+
+ _handleValue: function(inputElement) {
+ var value = this._inputElementValue;
+
+ // type="number" hack needed because this.value is empty until it's valid
+ if (value || value === 0 || (inputElement.type === 'number' && !inputElement.checkValidity())) {
+ this._inputHasContent = true;
+ } else {
+ this._inputHasContent = false;
+ }
+
+ this.updateAddons({
+ inputElement: inputElement,
+ value: value,
+ invalid: this.invalid
+ });
+ },
+
+ _handleValueAndAutoValidate: function(inputElement) {
+ if (this.autoValidate) {
+ var valid;
+ if (inputElement.validate) {
+ valid = inputElement.validate(this._inputElementValue);
+ } else {
+ valid = inputElement.checkValidity();
+ }
+ this.invalid = !valid;
+ }
+
+ // Call this last to notify the add-ons.
+ this._handleValue(inputElement);
+ },
+
+ _onIronInputValidate: function(event) {
+ this.invalid = this._inputElement.invalid;
+ },
+
+ _invalidChanged: function() {
+ if (this._addons) {
+ this.updateAddons({invalid: this.invalid});
+ }
+ },
+
+ /**
+ * Call this to update the state of add-ons.
+ * @param {Object} state Add-on state.
+ */
+ updateAddons: function(state) {
+ for (var addon, index = 0; addon = this._addons[index]; index++) {
+ addon.update(state);
+ }
+ },
+
+ _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, invalid, _inputHasContent) {
+ var cls = 'input-content';
+ if (!noLabelFloat) {
+ var label = this.querySelector('label');
+
+ if (alwaysFloatLabel || _inputHasContent) {
+ cls += ' label-is-floating';
+ // If the label is floating, ignore any offsets that may have been
+ // applied from a prefix element.
+ this.$.labelAndInputContainer.style.position = 'static';
+
+ if (invalid) {
+ cls += ' is-invalid';
+ } else if (focused) {
+ cls += " label-is-highlighted";
+ }
+ } else {
+ // When the label is not floating, it should overlap the input element.
+ if (label) {
+ this.$.labelAndInputContainer.style.position = 'relative';
+ }
+ if (invalid) {
+ cls += ' is-invalid';
+ }
+ }
+ } else {
+ if (_inputHasContent) {
+ cls += ' label-is-hidden';
+ }
+ if (invalid) {
+ cls += ' is-invalid';
+ }
+ }
+ if (focused) {
+ cls += ' focused';
+ }
+ return cls;
+ },
+
+ _computeUnderlineClass: function(focused, invalid) {
+ var cls = 'underline';
+ if (invalid) {
+ cls += ' is-invalid';
+ } else if (focused) {
+ cls += ' is-highlighted'
+ }
+ return cls;
+ },
+
+ _computeAddOnContentClass: function(focused, invalid) {
+ var cls = 'add-on-content';
+ if (invalid) {
+ cls += ' is-invalid';
+ } else if (focused) {
+ cls += ' is-highlighted'
+ }
+ return cls;
+ }
+ });
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/paper-input-error.html b/catapult/third_party/polymer/components/paper-input/paper-input-error.html
new file mode 100644
index 00000000..645f1e72
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/paper-input-error.html
@@ -0,0 +1,94 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../paper-styles/default-theme.html">
+<link rel="import" href="../paper-styles/typography.html">
+<link rel="import" href="paper-input-addon-behavior.html">
+
+<!--
+`<paper-input-error>` is an error message for use with `<paper-input-container>`. The error is
+displayed when the `<paper-input-container>` is `invalid`.
+
+ <paper-input-container>
+ <input is="iron-input" pattern="[0-9]*">
+ <paper-input-error>Only numbers are allowed!</paper-input-error>
+ </paper-input-container>
+
+### Styling
+
+The following custom properties and mixins are available for styling:
+
+Custom property | Description | Default
+----------------|-------------|----------
+`--paper-input-container-invalid-color` | The foreground color of the error | `--error-color`
+`--paper-input-error` | Mixin applied to the error | `{}`
+-->
+
+<dom-module id="paper-input-error">
+ <template>
+ <style>
+ :host {
+ display: inline-block;
+ visibility: hidden;
+
+ color: var(--paper-input-container-invalid-color, --error-color);
+
+ @apply(--paper-font-caption);
+ @apply(--paper-input-error);
+ position: absolute;
+ left:0;
+ right:0;
+ }
+
+ :host([invalid]) {
+ visibility: visible;
+ };
+ </style>
+
+ <content></content>
+ </template>
+</dom-module>
+
+<script>
+ Polymer({
+ is: 'paper-input-error',
+
+ behaviors: [
+ Polymer.PaperInputAddonBehavior
+ ],
+
+ properties: {
+ /**
+ * True if the error is showing.
+ */
+ invalid: {
+ readOnly: true,
+ reflectToAttribute: true,
+ type: Boolean
+ }
+ },
+
+ /**
+ * This overrides the update function in PaperInputAddonBehavior.
+ * @param {{
+ * inputElement: (Element|undefined),
+ * value: (string|undefined),
+ * invalid: boolean
+ * }} state -
+ * inputElement: The input element.
+ * value: The input value.
+ * invalid: True if the input value is invalid.
+ */
+ update: function(state) {
+ this._setInvalid(state.invalid);
+ }
+ });
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/paper-input.html b/catapult/third_party/polymer/components/paper-input/paper-input.html
new file mode 100644
index 00000000..3eb0024e
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/paper-input.html
@@ -0,0 +1,183 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html">
+<link rel="import" href="../iron-input/iron-input.html">
+<link rel="import" href="paper-input-behavior.html">
+<link rel="import" href="paper-input-char-counter.html">
+<link rel="import" href="paper-input-container.html">
+<link rel="import" href="paper-input-error.html">
+
+<!--
+Material design: [Text fields](https://www.google.com/design/spec/components/text-fields.html)
+
+`<paper-input>` is a single-line text field with Material Design styling.
+
+ <paper-input label="Input label"></paper-input>
+
+It may include an optional error message or character counter.
+
+ <paper-input error-message="Invalid input!" label="Input label"></paper-input>
+ <paper-input char-counter label="Input label"></paper-input>
+
+It can also include custom prefix or suffix elements, which are displayed
+before or after the text input itself. In order for an element to be
+considered as a prefix, it must have the `prefix` attribute (and similarly
+for `suffix`).
+
+ <paper-input label="total">
+ <div prefix>$</div>
+ <paper-icon-button suffix icon="clear"></paper-icon-button>
+ </paper-input>
+
+A `paper-input` can use the native `type=search` or `type=file` features.
+However, since we can't control the native styling of the input (search icon,
+file button, date placeholder, etc.), in these cases the label will be
+automatically floated. The `placeholder` attribute can still be used for
+additional informational text.
+
+ <paper-input label="search!" type="search"
+ placeholder="search for cats" autosave="test" results="5">
+ </paper-input>
+
+See `Polymer.PaperInputBehavior` for more API docs.
+
+### Focus
+
+To focus a paper-input, you can call the native `focus()` method as long as the
+paper input has a tab index.
+
+### Styling
+
+See `Polymer.PaperInputContainer` for a list of custom properties used to
+style this element.
+
+
+@group Paper Elements
+@element paper-input
+@hero hero.svg
+@demo demo/index.html
+-->
+
+<dom-module id="paper-input">
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+
+ :host([focused]) {
+ outline: none;
+ }
+
+ :host([hidden]) {
+ display: none !important;
+ }
+
+ input::-webkit-outer-spin-button,
+ input::-webkit-inner-spin-button {
+ @apply(--paper-input-container-input-webkit-spinner);
+ }
+
+ input::-webkit-clear-button {
+ @apply(--paper-input-container-input-webkit-clear);
+ }
+
+ input::-webkit-input-placeholder {
+ color: var(--paper-input-container-color, --secondary-text-color);
+ }
+
+ input:-moz-placeholder {
+ color: var(--paper-input-container-color, --secondary-text-color);
+ }
+
+ input::-moz-placeholder {
+ color: var(--paper-input-container-color, --secondary-text-color);
+ }
+
+ input::-ms-clear {
+ @apply(--paper-input-container-ms-clear);
+ }
+
+ input:-ms-input-placeholder {
+ color: var(--paper-input-container-color, --secondary-text-color);
+ }
+
+ label {
+ pointer-events: none;
+ }
+ </style>
+
+ <paper-input-container no-label-float="[[noLabelFloat]]" always-float-label="[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]" auto-validate$="[[autoValidate]]" disabled$="[[disabled]]" invalid="[[invalid]]">
+
+ <content select="[prefix]"></content>
+
+ <label hidden$="[[!label]]" aria-hidden="true" for="input">[[label]]</label>
+
+ <input is="iron-input" id="input"
+ aria-labelledby$="[[_ariaLabelledBy]]"
+ aria-describedby$="[[_ariaDescribedBy]]"
+ disabled$="[[disabled]]"
+ title$="[[title]]"
+ bind-value="{{value}}"
+ invalid="{{invalid}}"
+ prevent-invalid-input="[[preventInvalidInput]]"
+ allowed-pattern="[[allowedPattern]]"
+ validator="[[validator]]"
+ type$="[[type]]"
+ pattern$="[[pattern]]"
+ required$="[[required]]"
+ autocomplete$="[[autocomplete]]"
+ autofocus$="[[autofocus]]"
+ inputmode$="[[inputmode]]"
+ minlength$="[[minlength]]"
+ maxlength$="[[maxlength]]"
+ min$="[[min]]"
+ max$="[[max]]"
+ step$="[[step]]"
+ name$="[[name]]"
+ placeholder$="[[placeholder]]"
+ readonly$="[[readonly]]"
+ list$="[[list]]"
+ size$="[[size]]"
+ autocapitalize$="[[autocapitalize]]"
+ autocorrect$="[[autocorrect]]"
+ on-change="_onChange"
+ tabindex$="[[tabindex]]"
+ autosave$="[[autosave]]"
+ results$="[[results]]"
+ accept$="[[accept]]"
+ multiple$="[[multiple]]">
+
+ <content select="[suffix]"></content>
+
+ <template is="dom-if" if="[[errorMessage]]">
+ <paper-input-error aria-live="assertive">[[errorMessage]]</paper-input-error>
+ </template>
+
+ <template is="dom-if" if="[[charCounter]]">
+ <paper-input-char-counter></paper-input-char-counter>
+ </template>
+
+ </paper-input-container>
+ </template>
+</dom-module>
+
+<script>
+ Polymer({
+ is: 'paper-input',
+
+ behaviors: [
+ Polymer.IronFormElementBehavior,
+ Polymer.PaperInputBehavior
+ ]
+ });
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/paper-textarea.html b/catapult/third_party/polymer/components/paper-input/paper-textarea.html
new file mode 100644
index 00000000..cfc06520
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/paper-textarea.html
@@ -0,0 +1,145 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../iron-autogrow-textarea/iron-autogrow-textarea.html">
+<link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html">
+<link rel="import" href="paper-input-behavior.html">
+<link rel="import" href="paper-input-char-counter.html">
+<link rel="import" href="paper-input-container.html">
+<link rel="import" href="paper-input-error.html">
+
+<!--
+`<paper-textarea>` is a multi-line text field with Material Design styling.
+
+ <paper-textarea label="Textarea label"></paper-textarea>
+
+See `Polymer.PaperInputBehavior` for more API docs.
+
+### Validation
+
+Currently only `required` and `maxlength` validation is supported.
+
+### Styling
+
+See `Polymer.PaperInputContainer` for a list of custom properties used to
+style this element.
+-->
+
+<dom-module id="paper-textarea">
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+
+ :host([hidden]) {
+ display: none !important;
+ }
+
+ label {
+ pointer-events: none;
+ }
+ </style>
+
+ <paper-input-container no-label-float$="[[noLabelFloat]]" always-float-label="[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]" auto-validate$="[[autoValidate]]" disabled$="[[disabled]]" invalid="[[invalid]]">
+
+ <label hidden$="[[!label]]" aria-hidden="true">[[label]]</label>
+
+ <iron-autogrow-textarea id="input" class="paper-input-input"
+ bind-value="{{value}}"
+ invalid="{{invalid}}"
+ validator$="[[validator]]"
+ disabled$="[[disabled]]"
+ autocomplete$="[[autocomplete]]"
+ autofocus$="[[autofocus]]"
+ inputmode$="[[inputmode]]"
+ name$="[[name]]"
+ placeholder$="[[placeholder]]"
+ readonly$="[[readonly]]"
+ required$="[[required]]"
+ minlength$="[[minlength]]"
+ maxlength$="[[maxlength]]"
+ autocapitalize$="[[autocapitalize]]"
+ rows$="[[rows]]"
+ max-rows$="[[maxRows]]"
+ on-change="_onChange"></iron-autogrow-textarea>
+
+ <template is="dom-if" if="[[errorMessage]]">
+ <paper-input-error>[[errorMessage]]</paper-input-error>
+ </template>
+
+ <template is="dom-if" if="[[charCounter]]">
+ <paper-input-char-counter></paper-input-char-counter>
+ </template>
+
+ </paper-input-container>
+ </template>
+</dom-module>
+
+<script>
+ Polymer({
+ is: 'paper-textarea',
+
+ behaviors: [
+ Polymer.PaperInputBehavior,
+ Polymer.IronFormElementBehavior
+ ],
+
+ properties: {
+ _ariaLabelledBy: {
+ observer: '_ariaLabelledByChanged',
+ type: String
+ },
+
+ _ariaDescribedBy: {
+ observer: '_ariaDescribedByChanged',
+ type: String
+ },
+
+ /**
+ * The initial number of rows.
+ *
+ * @attribute rows
+ * @type number
+ * @default 1
+ */
+ rows: {
+ type: Number,
+ value: 1
+ },
+
+ /**
+ * The maximum number of rows this element can grow to until it
+ * scrolls. 0 means no maximum.
+ *
+ * @attribute maxRows
+ * @type number
+ * @default 0
+ */
+ maxRows: {
+ type: Number,
+ value: 0
+ }
+ },
+
+ _ariaLabelledByChanged: function(ariaLabelledBy) {
+ this.$.input.textarea.setAttribute('aria-labelledby', ariaLabelledBy);
+ },
+
+ _ariaDescribedByChanged: function(ariaDescribedBy) {
+ this.$.input.textarea.setAttribute('aria-describedby', ariaDescribedBy);
+ },
+
+ get _focusableElement() {
+ return this.$.input.textarea;
+ },
+ });
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/test/index.html b/catapult/third_party/polymer/components/paper-input/test/index.html
new file mode 100644
index 00000000..48aa82fd
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/test/index.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html><!--
+@license
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+--><html><head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
+ <title>paper-input tests</title>
+ <script src="../../web-component-tester/browser.js"></script>
+</head>
+<body>
+ <script>
+ WCT.loadSuites([
+ 'paper-input.html',
+ 'paper-textarea.html',
+ 'paper-input-container.html',
+ 'paper-input-error.html',
+ 'paper-input-char-counter.html',
+ 'paper-input.html?dom=shadow',
+ 'paper-textarea.html?dom=shadow',
+ 'paper-input-container.html?dom=shadow',
+ 'paper-input-error.html?dom=shadow',
+ 'paper-input-char-counter.html?dom=shadow'
+ ]);
+ </script>
+
+
+</body></html>
diff --git a/catapult/third_party/polymer/components/paper-input/test/letters-only.html b/catapult/third_party/polymer/components/paper-input/test/letters-only.html
new file mode 100644
index 00000000..bfc301c3
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/test/letters-only.html
@@ -0,0 +1,30 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+
+<link rel="import" href="../../polymer/polymer.html">
+<link rel="import" href="../../iron-validator-behavior/iron-validator-behavior.html">
+
+<script>
+
+ Polymer({
+
+ is: 'letters-only',
+
+ behaviors: [
+ Polymer.IronValidatorBehavior
+ ],
+
+ validate: function(value) {
+ return !value || value.match(/^[a-zA-Z]*$/) !== null;
+ }
+
+ });
+
+</script>
diff --git a/catapult/third_party/polymer/components/paper-input/test/paper-input-char-counter.html b/catapult/third_party/polymer/components/paper-input/test/paper-input-char-counter.html
new file mode 100644
index 00000000..65d2d140
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/test/paper-input-char-counter.html
@@ -0,0 +1,109 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+
+ <title>paper-input-counter tests</title>
+
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+
+ <script src="../../web-component-tester/browser.js"></script>
+ <script src="../../iron-test-helpers/test-helpers.js"></script>
+
+ <link rel="import" href="../../iron-input/iron-input.html">
+ <link rel="import" href="../paper-input-container.html">
+ <link rel="import" href="../paper-input-char-counter.html">
+ <link rel="import" href="../paper-textarea.html">
+
+</head>
+<body>
+
+ <test-fixture id="counter">
+ <template>
+ <paper-input-container>
+ <label id="l">label</label>
+ <input id="i" value="foobar">
+ <paper-input-char-counter id="c"></paper-input-char-counter>
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="counter-with-max">
+ <template>
+ <paper-input-container>
+ <label id="l">label</label>
+ <input id="i" value="foobar" maxlength="10">
+ <paper-input-char-counter id="c"></paper-input-char-counter>
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="textarea">
+ <template>
+ <paper-textarea char-counter value="foobar"></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="textarea-with-max">
+ <template>
+ <paper-textarea char-counter value="foobar" maxlength="100"></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <script>
+
+ suite('basic', function() {
+
+ test('character counter shows the value length', function() {
+ var container = fixture('counter');
+ var input = Polymer.dom(container).querySelector('#i');
+ var counter = Polymer.dom(container).querySelector('#c');
+ assert.equal(counter._charCounterStr, input.value.length, 'character counter shows input value length');
+ });
+
+ test('character counter shows the value length with maxlength', function() {
+ var container = fixture('counter-with-max');
+ var input = Polymer.dom(container).querySelector('#i');
+ var counter = Polymer.dom(container).querySelector('#c');
+ assert.equal(counter._charCounterStr, input.value.length + '/' + input.maxLength, 'character counter shows input value length and maxLength');
+ });
+
+ test('character counter shows the value length with maxlength', function() {
+ var input = fixture('textarea-with-max');
+ forceXIfStamp(input);
+
+ var counter = Polymer.dom(input.root).querySelector('paper-input-char-counter');
+ assert.ok(counter, 'paper-input-char-counter exists');
+
+ assert.equal(counter._charCounterStr, input.value.length + '/' + input.inputElement.textarea.getAttribute('maxlength'), 'character counter shows input value length and maxLength');
+ });
+
+ test('character counter counts new lines in textareas correctly', function() {
+ var input = fixture('textarea');
+ input.value = 'foo\nbar';
+ forceXIfStamp(input);
+
+ var counter = Polymer.dom(input.root).querySelector('paper-input-char-counter')
+ assert.ok(counter, 'paper-input-char-counter exists');
+
+ assert.equal(counter._charCounterStr, input.value.length, 'character counter shows the value length');
+ });
+
+ });
+
+ </script>
+
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/paper-input/test/paper-input-container.html b/catapult/third_party/polymer/components/paper-input/test/paper-input-container.html
new file mode 100644
index 00000000..6af730d2
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/test/paper-input-container.html
@@ -0,0 +1,333 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+
+ <title>paper-input-container tests</title>
+
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+
+ <script src="../../web-component-tester/browser.js"></script>
+ <script src="../../iron-test-helpers/mock-interactions.js"></script>
+
+ <link rel="import" href="../../iron-input/iron-input.html">
+ <link rel="import" href="../paper-input-container.html">
+ <link rel="import" href="letters-only.html">
+
+</head>
+<body>
+
+ <test-fixture id="basic">
+ <template>
+ <paper-input-container>
+ <label id="l">label</label>
+ <input id="i">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="prefix">
+ <template>
+ <paper-input-container>
+ <div prefix>$</div>
+ <label id="l">label</label>
+ <input is="iron-input" id="i">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="prefix-has-value">
+ <template>
+ <paper-input-container>
+ <div prefix>$</div>
+ <label id="l">label</label>
+ <input is="iron-input" id="i" value="foo">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="has-value">
+ <template>
+ <paper-input-container>
+ <label id="l">label</label>
+ <input id="i" value="value">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="no-float-has-value">
+ <template>
+ <paper-input-container no-label-float>
+ <label id="l">label</label>
+ <input id="i" value="value">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="always-float">
+ <template>
+ <paper-input-container always-float-label>
+ <label id="l">label</label>
+ <input id="i" value="value">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="auto-validate-numbers">
+ <template>
+ <paper-input-container auto-validate>
+ <label id="l">label</label>
+ <input is="iron-input" id="i" pattern="[0-9]*">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="manual-validate-numbers">
+ <template>
+ <paper-input-container>
+ <label id="l">label</label>
+ <input is="iron-input" id="i" pattern="[0-9]*">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="required-validate">
+ <template>
+ <paper-input-container>
+ <label id="l">label</label>
+ <input is="iron-input" id="i" required>
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <letters-only></letters-only>
+
+ <test-fixture id="auto-validate-validator">
+ <template>
+ <paper-input-container auto-validate>
+ <label id="l">label</label>
+ <input is="iron-input" id="i" pattern="[0-9]*" validator="letters-only">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="auto-validate-validator-has-invalid-value">
+ <template>
+ <paper-input-container auto-validate>
+ <label id="l">label</label>
+ <input is="iron-input" id="i" validator="letters-only" value="123123">
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <script>
+
+ function getTransform(node) {
+ var style = getComputedStyle(node);
+ return style.transform || style.webkitTransform;
+ }
+
+ suite('basic', function() {
+ test('can be created imperatively', function() {
+ var container = document.createElement('paper-input-container');
+ var input = document.createElement('input', 'iron-input');
+ input.className = 'paper-input-input';
+ input.id = 'input';
+
+ var label = document.createElement('label');
+ label.innerHTML = 'label';
+
+ Polymer.dom(container).appendChild(label);
+ Polymer.dom(container).appendChild(input);
+
+ document.body.appendChild(container);
+ assert.isOk(container);
+ document.body.removeChild(container);
+ });
+ });
+
+ suite('label position', function() {
+
+ test('label is visible by default', function() {
+ var container = fixture('basic');
+ assert.equal(getComputedStyle(container.querySelector('#l')).visibility, 'visible', 'label has visibility:visible');
+ });
+
+ test('label is floated if value is initialized to not null', function(done) {
+ var container = fixture('has-value');
+ requestAnimationFrame(function() {
+ assert.notEqual(getTransform(container.querySelector('#l')), 'none', 'label has transform');
+ done();
+ });
+ });
+
+ test('label is invisible if no-label-float and value is initialized to not null', function() {
+ var container = fixture('no-float-has-value');
+ assert.equal(getComputedStyle(container.querySelector('#l')).visibility, 'hidden', 'label has visibility:hidden');
+ });
+
+ test('label is floated if always-float-label is true', function() {
+ var container = fixture('always-float');
+ assert.notEqual(getTransform(container.querySelector('#l')), 'none', 'label has transform');
+ });
+
+ test('label is floated correctly with a prefix', function(done) {
+ var container = fixture('prefix');
+ var label = Polymer.dom(container).querySelector('#l');
+ var input = Polymer.dom(container).querySelector('#i');
+
+ // Label is initially visible.
+ assert.equal(getComputedStyle(label).visibility, 'visible', 'label has visibility:visible');
+
+ // After entering text, the label floats, and it is not indented.
+ input.bindValue = 'foobar';
+ requestAnimationFrame(function() {
+ assert.notEqual(getTransform(label), 'none', 'label has transform');
+ assert.equal(label.getBoundingClientRect().left, container.getBoundingClientRect().left);
+ done();
+ });
+ });
+
+ test('label is floated correctly with a prefix and prefilled value', function(done) {
+ var container = fixture('prefix-has-value');
+ var label = Polymer.dom(container).querySelector('#l');
+
+ // The label floats, and it is not indented.
+ requestAnimationFrame(function() {
+ assert.notEqual(getTransform(label), 'none', 'label has transform');
+ assert.equal(label.getBoundingClientRect().left, container.getBoundingClientRect().left);
+ done();
+ });
+ });
+
+ });
+
+ suite('focused styling', function() {
+
+ test('label is colored when input is focused and has value', function(done) {
+ var container = fixture('has-value');
+ var label = Polymer.dom(container).querySelector('#l');
+ var input = Polymer.dom(container).querySelector('#i');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ MockInteractions.focus(input);
+ requestAnimationFrame(function() {
+ assert.isTrue(container.focused, 'focused is true');
+ assert.isTrue(inputContent.classList.contains('label-is-highlighted'), 'label is highlighted when input has focus');
+ done();
+ });
+ });
+
+ test('label is not colored when input is focused and has null value', function(done) {
+ var container = fixture('basic');
+ var label = Polymer.dom(container).querySelector('#l');
+ var input = Polymer.dom(container).querySelector('#i');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ MockInteractions.focus(input);
+ requestAnimationFrame(function() {
+ assert.isFalse(inputContent.classList.contains('label-is-highlighted'), 'label is not highlighted when input has focus and has null value');
+ done();
+ });
+ });
+
+ test('underline is colored when input is focused', function(done) {
+ var container = fixture('basic');
+ var input = Polymer.dom(container).querySelector('#i');
+ var line = Polymer.dom(container.root).querySelector('.underline');
+ assert.isFalse(line.classList.contains('is-highlighted'), 'line is not highlighted when input is not focused');
+ MockInteractions.focus(input);
+ requestAnimationFrame(function() {
+ assert.isTrue(line.classList.contains('is-highlighted'), 'line is highlighted when input is focused');
+ done();
+ });
+ });
+
+ test('focused class added to input content', function(done) {
+ var container = fixture('basic');
+ var input = Polymer.dom(container).querySelector('#i');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ assert.isFalse(inputContent.classList.contains('focused'), 'input content does not have class "focused" when input is not focused');
+ MockInteractions.focus(input);
+ requestAnimationFrame(function() {
+ assert.isTrue(inputContent.classList.contains('focused'), 'input content has class "focused" when input is focused');
+ done();
+ });
+ });
+
+ });
+
+ suite('validation', function() {
+
+ test('styled when the input is set to an invalid value with auto-validate', function() {
+ var container = fixture('auto-validate-numbers');
+ var input = Polymer.dom(container).querySelector('#i');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ var line = Polymer.dom(container.root).querySelector('.underline');
+
+ input.bindValue = 'foobar';
+
+ assert.isTrue(container.invalid, 'invalid is true');
+ assert.isTrue(inputContent.classList.contains('is-invalid'), 'label has invalid styling when input is invalid');
+ assert.isTrue(line.classList.contains('is-invalid'), 'underline has invalid styling when input is invalid');
+ });
+
+ test('styled when the input is set to an invalid value with auto-validate, with validator', function() {
+ var container = fixture('auto-validate-validator');
+ var input = Polymer.dom(container).querySelector('#i');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ var line = Polymer.dom(container.root).querySelector('.underline');
+
+ input.bindValue = '123123';
+
+ assert.isTrue(container.invalid, 'invalid is true');
+ assert.isTrue(inputContent.classList.contains('is-invalid'), 'label has invalid styling when input is invalid');
+ assert.isTrue(line.classList.contains('is-invalid'), 'underline has invalid styling when input is invalid');
+ });
+
+ test('styled when the input is set initially to an invalid value with auto-validate, with validator', function() {
+ var container = fixture('auto-validate-validator-has-invalid-value');
+ assert.isTrue(container.invalid, 'invalid is true');
+ assert.isTrue(Polymer.dom(container.root).querySelector('.underline').classList.contains('is-invalid'), 'underline has is-invalid class');
+ });
+
+ test('styled when the input is set to an invalid value with manual validation', function() {
+ var container = fixture('manual-validate-numbers');
+ var input = Polymer.dom(container).querySelector('#i');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ var line = Polymer.dom(container.root).querySelector('.underline');
+
+ input.bindValue = 'foobar';
+ input.validate();
+
+ assert.isTrue(container.invalid, 'invalid is true');
+ assert.isTrue(inputContent.classList.contains('is-invalid'), 'label has invalid styling when input is invalid');
+ assert.isTrue(line.classList.contains('is-invalid'), 'underline has invalid styling when input is invalid');
+ });
+
+ test('styled when the input is manually validated and required', function() {
+ var container = fixture('required-validate');
+ var input = Polymer.dom(container).querySelector('#i');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ assert.isFalse(container.invalid, 'invalid is false');
+ input.validate();
+ assert.isTrue(container.invalid, 'invalid is true');
+ assert.isTrue(inputContent.classList.contains('is-invalid'), 'input content has is-invalid class');
+ });
+
+ });
+
+ </script>
+
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/paper-input/test/paper-input-error.html b/catapult/third_party/polymer/components/paper-input/test/paper-input-error.html
new file mode 100644
index 00000000..9337a95e
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/test/paper-input-error.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+
+ <title>paper-input-error tests</title>
+
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+ <script src="../../web-component-tester/browser.js"></script>
+
+ <link rel="import" href="../../iron-input/iron-input.html">
+ <link rel="import" href="../paper-input-container.html">
+ <link rel="import" href="../paper-input-error.html">
+
+</head>
+<body>
+
+ <paper-input-container id="container">
+ <input is="iron-input">
+ <paper-input-error>error</paper-input-error>
+ </paper-input-container>
+
+ <test-fixture id="auto-validate-numbers">
+ <template>
+ <paper-input-container auto-validate attr-for-value="bind-value">
+ <label id="l">label</label>
+ <input is="iron-input" id="i" pattern="[0-9]*">
+ <paper-input-error id="e">error</paper-input-error>
+ </paper-input-container>
+ </template>
+ </test-fixture>
+
+ <script>
+
+ suite('basic', function() {
+
+ test('error message only appears when input is invalid', function() {
+ var container = fixture('auto-validate-numbers');
+ var input = Polymer.dom(container).querySelector('#i');
+ var error = Polymer.dom(container).querySelector('#e');
+ assert.equal(getComputedStyle(error).visibility, 'hidden', 'error is visibility:hidden');
+ input.bindValue = 'foobar';
+ assert.notEqual(getComputedStyle(error).visibility, 'hidden', 'error is not visibility:hidden');
+ });
+
+ test('error message add on is registered', function() {
+ var container = document.getElementById('container');
+ assert.isTrue(container._addons && container._addons.length === 1, 'add on is registered');
+ });
+
+ });
+
+ </script>
+
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/paper-input/test/paper-input.html b/catapult/third_party/polymer/components/paper-input/test/paper-input.html
new file mode 100644
index 00000000..77f68c58
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/test/paper-input.html
@@ -0,0 +1,398 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+
+ <title>paper-input tests</title>
+
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+
+ <script src="../../web-component-tester/browser.js"></script>
+ <script src="../../iron-test-helpers/test-helpers.js"></script>
+ <script src="../../iron-test-helpers/mock-interactions.js"></script>
+
+ <link rel="import" href="../paper-input.html">
+ <link rel="import" href="letters-only.html">
+
+</head>
+<body>
+
+ <test-fixture id="basic">
+ <template>
+ <paper-input></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="has-tabindex">
+ <template>
+ <paper-input tabindex="0"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="label">
+ <template>
+ <paper-input label="foo"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="label-has-value">
+ <template>
+ <paper-input label="foo" value="bar"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="error">
+ <template>
+ <paper-input auto-validate pattern="[0-9]*" value="foobar" error-message="error"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="required">
+ <template>
+ <paper-input auto-validate required error-message="error"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="required-no-auto-validate">
+ <template>
+ <paper-input required error-message="error"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="required-char-counter">
+ <template>
+ <paper-input auto-validate char-counter required error-message="error"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="char-counter">
+ <template>
+ <paper-input char-counter value="foobar"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="type-number-char-counter">
+ <template>
+ <paper-input type="number" char-counter value="1138"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="always-float-label">
+ <template>
+ <paper-input always-float-label label="foo"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="placeholder">
+ <template>
+ <paper-input label="foo" placeholder="bar"></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="date">
+ <template>
+ <paper-input label="foo" type="date"></paper-input>
+ </template>
+ </test-fixture>
+
+ <letters-only></letters-only>
+
+ <test-fixture id="validator">
+ <template>
+ <paper-input value="123123" validator="letters-only" auto-validate></paper-input>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="multiple-inputs">
+ <template>
+ <paper-input label="one"></paper-input>
+ <paper-input label="two"></paper-input>
+ <paper-input label="three"></paper-input>
+ <paper-input label="four"></paper-input>
+ </template>
+ </test-fixture>
+
+ <script>
+
+ suite('basic', function() {
+
+ test('setting value sets the input value', function() {
+ var input = fixture('basic');
+ input.value = 'foobar';
+ assert.equal(input.inputElement.value, input.value, 'inputElement.value equals input.value');
+ });
+
+ test('placeholder does not overlap label', function() {
+ var input = fixture('placeholder');
+ assert.equal(input.inputElement.placeholder, input.placeholder, 'inputElement.placeholder equals input.placeholder');
+ assert.equal(input.noLabelFloat, false);
+ var floatingLabel = Polymer.dom(Polymer.dom(input.root).querySelector('paper-input-container').root).querySelector('.label-is-floating');
+ assert.ok(floatingLabel);
+ });
+
+ test('special types autofloat the label', function() {
+ var input = fixture('date');
+ // Browsers that don't support special <input> types like `date` fallback
+ // to `text`, so make sure to only test if type is still preserved after
+ // the element is attached.
+ if (input.inputElement.type === "date") {
+ assert.equal(input.alwaysFloatLabel, true);
+ var floatingLabel = Polymer.dom(Polymer.dom(input.root).querySelector('paper-input-container').root).querySelector('.label-is-floating');
+ assert.ok(floatingLabel);
+ }
+ });
+
+ test('always-float-label attribute works without placeholder', function() {
+ var input = fixture('always-float-label');
+ var container = Polymer.dom(input.root).querySelector('paper-input-container');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ assert.isTrue(inputContent.classList.contains('label-is-floating'), 'label is floating');
+ });
+
+ test('label does not receive pointer events', function() {
+ var input = fixture('always-float-label');
+ var label = Polymer.dom(input.root).querySelector('label');
+ assert.equal(getComputedStyle(label).pointerEvents, 'none');
+ });
+
+ test('error message is displayed', function() {
+ var input = fixture('error');
+ forceXIfStamp(input);
+ var error = Polymer.dom(input.root).querySelector('paper-input-error');
+ assert.ok(error, 'paper-input-error exists');
+ assert.notEqual(getComputedStyle(error).display, 'none', 'error is not display:none');
+ });
+
+ test('empty required input shows error', function() {
+ var input = fixture('required');
+ forceXIfStamp(input);
+ var error = Polymer.dom(input.root).querySelector('paper-input-error');
+ assert.ok(error, 'paper-input-error exists');
+ assert.notEqual(getComputedStyle(error).display, 'none', 'error is not display:none');
+ });
+
+ test('character counter is displayed', function() {
+ var input = fixture('char-counter');
+ forceXIfStamp(input);
+ var counter = Polymer.dom(input.root).querySelector('paper-input-char-counter')
+ assert.ok(counter, 'paper-input-char-counter exists');
+ assert.equal(counter._charCounterStr, input.value.length, 'character counter shows the value length');
+ });
+
+ test('character counter is correct for type=number', function() {
+ var input = fixture('type-number-char-counter');
+ forceXIfStamp(input);
+ var counter = Polymer.dom(input.root).querySelector('paper-input-char-counter')
+ assert.ok(counter, 'paper-input-char-counter exists');
+ assert.equal(counter._charCounterStr, input.value.toString().length, 'character counter shows the value length');
+ });
+
+ test('validator is used', function() {
+ var input = fixture('validator');
+ assert.ok(input.inputElement.invalid, 'input is invalid');
+ });
+
+ test('caret position is preserved', function() {
+ var input = fixture('basic');
+ var ironInput = Polymer.dom(input.root).querySelector('input[is="iron-input"]');
+ input.value = 'nananana';
+ ironInput.selectionStart = 2;
+ ironInput.selectionEnd = 2;
+
+ input.updateValueAndPreserveCaret('nanananabatman');
+
+ assert.equal(ironInput.selectionStart, 2, 'selectionStart is preserved');
+ assert.equal(ironInput.selectionEnd, 2, 'selectionEnd is preserved');
+ });
+
+ test('setting autofocus to true implictly acquires focus', function(done) {
+ var input = fixture('basic');
+ var inputFocusSpy = sinon.spy(input.inputElement, 'focus');
+ window.setTimeout(function() {
+ assert(inputFocusSpy.called);
+ done();
+ }, 50);
+ input.autofocus = true;
+ });
+
+ test('autofocus doesn\'t grab focus if another element already has it', function(done) {
+ var inputs = fixture('multiple-inputs');
+ var inputFocusSpies = inputs.map(function(input) {
+ return sinon.spy(input.inputElement, 'focus');
+ });
+ window.setTimeout(function() {
+ assert(inputFocusSpies[0].called, 'first autofocus input with grabbed focus');
+ assert(!inputFocusSpies[1].called, 'second autofocus input let first input keep focus');
+ done();
+ }, 50);
+ inputs[0].autofocus = true;
+ inputs[1].autofocus = true; // Shouldn't cause focus to change
+ });
+
+ });
+
+ suite('focus/blur events', function() {
+ var input;
+
+ setup(function() {
+ input = fixture('basic');
+ });
+
+ // At the moment, it is very hard to correctly fire exactly
+ // one focus/blur events on a paper-input. This is because
+ // when a paper-input is focused, it needs to focus
+ // its underlying native input, which will also fire a `blur`
+ // event.
+ test('focus events fired on host element', function() {
+ input.addEventListener('focus', function(event) {
+ assert(input.focused, 'input is focused');
+ });
+ MockInteractions.focus(input);
+ });
+
+ test('focus events fired on host element if nested element is focused', function() {
+ input.addEventListener('focus', function(event) {
+ assert(input.focused, 'input is focused');
+ });
+ MockInteractions.focus(input.inputElement);
+ });
+
+ test('blur events fired on host element', function() {
+ MockInteractions.focus(input);
+ input.addEventListener('blur', function(event) {
+ assert(!input.focused, 'input is blurred');
+ });
+ MockInteractions.blur(input);
+ });
+
+ test('blur events fired on host element nested element is blurred', function() {
+ MockInteractions.focus(input);
+ input.addEventListener('blur', function(event) {
+ assert(!input.focused, 'input is blurred');
+ });
+ MockInteractions.blur(input.inputElement);
+ });
+
+ test('focusing then bluring sets the focused attribute correctly', function() {
+ MockInteractions.focus(input);
+ assert(input.focused, 'input is focused');
+ MockInteractions.blur(input);
+ assert(!input.focused, 'input is blurred');
+ MockInteractions.focus(input.inputElement);
+ assert(input.focused, 'input is focused');
+ MockInteractions.blur(input.inputElement);
+ assert(!input.focused, 'input is blurred');
+ });
+
+ test('focusing then bluring with shift-tab removes the focused attribute correctly', function() {
+ MockInteractions.focus(input);
+ assert(input.focused, 'input is focused');
+
+ // Fake a shift-tab induced blur by forcing the flag.
+ input._shiftTabPressed = true;
+ MockInteractions.blur(input.inputElement);
+ assert(!input.focused, 'input is blurred');
+ });
+ });
+
+ suite('focused styling (integration test)', function() {
+
+ test('underline is colored when input is focused', function(done) {
+ var input = fixture('basic');
+ var container = Polymer.dom(input.root).querySelector('paper-input-container');
+ var line = Polymer.dom(container.root).querySelector('.underline');
+ assert.isFalse(line.classList.contains('is-highlighted'), 'line is not highlighted when input is not focused');
+ MockInteractions.focus(input.inputElement);
+ requestAnimationFrame(function() {
+ assert.isTrue(line.classList.contains('is-highlighted'), 'line is highlighted when input is focused');
+ done();
+ });
+ });
+
+ });
+
+ suite('validation', function() {
+
+ test('invalid attribute updated after calling validate()', function() {
+ var input = fixture('required-no-auto-validate');
+ forceXIfStamp(input);
+ input.validate();
+ var error = Polymer.dom(input.root).querySelector('paper-input-error');
+ assert.ok(error, 'paper-input-error exists');
+ assert.notEqual(getComputedStyle(error).display, 'none', 'error is not display:none');
+ assert.isTrue(input.invalid, 'invalid is true');
+ });
+
+ });
+
+ suite('a11y', function() {
+ test('has aria-labelledby, which is monotonically increasing', function() {
+ var inputs = fixture('multiple-inputs');
+
+ // Find the first index of the input in this fixture. Since the label
+ // ids monotonically increase every time a new input is created, and
+ // this fixture isn't the first one in the document, we're going to start
+ // at an ID > 1.
+ var firstLabel = Polymer.dom(inputs[0].root).querySelector('label').id;
+ var index = parseInt(firstLabel.substr(firstLabel.lastIndexOf('-') + 1));
+
+ for (var i = 0; i < inputs.length; i++ ) {
+ var input = inputs[i].inputElement;
+ var label = Polymer.dom(inputs[i].root).querySelector('label').id;
+
+ assert.isTrue(input.hasAttribute('aria-labelledby'));
+ assert.equal(label, 'paper-input-label-' + (index++));
+ assert.equal(input.getAttribute('aria-labelledby'), label);
+ }
+ });
+
+ test('has aria-describedby for error message', function() {
+ var input = fixture('required');
+ forceXIfStamp(input);
+ assert.isTrue(input.inputElement.hasAttribute('aria-describedby'));
+ assert.equal(input.inputElement.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-error').id, 'aria-describedby points to the error message');
+ });
+
+ test('has aria-describedby for character counter', function() {
+ var input = fixture('char-counter');
+ forceXIfStamp(input);
+ assert.isTrue(input.inputElement.hasAttribute('aria-describedby'));
+ assert.equal(input.inputElement.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-char-counter').id, 'aria-describedby points to the character counter');
+ });
+
+ test('has aria-describedby for character counter and error', function() {
+ var input = fixture('required-char-counter');
+ forceXIfStamp(input);
+ assert.isTrue(input.inputElement.hasAttribute('aria-describedby'));
+ assert.equal(input.inputElement.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-error').id + ' ' + Polymer.dom(input.root).querySelector('paper-input-char-counter').id, 'aria-describedby points to the error message and character counter');
+ });
+
+ test('focus an input with tabindex', function(done) {
+ var input = fixture('has-tabindex');
+ flush(function() {
+ MockInteractions.focus(input);
+ flush(function() {
+ assert.equal(input.shadowRoot ? input.shadowRoot.activeElement :
+ document.activeElement, input._focusableElement);
+ done();
+ });
+ });
+ });
+ });
+
+ </script>
+
+</body>
+</html>
diff --git a/catapult/third_party/polymer/components/paper-input/test/paper-textarea.html b/catapult/third_party/polymer/components/paper-input/test/paper-textarea.html
new file mode 100644
index 00000000..f69e4ee7
--- /dev/null
+++ b/catapult/third_party/polymer/components/paper-input/test/paper-textarea.html
@@ -0,0 +1,233 @@
+<!doctype html>
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+-->
+<html>
+<head>
+
+ <title>paper-textarea tests</title>
+
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
+
+ <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
+
+ <script src="../../web-component-tester/browser.js"></script>
+ <script src="../../iron-test-helpers/test-helpers.js"></script>
+ <script src="../../iron-test-helpers/mock-interactions.js"></script>
+
+ <link rel="import" href="../paper-textarea.html">
+</head>
+<body>
+
+ <test-fixture id="basic">
+ <template>
+ <paper-textarea></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="label">
+ <template>
+ <paper-textarea label="foo"></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="char-counter">
+ <template>
+ <paper-textarea char-counter></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="required">
+ <template>
+ <paper-textarea auto-validate required error-message="error"></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="required-char-counter">
+ <template>
+ <paper-textarea auto-validate char-counter required error-message="error"></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <test-fixture id="always-float-label">
+ <template>
+ <paper-textarea always-float-label label="label"></paper-textarea>
+ </template>
+ </test-fixture>
+
+ <script>
+
+ suite('basic', function() {
+
+ test('setting value sets the input value', function() {
+ var input = fixture('basic');
+ input.value = 'foobar';
+ assert.equal(input.inputElement.bindValue, input.value, 'inputElement value equals input.value');
+ });
+
+ test('empty required input shows error', function() {
+ var input = fixture('required');
+ forceXIfStamp(input);
+ var error = Polymer.dom(input.root).querySelector('paper-input-error');
+ assert.ok(error, 'paper-input-error exists');
+ assert.notEqual(getComputedStyle(error).display, 'none', 'error is not display:none');
+ });
+
+ test('caret position is preserved', function() {
+ var input = fixture('basic');
+ var ironTextarea = Polymer.dom(input.root).querySelector('iron-autogrow-textarea');
+ input.value = 'nananana';
+ ironTextarea.selectionStart = 2;
+ ironTextarea.selectionEnd = 2;
+
+ input.updateValueAndPreserveCaret('nanananabatman');
+
+ assert.equal(ironTextarea.selectionStart, 2, 'selectionStart is preserved');
+ assert.equal(ironTextarea.selectionEnd, 2, 'selectionEnd is preserved');
+ });
+
+ test('input attributes are bound to textarea', function() {
+ var input = fixture('basic');
+ var attrs = {
+ 'autocomplete': 'true',
+ 'autofocus': true,
+ 'inputmode': 'number',
+ 'name': 'foo',
+ 'placeholder': 'bar',
+ 'readonly': true,
+ 'required': true,
+ 'maxlength': 3
+ };
+ for (var attr in attrs) {
+ input[attr] = attrs[attr];
+ }
+ for (var attr in attrs) {
+ var inputAttr = input.inputElement.getAttribute(attr);
+ if (typeof attrs[attr] === 'boolean') {
+ assert.equal(inputAttr !== null, attrs[attr], 'attribute "' + attr + '" is equal to property (' + attrs[attr] + ', ' + inputAttr !== null + ')');
+ } else {
+ assert.equal(inputAttr, attrs[attr], 'attribute "' + attr + '" is equal to property (' + attrs[attr] + ', ' + inputAttr + ')');
+ }
+ }
+ });
+
+ test('always-float-label attribute works', function() {
+ var input = fixture('always-float-label');
+ var container = Polymer.dom(input.root).querySelector('paper-input-container');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ assert.isTrue(inputContent.classList.contains('label-is-floating'), 'label is floating');
+ });
+
+ test('label does not receive pointer events', function() {
+ var input = fixture('always-float-label');
+ var label = Polymer.dom(input.root).querySelector('label');
+ assert.equal(getComputedStyle(label).pointerEvents, 'none');
+ });
+
+ test('no extra space between input and underline', function() {
+ var input = fixture('label');
+ var container = Polymer.dom(input.root).querySelector('paper-input-container');
+ var inputContent = Polymer.dom(container.root).querySelector('.input-content');
+ var ironTextarea = Polymer.dom(input.root).querySelector('iron-autogrow-textarea');
+ assert.equal(inputContent.clientHeight,ironTextarea.clientHeight, 'container and textarea are same height');
+ });
+ });
+
+ suite('focus/blur events', function() {
+ var input;
+
+ setup(function() {
+ input = fixture('basic');
+ });
+
+ // At the moment, it is very hard to correctly fire exactly
+ // one focus/blur events on a paper-textarea. This is because
+ // when a paper-textarea is focused, it needs to focus
+ // its underlying native textarea, which will also fire a `blur`
+ // event.
+ test('focus events fired on host element', function() {
+ input.addEventListener('focus', function(event) {
+ assert(input.focused, 'input is focused');
+ });
+ MockInteractions.focus(input);
+ });
+
+ test('focus events fired on host element if nested element is focused', function() {
+ input.addEventListener('focus', function(event) {
+ assert(input.focused, 'input is focused');
+ });
+ MockInteractions.focus(input.inputElement.textarea);
+ });
+
+ test('blur events fired on host element', function() {
+ MockInteractions.focus(input);
+ input.addEventListener('blur', function(event) {
+ assert(!input.focused, 'input is blurred');
+ });
+ MockInteractions.blur(input);
+ });
+
+ test('blur events fired on host element nested element is blurred', function() {
+ MockInteractions.focus(input);
+ input.addEventListener('blur', function(event) {
+ assert(!input.focused, 'input is blurred');
+ });
+ MockInteractions.blur(input.inputElement.textarea);
+ });
+
+ test('focusing then bluring sets the focused attribute correctly', function() {
+ MockInteractions.focus(input);
+ assert(input.focused, 'input is focused');
+ MockInteractions.blur(input);
+ assert(!input.focused, 'input is blurred');
+ MockInteractions.focus(input.inputElement.textarea);
+ assert(input.focused, 'input is focused');
+ MockInteractions.blur(input.inputElement.textarea);
+ assert(!input.focused, 'input is blurred');
+ });
+ });
+
+ suite('a11y', function() {
+
+ test('has aria-labelledby', function() {
+ var input = fixture('label');
+ assert.isTrue(input.inputElement.textarea.hasAttribute('aria-labelledby'))
+ assert.equal(input.inputElement.textarea.getAttribute('aria-labelledby'), Polymer.dom(input.root).querySelector('label').id, 'aria-labelledby points to the label');
+ });
+
+ test('has aria-describedby for error message', function() {
+ var input = fixture('required');
+ forceXIfStamp(input);
+ assert.isTrue(input.inputElement.textarea.hasAttribute('aria-describedby'));
+ assert.equal(input.inputElement.textarea.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-error').id, 'aria-describedby points to the error message');
+ });
+
+ test('has aria-describedby for character counter', function() {
+ var input = fixture('char-counter');
+ forceXIfStamp(input);
+ assert.isTrue(input.inputElement.textarea.hasAttribute('aria-describedby'));
+ assert.equal(input.inputElement.textarea.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-char-counter').id, 'aria-describedby points to the character counter');
+ });
+
+ test('has aria-describedby for character counter and error', function() {
+ var input = fixture('required-char-counter');
+ forceXIfStamp(input);
+ assert.isTrue(input.inputElement.textarea.hasAttribute('aria-describedby'));
+ assert.equal(input.inputElement.textarea.getAttribute('aria-describedby'), Polymer.dom(input.root).querySelector('paper-input-error').id + ' ' + Polymer.dom(input.root).querySelector('paper-input-char-counter').id, 'aria-describedby points to the error message and character counter');
+ });
+
+ });
+
+
+ </script>
+
+</body>
+</html>