654 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			654 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			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
 | |
| -->
 | |
| 
 | |
| <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"> </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>
 |