Index: third_party/polymer/v0_8/components/paper-input/paper-input-container.html |
diff --git a/third_party/polymer/v0_8/components/paper-input/paper-input-container.html b/third_party/polymer/v0_8/components/paper-input/paper-input-container.html |
index 3137d6b2396091388317064e7b75a5078cb32adf..18935c153b5bb152d4dcff26dca4c8c23404615f 100644 |
--- a/third_party/polymer/v0_8/components/paper-input/paper-input-container.html |
+++ b/third_party/polymer/v0_8/components/paper-input/paper-input-container.html |
@@ -11,34 +11,64 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN |
<link rel="import" href="../polymer/polymer.html"> |
<link rel="import" href="../paper-styles/paper-styles.html"> |
-<style is="x-style"> |
+<!-- |
+`<paper-input-container>` is a container for a `<label>`, an `<input is="iron-input">` or |
+`<iron-autogrow-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-font: var(--paper-font-subhead); |
- --paper-input-container-floating-label-font: var(--paper-font-caption); |
- --paper-input-container-add-on-font: var(--paper-font-caption); |
+ <paper-input-container> |
+ <label>Your name</label> |
+ <input is="iron-input"> |
+ </paper-input-container> |
- --paper-input-container-focus-color: var(--default-primary-color); |
- --paper-input-container-color: var(--secondary-text-color); |
- --paper-input-container-invalid-color: var(--google-red-500); |
- --paper-input-container-input-color: var(--primary-text-color); |
+### 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. |
-</style> |
+### Using a custom input element |
-<!-- |
-`<paper-input-container>` wraps an `<input>` and `<label>` element, decorating |
-them following the [Material Design spec](http://www.google.com/design/spec/components/text-fields.html#text-fields-single-line-text-field) |
+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 validatble. |
-For example: |
- |
- <paper-input-container> |
- <label>email address</label> |
- <input type="email"> |
+ <paper-input-container attr-for-value="ssn-value"> |
+ <label>Social security number</label> |
+ <ssn-input class="paper-input-input"></ssn-input> |
</paper-input-container> |
+### 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. |
+ |
+### 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 | `--default-primary-color` |
+`--paper-input-container-invalid-color` | Label and underline color when the input is focused | `--google-red-500` |
+`--paper-input-container-input-color` | Input foreground color | `--primary-text-color` |
+`--paper-input-container` | Mixin applied to the container | `{}` |
+`--paper-input-container-label` | Mixin applied to the label | `{}` |
+`--paper-input-container-input` | Mixin applied to the input | `{}` |
+ |
+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"> |
@@ -48,7 +78,11 @@ For example: |
display: block; |
padding: 8px 0; |
- --mixin(--paper-input-container); |
+ @apply(--paper-input-container); |
+ } |
+ |
+ :host[inline] { |
+ display: inline-block; |
} |
:host([disabled]) { |
@@ -57,7 +91,11 @@ For example: |
} |
.floated-label-placeholder { |
- mixin(--paper-input-container-label-font); |
+ @apply(--paper-font-caption); |
+ } |
+ |
+ .underline { |
+ position: relative; |
} |
.focused-line { |
@@ -68,7 +106,7 @@ For example: |
-webkit-transform: scale3d(0,1,1); |
transform: scale3d(0,1,1); |
- background: var(--paper-input-container-focus-color); |
+ background: var(--paper-input-container-focus-color, --default-primary-color); |
} |
.is-highlighted .focused-line { |
@@ -77,31 +115,35 @@ For example: |
-webkit-transition: -webkit-transform 0.25s; |
transition: transform 0.25s; |
- mixin(--paper-transition-easing); |
+ @apply(--paper-transition-easing); |
} |
.is-invalid .focused-line { |
- background: var(--paper-input-container-invalid-color); |
+ background: var(--paper-input-container-invalid-color, --google-red-500); |
-webkit-transform: none; |
transform: none; |
-webkit-transition: -webkit-transform 0.25s; |
transition: transform 0.25s; |
- mixin(--paper-transition-easing); |
+ @apply(--paper-transition-easing); |
} |
.unfocused-line { |
height: 1px; |
- background: var(--paper-input-container-color); |
+ background: var(--paper-input-container-color, --secondary-text-color); |
} |
:host([disabled]) .unfocused-line { |
border-bottom: 1px dashed; |
- border-color: var(--paper-input-container-color); |
+ border-color: var(--paper-input-container-color, --secondary-text-color); |
background: transparent; |
} |
+ .input-content { |
+ position: relative; |
+ } |
+ |
.input-content ::content label, |
.input-content ::content .paper-input-label { |
position: absolute; |
@@ -109,11 +151,10 @@ For example: |
right: 0; |
left: 0; |
font: inherit; |
- color: var(--paper-input-container-color); |
- |
- mixin(--paper-input-container-font); |
+ color: var(--paper-input-container-color, --secondary-text-color); |
- mixin(--paper-input-container-label); |
+ @apply(--paper-font-subhead); |
+ @apply(--paper-input-container-label); |
} |
.input-content.label-is-floating ::content label, |
@@ -125,17 +166,17 @@ For example: |
-webkit-transition: -webkit-transform 0.25s; |
transition: transform 0.25s; |
- mixin(--paper-transition-easing); |
+ @apply(--paper-transition-easing); |
} |
.input-content.label-is-highlighted ::content label, |
.input-content.label-is-highlighted ::content .paper-input-label { |
- color: var(--paper-input-container-focus-color); |
+ color: var(--paper-input-container-focus-color, --default-primary-color); |
} |
.input-content.is-invalid ::content label, |
.input-content.is-invalid ::content .paper-input-label { |
- color: var(--paper-input-container-invalid-color); |
+ color: var(--paper-input-container-invalid-color, --google-red-500); |
} |
.input-content.label-is-hidden ::content label, |
@@ -145,24 +186,24 @@ For example: |
.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; |
- color: var(--paper-input-container-input-color); |
- |
- mixin(--paper-input-container-floating-label-font); |
- } |
- |
- .input-content ::content input, |
- .input-content ::content textarea { |
+ box-shadow: none; |
padding: 0; |
width: 100%; |
background: transparent; |
border: none; |
+ color: var(--paper-input-container-input-color, --primary-text-color); |
- mixin(--paper-input-container-font); |
+ @apply(--paper-font-subhead); |
+ @apply(--paper-input-container-input); |
+ } |
- mixin(--paper-input-container-input); |
+ /* Firefox sets a min-width on the input, which can cause layout issues */ |
+ .input-content ::content input { |
+ min-width: 0; |
} |
.input-content ::content textarea { |
@@ -170,36 +211,31 @@ For example: |
} |
.add-on-content.is-invalid ::content * { |
- color: var(--paper-input-container-invalid-color); |
+ color: var(--paper-input-container-invalid-color, --google-red-500); |
} |
.add-on-content.is-highlighted ::content * { |
- color: var(--paper-input-container-focus-color); |
- } |
- |
- .input-content, |
- .underline { |
- position: relative; |
+ color: var(--paper-input-container-focus-color, --default-primary-color); |
} |
</style> |
<template> |
- <template is="x-if" if="[[!noLabelFloat]]"> |
+ <template is="dom-if" if="[[!noLabelFloat]]"> |
<div class="floated-label-placeholder"> </div> |
</template> |
- <div class$="[[_computeInputContentClass(noLabelFloat,focused,_inputHasContent,_inputIsInvalid)]]"> |
+ <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focused,invalid,_inputHasContent)]]"> |
<content select=":not([add-on])"></content> |
</div> |
- <div class$="[[_computeUnderlineClass(focused,_inputIsInvalid)]]"> |
+ <div class$="[[_computeUnderlineClass(focused,invalid)]]"> |
<div class="unfocused-line fit"></div> |
<div class="focused-line fit"></div> |
</div> |
- <div class$="[[_computeAddOnContentClass(focused,_inputIsInvalid)]]"> |
+ <div class$="[[_computeAddOnContentClass(focused,invalid)]]"> |
<content id="addOnContent" select="[add-on]"></content> |
</div> |
@@ -214,12 +250,11 @@ For example: |
is: 'paper-input-container', |
- enableCustomStyleProperties: true, |
- |
properties: { |
/** |
- * Set to true to disable the floating label. |
+ * Set to true to disable the floating label. The label disappears when the input value is |
+ * not null. |
*/ |
noLabelFloat: { |
type: Boolean, |
@@ -227,6 +262,14 @@ For example: |
}, |
/** |
+ * Set to true to always float the floating label. |
+ */ |
+ alwaysFloatLabel: { |
+ type: Boolean, |
+ value: false |
+ }, |
+ |
+ /** |
* The attribute to listen for value changes on. |
*/ |
attrForValue: { |
@@ -235,7 +278,7 @@ For example: |
}, |
/** |
- * Set to true to auto-validate the input value. |
+ * Set to true to auto-validate the input value when it changes. |
*/ |
autoValidate: { |
type: Boolean, |
@@ -243,6 +286,16 @@ For example: |
}, |
/** |
+ * True if the input is invalid. This property is set automatically when the input value |
+ * changes if auto-validating, or when the `iron-input-valid` event is heard from a child. |
+ */ |
+ invalid: { |
+ observer: '_invalidChanged', |
+ type: Boolean, |
+ value: false |
+ }, |
+ |
+ /** |
* True if the input has focus. |
*/ |
focused: { |
@@ -263,11 +316,6 @@ For example: |
value: false |
}, |
- _inputIsInvalid: { |
- type: Boolean, |
- value: false |
- }, |
- |
_inputSelector: { |
type: String, |
value: 'input,textarea,.paper-input-input' |
@@ -287,6 +335,13 @@ For example: |
} |
}, |
+ _boundOnInput: { |
+ type: Function, |
+ value: function() { |
+ this._onInput.bind(this) |
+ } |
+ }, |
+ |
_boundValueChanged: { |
type: Function, |
value: function() { |
@@ -298,7 +353,7 @@ For example: |
listeners: { |
'addon-attached': '_onAddonAttached', |
- 'input': '_onInput' |
+ 'iron-input-validate': '_onIronInputValidate' |
}, |
get _valueChangedEvent() { |
@@ -316,16 +371,20 @@ For example: |
ready: function() { |
this.addEventListener('focus', this._boundOnFocus, true); |
this.addEventListener('blur', this._boundOnBlur, true); |
- this.addEventListener(this._valueChangedEvent, this._boundValueChanged, true); |
+ if (this.attrForValue) { |
+ this._inputElement.addEventListener(this._valueChangedEvent, this._boundValueChanged); |
+ } else { |
+ this.addEventListener('input', this._onInput); |
+ } |
}, |
attached: function() { |
- this._handleInput(this._inputElement); |
+ this._handleValue(this._inputElement); |
}, |
_onAddonAttached: function(event) { |
this._addons.push(event.target); |
- this._handleInput(this._inputElement); |
+ this._handleValue(this._inputElement); |
}, |
_onFocus: function() { |
@@ -337,43 +396,66 @@ For example: |
}, |
_onInput: function(event) { |
- this._handleInput(event.target); |
+ this._handleValue(event.target); |
}, |
_onValueChanged: function(event) { |
- this._handleInput(event.target); |
+ this._handleValue(event.target); |
}, |
- _handleInput: function(inputElement) { |
+ _handleValue: function(inputElement) { |
var value = inputElement[this._propertyForValue] || inputElement.value; |
- var valid = inputElement.checkValidity(); |
+ |
+ if (this.autoValidate) { |
+ var valid; |
+ if (inputElement.validate) { |
+ valid = inputElement.validate(value); |
+ } else { |
+ valid = inputElement.checkValidity(); |
+ } |
+ this.invalid = !valid; |
+ } |
// type="number" hack needed because this.value is empty until it's valid |
- if (value || inputElement.type === 'number' && !valid) { |
+ if (value || (inputElement.type === 'number' && !inputElement.checkValidity())) { |
this._inputHasContent = true; |
} else { |
this._inputHasContent = false; |
} |
- if (this.autoValidate) { |
- this._inputIsInvalid = !valid; |
+ this.updateAddons({ |
+ inputElement: inputElement, |
+ value: value, |
+ invalid: this.invalid |
+ }); |
+ }, |
+ |
+ _onIronInputValidate: function(event) { |
+ this.invalid = this._inputElement.invalid; |
+ }, |
+ |
+ _invalidChanged: function() { |
+ if (this._addons) { |
+ this.updateAddons({invalid: this.invalid}); |
} |
+ }, |
- // notify add-ons |
- for (var addon, i = 0; addon = this._addons[i]; i++) { |
- // need to set all of these, or call method... thanks input type="number"! |
- addon.inputElement = inputElement; |
- addon.value = value; |
- addon.invalid = !valid; |
+ /** |
+ * 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, focused, _inputHasContent, _inputIsInvalid) { |
+ _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, invalid, _inputHasContent) { |
var cls = 'input-content'; |
if (!noLabelFloat) { |
- if (_inputHasContent) { |
+ if (alwaysFloatLabel || _inputHasContent) { |
cls += ' label-is-floating'; |
- if (_inputIsInvalid) { |
+ if (invalid) { |
cls += ' is-invalid'; |
} else if (focused) { |
cls += " label-is-highlighted"; |
@@ -387,9 +469,9 @@ For example: |
return cls; |
}, |
- _computeUnderlineClass: function(focused, _inputIsInvalid) { |
+ _computeUnderlineClass: function(focused, invalid) { |
var cls = 'underline'; |
- if (_inputIsInvalid) { |
+ if (invalid) { |
cls += ' is-invalid'; |
} else if (focused) { |
cls += ' is-highlighted' |
@@ -397,9 +479,9 @@ For example: |
return cls; |
}, |
- _computeAddOnContentClass: function(focused, _inputIsInvalid) { |
+ _computeAddOnContentClass: function(focused, invalid) { |
var cls = 'add-on-content'; |
- if (_inputIsInvalid) { |
+ if (invalid) { |
cls += ' is-invalid'; |
} else if (focused) { |
cls += ' is-highlighted' |