3 is: 'paper-input-container',
7 * Set to true to disable the floating label. The label disappears when the input value is
16 * Set to true to always float the floating label.
24 * The attribute to listen for value changes on.
32 * Set to true to auto-validate the input value when it changes.
40 * True if the input is invalid. This property is set automatically when the input value
41 * changes if auto-validating, or when the `iron-input-valid` event is heard from a child.
44 observer: '_invalidChanged',
50 * True if the input has focus.
61 // do not set a default value here intentionally - it will be initialized lazily when a
62 // distributed child is attached, which may occur before configuration for this element
73 value: 'input,textarea,.paper-input-input'
79 return this._onFocus.bind(this);
86 return this._onBlur.bind(this);
93 return this._onInput.bind(this);
100 return this._onValueChanged.bind(this);
106 'addon-attached': '_onAddonAttached',
107 'iron-input-validate': '_onIronInputValidate'
110 get _valueChangedEvent() {
111 return this.attrForValue + '-changed';
114 get _propertyForValue() {
115 return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
118 get _inputElement() {
119 return Polymer.dom(this).querySelector(this._inputSelector);
122 get _inputElementValue() {
123 return this._inputElement[this._propertyForValue] || this._inputElement.value;
130 this.addEventListener('focus', this._boundOnFocus, true);
131 this.addEventListener('blur', this._boundOnBlur, true);
132 if (this.attrForValue) {
133 this._inputElement.addEventListener(this._valueChangedEvent, this._boundValueChanged);
135 this.addEventListener('input', this._onInput);
139 attached: function() {
140 // Only validate when attached if the input already has a value.
141 if (this._inputElementValue != '') {
142 this._handleValueAndAutoValidate(this._inputElement);
144 this._handleValue(this._inputElement);
148 _onAddonAttached: function(event) {
152 var target = event.target;
153 if (this._addons.indexOf(target) === -1) {
154 this._addons.push(target);
155 if (this.isAttached) {
156 this._handleValue(this._inputElement);
161 _onFocus: function() {
162 this._setFocused(true);
165 _onBlur: function() {
166 this._setFocused(false);
167 this._handleValueAndAutoValidate(this._inputElement);
170 _onInput: function(event) {
171 this._handleValueAndAutoValidate(event.target);
174 _onValueChanged: function(event) {
175 this._handleValueAndAutoValidate(event.target);
178 _handleValue: function(inputElement) {
179 var value = this._inputElementValue;
181 // type="number" hack needed because this.value is empty until it's valid
182 if (value || value === 0 || (inputElement.type === 'number' && !inputElement.checkValidity())) {
183 this._inputHasContent = true;
185 this._inputHasContent = false;
189 inputElement: inputElement,
191 invalid: this.invalid
195 _handleValueAndAutoValidate: function(inputElement) {
196 if (this.autoValidate) {
198 if (inputElement.validate) {
199 valid = inputElement.validate(this._inputElementValue);
201 valid = inputElement.checkValidity();
203 this.invalid = !valid;
206 // Call this last to notify the add-ons.
207 this._handleValue(inputElement);
210 _onIronInputValidate: function(event) {
211 this.invalid = this._inputElement.invalid;
214 _invalidChanged: function() {
216 this.updateAddons({invalid: this.invalid});
221 * Call this to update the state of add-ons.
222 * @param {Object} state Add-on state.
224 updateAddons: function(state) {
225 for (var addon, index = 0; addon = this._addons[index]; index++) {
230 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, invalid, _inputHasContent) {
231 var cls = 'input-content';
233 var label = this.querySelector('label');
235 if (alwaysFloatLabel || _inputHasContent) {
236 cls += ' label-is-floating';
238 cls += ' is-invalid';
239 } else if (focused) {
240 cls += " label-is-highlighted";
242 // The label might have a horizontal offset if a prefix element exists
243 // which needs to be undone when displayed as a floating label.
244 if (this.$.prefix && label && label.offsetParent &&
245 Polymer.dom(this.$.prefix).getDistributedNodes().length > 0) {
246 label.style.left = -label.offsetParent.offsetLeft + 'px';
249 // When the label is not floating, it should overlap the input element.
251 label.style.left = 0;
255 if (_inputHasContent) {
256 cls += ' label-is-hidden';
262 _computeUnderlineClass: function(focused, invalid) {
263 var cls = 'underline';
265 cls += ' is-invalid';
266 } else if (focused) {
267 cls += ' is-highlighted'
272 _computeAddOnContentClass: function(focused, invalid) {
273 var cls = 'add-on-content';
275 cls += ' is-invalid';
276 } else if (focused) {
277 cls += ' is-highlighted'