(function() { var paperInput = CoreStyle.g.paperInput = CoreStyle.g.paperInput || {}; paperInput.focusedColor = '#4059a9'; paperInput.invalidColor = '#d34336'; Polymer('paper-input', { /** * The label for this input. It normally appears as grey text inside * the text input and disappears once the user enters text. * * @attribute label * @type string * @default '' */ label: '', /** * If true, the label will "float" above the text input once the * user enters text instead of disappearing. * * @attribute floatingLabel * @type boolean * @default false */ floatingLabel: false, /** * (multiline only) If set to a non-zero value, the height of this * text input will grow with the value changes until it is maxRows * rows tall. If the maximum size does not fit the value, the text * input will scroll internally. * * @attribute maxRows * @type number * @default 0 */ maxRows: 0, /** * The message to display if the input value fails validation. If this * is unset or the empty string, a default message is displayed depending * on the type of validation error. * * @attribute error * @type string */ error: '', focused: false, pressed: false, attached: function() { if (this.multiline) { this.resizeInput(); window.requestAnimationFrame(function() { this.$.underlineContainer.classList.add('animating'); }.bind(this)); } }, resizeInput: function() { var height = this.$.inputClone.getBoundingClientRect().height; var bounded = this.maxRows > 0 || this.rows > 0; if (bounded) { var minHeight = this.$.minInputHeight.getBoundingClientRect().height; var maxHeight = this.$.maxInputHeight.getBoundingClientRect().height; height = Math.max(minHeight, Math.min(height, maxHeight)); } this.$.inputContainer.style.height = height + 'px'; this.$.underlineContainer.style.top = height + 'px'; }, prepareLabelTransform: function() { var toRect = this.$.floatedLabelSpan.getBoundingClientRect(); var fromRect = this.$.labelSpan.getBoundingClientRect(); if (toRect.width !== 0) { this.$.label.cachedTransform = 'scale(' + (toRect.width / fromRect.width) + ') ' + 'translateY(' + (toRect.bottom - fromRect.bottom) + 'px)'; } }, toggleLabel: function(force) { var v = force !== undefined ? force : this.inputValue; if (!this.floatingLabel) { this.$.label.classList.toggle('hidden', v); } if (this.floatingLabel && !this.focused) { this.$.label.classList.toggle('hidden', v); this.$.floatedLabel.classList.toggle('hidden', !v); } }, rowsChanged: function() { if (this.multiline && !isNaN(parseInt(this.rows))) { this.$.minInputHeight.innerHTML = ''; for (var i = 0; i < this.rows; i++) { this.$.minInputHeight.appendChild(document.createElement('br')); } this.resizeInput(); } }, maxRowsChanged: function() { if (this.multiline && !isNaN(parseInt(this.maxRows))) { this.$.maxInputHeight.innerHTML = ''; for (var i = 0; i < this.maxRows; i++) { this.$.maxInputHeight.appendChild(document.createElement('br')); } this.resizeInput(); } }, inputValueChanged: function() { this.super(); if (this.multiline) { var escaped = this.inputValue.replace(/\n/gm, '<br>'); if (!escaped || escaped.lastIndexOf('<br>') === escaped.length - 4) { escaped += ' '; } this.$.inputCloneSpan.innerHTML = escaped; this.resizeInput(); } this.toggleLabel(); }, labelChanged: function() { if (this.floatingLabel && this.$.floatedLabel && this.$.label) { // If the element is created programmatically, labelChanged is called before // binding. Run the measuring code in async so the DOM is ready. this.async(function() { this.prepareLabelTransform(); }); } }, placeholderChanged: function() { this.label = this.placeholder; }, inputFocusAction: function() { if (!this.pressed) { if (this.floatingLabel) { this.$.floatedLabel.classList.remove('hidden'); this.$.floatedLabel.classList.add('focused'); this.$.floatedLabel.classList.add('focusedColor'); } this.$.label.classList.add('hidden'); this.$.underlineHighlight.classList.add('focused'); this.$.caret.classList.add('focused'); this.super(arguments); } this.focused = true; }, shouldFloatLabel: function() { // if type = number, the input value is the empty string until a valid number // is entered so we must do some hacks here return this.inputValue || (this.type === 'number' && !this.validity.valid); }, inputBlurAction: function() { this.super(arguments); this.$.underlineHighlight.classList.remove('focused'); this.$.caret.classList.remove('focused'); if (this.floatingLabel) { this.$.floatedLabel.classList.remove('focused'); this.$.floatedLabel.classList.remove('focusedColor'); if (!this.shouldFloatLabel()) { this.$.floatedLabel.classList.add('hidden'); } } // type = number hack. see core-input for more info if (!this.shouldFloatLabel()) { this.$.label.classList.remove('hidden'); this.$.label.classList.add('animating'); this.async(function() { this.$.label.style.webkitTransform = 'none'; this.$.label.style.transform = 'none'; }); } this.focused = false; }, downAction: function(e) { if (this.disabled) { return; } if (this.focused) { return; } this.pressed = true; var rect = this.$.underline.getBoundingClientRect(); var right = e.x - rect.left; this.$.underlineHighlight.style.webkitTransformOriginX = right + 'px'; this.$.underlineHighlight.style.transformOriginX = right + 'px'; this.$.underlineHighlight.classList.remove('focused'); this.underlineAsync = this.async(function() { this.$.underlineHighlight.classList.add('pressed'); }, null, 200); // No caret animation if there is text in the input. if (!this.inputValue) { this.$.caret.classList.remove('focused'); } }, upAction: function(e) { if (this.disabled) { return; } if (!this.pressed) { return; } // if a touchevent caused the up, the synthentic mouseevents will blur // the input, make sure to prevent those from being generated. if (e._source === 'touch') { e.preventDefault(); } if (this.underlineAsync) { clearTimeout(this.underlineAsync); this.underlineAsync = null; } // Focus the input here to bring up the virtual keyboard. this.$.input.focus(); this.pressed = false; this.animating = true; this.$.underlineHighlight.classList.remove('pressed'); this.$.underlineHighlight.classList.add('animating'); this.async(function() { this.$.underlineHighlight.classList.add('focused'); }); // No caret animation if there is text in the input. if (!this.inputValue) { this.$.caret.classList.add('animating'); this.async(function() { this.$.caret.classList.add('focused'); }, null, 100); } if (this.floatingLabel) { this.$.label.classList.add('focusedColor'); this.$.label.classList.add('animating'); if (!this.$.label.cachedTransform) { this.prepareLabelTransform(); } this.$.label.style.webkitTransform = this.$.label.cachedTransform; this.$.label.style.transform = this.$.label.cachedTransform; } }, keydownAction: function() { this.super(); // more type = number hacks. see core-input for more info if (this.type === 'number') { this.async(function() { if (!this.inputValue) { this.toggleLabel(!this.validity.valid); } }); } }, keypressAction: function() { if (this.animating) { this.transitionEndAction(); } }, transitionEndAction: function(e) { this.animating = false; if (this.pressed) { return; } if (this.focused) { if (this.floatingLabel || this.inputValue) { this.$.label.classList.add('hidden'); } if (this.floatingLabel) { this.$.label.classList.remove('focusedColor'); this.$.label.classList.remove('animating'); this.$.floatedLabel.classList.remove('hidden'); this.$.floatedLabel.classList.add('focused'); this.$.floatedLabel.classList.add('focusedColor'); } this.async(function() { this.$.underlineHighlight.classList.remove('animating'); this.$.caret.classList.remove('animating'); }, null, 100); } else { this.$.label.classList.remove('animating'); } } }); }());