Service workers: Allow HTTPS pages arrived at via HTTP redirect to use SW
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components-chromium / paper-input / paper-input-container-extracted.js
blob585e4c8d377bcee07957480b523b83fdd52053a4
1 (function() {
3   Polymer({
5     is: 'paper-input-container',
7     properties: {
9       /**
10        * Set to true to disable the floating label. The label disappears when the input value is
11        * not null.
12        */
13       noLabelFloat: {
14         type: Boolean,
15         value: false
16       },
18       /**
19        * Set to true to always float the floating label.
20        */
21       alwaysFloatLabel: {
22         type: Boolean,
23         value: false
24       },
26       /**
27        * The attribute to listen for value changes on.
28        */
29       attrForValue: {
30         type: String,
31         value: 'bind-value'
32       },
34       /**
35        * Set to true to auto-validate the input value when it changes.
36        */
37       autoValidate: {
38         type: Boolean,
39         value: false
40       },
42       /**
43        * True if the input is invalid. This property is set automatically when the input value
44        * changes if auto-validating, or when the `iron-input-valid` event is heard from a child.
45        */
46       invalid: {
47         observer: '_invalidChanged',
48         type: Boolean,
49         value: false
50       },
52       /**
53        * True if the input has focus.
54        */
55       focused: {
56         readOnly: true,
57         type: Boolean,
58         value: false
59       },
61       _addons: {
62         type: Array
63         // do not set a default value here intentionally - it will be initialized lazily when a
64         // distributed child is attached, which may occur before configuration for this element
65         // in polyfill.
66       },
68       _inputHasContent: {
69         type: Boolean,
70         value: false
71       },
73       _inputSelector: {
74         type: String,
75         value: 'input,textarea,.paper-input-input'
76       },
78       _boundOnFocus: {
79         type: Function,
80         value: function() {
81           return this._onFocus.bind(this);
82         }
83       },
85       _boundOnBlur: {
86         type: Function,
87         value: function() {
88           return this._onBlur.bind(this);
89         }
90       },
92       _boundOnInput: {
93         type: Function,
94         value: function() {
95           return this._onInput.bind(this);
96         }
97       },
99       _boundValueChanged: {
100         type: Function,
101         value: function() {
102           return this._onValueChanged.bind(this);
103         }
104       }
106     },
108     listeners: {
109       'addon-attached': '_onAddonAttached',
110       'iron-input-validate': '_onIronInputValidate'
111     },
113     get _valueChangedEvent() {
114       return this.attrForValue + '-changed';
115     },
117     get _propertyForValue() {
118       return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
119     },
121     get _inputElement() {
122       return Polymer.dom(this).querySelector(this._inputSelector);
123     },
125     ready: function() {
126       if (!this._addons) {
127         this._addons = [];
128       }
129       this.addEventListener('focus', this._boundOnFocus, true);
130       this.addEventListener('blur', this._boundOnBlur, true);
131       if (this.attrForValue) {
132         this._inputElement.addEventListener(this._valueChangedEvent, this._boundValueChanged);
133       } else {
134         this.addEventListener('input', this._onInput);
135       }
136     },
138     attached: function() {
139       this._handleValue(this._inputElement);
140     },
142     _onAddonAttached: function(event) {
143       if (!this._addons) {
144         this._addons = [];
145       }
146       var target = event.target;
147       if (this._addons.indexOf(target) === -1) {
148         this._addons.push(target);
149         if (this.isAttached) {
150           this._handleValue(this._inputElement);
151         }
152       }
153     },
155     _onFocus: function() {
156       this._setFocused(true);
157     },
159     _onBlur: function() {
160       this._setFocused(false);
161     },
163     _onInput: function(event) {
164       this._handleValue(event.target);
165     },
167     _onValueChanged: function(event) {
168       this._handleValue(event.target);
169     },
171     _handleValue: function(inputElement) {
172       var value = inputElement[this._propertyForValue] || inputElement.value;
174       if (this.autoValidate) {
175         var valid;
176         if (inputElement.validate) {
177           valid = inputElement.validate(value);
178         } else {
179           valid = inputElement.checkValidity();
180         }
181         this.invalid = !valid;
182       }
184       // type="number" hack needed because this.value is empty until it's valid
185       if (value || value === 0 || (inputElement.type === 'number' && !inputElement.checkValidity())) {
186         this._inputHasContent = true;
187       } else {
188         this._inputHasContent = false;
189       }
191       this.updateAddons({
192         inputElement: inputElement,
193         value: value,
194         invalid: this.invalid
195       });
196     },
198     _onIronInputValidate: function(event) {
199       this.invalid = this._inputElement.invalid;
200     },
202     _invalidChanged: function() {
203       if (this._addons) {
204         this.updateAddons({invalid: this.invalid});
205       }
206     },
208     /**
209      * Call this to update the state of add-ons.
210      * @param {Object} state Add-on state.
211      */
212     updateAddons: function(state) {
213       for (var addon, index = 0; addon = this._addons[index]; index++) {
214         addon.update(state);
215       }
216     },
218     _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, invalid, _inputHasContent) {
219       var cls = 'input-content';
220       if (!noLabelFloat) {
221         var label = this.querySelector('label');
223         if (alwaysFloatLabel || _inputHasContent) {
224           cls += ' label-is-floating';
225           if (invalid) {
226             cls += ' is-invalid';
227           } else if (focused) {
228             cls += " label-is-highlighted";
229           }
230           // The label might have a horizontal offset if a prefix element exists
231           // which needs to be undone when displayed as a floating label.
232           if (this.$.prefix && label && label.offsetParent &&
233               Polymer.dom(this.$.prefix).getDistributedNodes().length > 0) {
234            label.style.left = -label.offsetParent.offsetLeft + 'px';
235           }
236         } else {
237           // When the label is not floating, it should overlap the input element.
238           if (label) {
239             label.style.left = 0;
240           }
241         }
242       } else {
243         if (_inputHasContent) {
244           cls += ' label-is-hidden';
245         }
246       }
247       return cls;
248     },
250     _computeUnderlineClass: function(focused, invalid) {
251       var cls = 'underline';
252       if (invalid) {
253         cls += ' is-invalid';
254       } else if (focused) {
255         cls += ' is-highlighted'
256       }
257       return cls;
258     },
260     _computeAddOnContentClass: function(focused, invalid) {
261       var cls = 'add-on-content';
262       if (invalid) {
263         cls += ' is-invalid';
264       } else if (focused) {
265         cls += ' is-highlighted'
266       }
267       return cls;
268     }
270   });
272 })();