ApplicationImpl cleanup, part 1:
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components-chromium / paper-input / paper-input-behavior-extracted.js
blob6acae9908bc32b878aa14f97a502545390563aeb
3   /**
4    * Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-container>`. This
5    * behavior is implemented by `<paper-input>`. It exposes a number of properties from
6    * `<paper-input-container>` and `<input is="iron-input">` and they should be bound in your
7    * template.
8    *
9    * The input element can be accessed by the `inputElement` property if you need to access
10    * properties or methods that are not exposed.
11    * @polymerBehavior Polymer.PaperInputBehavior
12    */
13   Polymer.PaperInputBehaviorImpl = {
15     properties: {
17       /**
18        * The label for this input. Bind this to `<paper-input-container>`'s `label` property.
19        */
20       label: {
21         type: String
22       },
24       /**
25        * The value for this input. Bind this to the `<input is="iron-input">`'s `bindValue`
26        * property, or the value property of your input that is `notify:true`.
27        */
28       value: {
29         notify: true,
30         type: String
31       },
33       /**
34        * Set to true to disable this input. Bind this to both the `<paper-input-container>`'s
35        * and the input's `disabled` property.
36        */
37       disabled: {
38         type: Boolean,
39         value: false
40       },
42       /**
43        * Returns true if the value is invalid. Bind this to both the `<paper-input-container>`'s
44        * and the input's `invalid` property.
45        */
46       invalid: {
47         type: Boolean,
48         value: false
49       },
51       /**
52        * Set to true to prevent the user from entering invalid input. Bind this to the
53        * `<input is="iron-input">`'s `preventInvalidInput` property.
54        */
55       preventInvalidInput: {
56         type: Boolean
57       },
59       /**
60        * Set this to specify the pattern allowed by `preventInvalidInput`. Bind this to the
61        * `<input is="iron-input">`'s `allowedPattern` property.
62        */
63       allowedPattern: {
64         type: String
65       },
67       /**
68        * The type of the input. The supported types are `text`, `number` and `password`. Bind this
69        * to the `<input is="iron-input">`'s `type` property.
70        */
71       type: {
72         type: String
73       },
75       /**
76        * The datalist of the input (if any). This should match the id of an existing <datalist>. Bind this
77        * to the `<input is="iron-input">`'s `list` property.
78        */
79       list: {
80         type: String
81       },
83       /**
84        * A pattern to validate the `input` with. Bind this to the `<input is="iron-input">`'s
85        * `pattern` property.
86        */
87       pattern: {
88         type: String
89       },
91       /**
92        * Set to true to mark the input as required. Bind this to the `<input is="iron-input">`'s
93        * `required` property.
94        */
95       required: {
96         type: Boolean,
97         value: false
98       },
100       /**
101        * The maximum length of the input value. Bind this to the `<input is="iron-input">`'s
102        * `maxlength` property.
103        */
104       maxlength: {
105         type: Number
106       },
108       /**
109        * The error message to display when the input is invalid. Bind this to the
110        * `<paper-input-error>`'s content, if using.
111        */
112       errorMessage: {
113         type: String
114       },
116       /**
117        * Set to true to show a character counter.
118        */
119       charCounter: {
120         type: Boolean,
121         value: false
122       },
124       /**
125        * Set to true to disable the floating label. Bind this to the `<paper-input-container>`'s
126        * `noLabelFloat` property.
127        */
128       noLabelFloat: {
129         type: Boolean,
130         value: false
131       },
133       /**
134        * Set to true to always float the label. Bind this to the `<paper-input-container>`'s
135        * `alwaysFloatLabel` property.
136        */
137       alwaysFloatLabel: {
138         type: Boolean,
139         value: false
140       },
142       /**
143        * Set to true to auto-validate the input value. Bind this to the `<paper-input-container>`'s
144        * `autoValidate` property.
145        */
146       autoValidate: {
147         type: Boolean,
148         value: false
149       },
151       /**
152        * Name of the validator to use. Bind this to the `<input is="iron-input">`'s `validator`
153        * property.
154        */
155       validator: {
156         type: String
157       },
159       // HTMLInputElement attributes for binding if needed
161       /**
162        * Bind this to the `<input is="iron-input">`'s `autocomplete` property.
163        */
164       autocomplete: {
165         type: String,
166         value: 'off'
167       },
169       /**
170        * Bind this to the `<input is="iron-input">`'s `autofocus` property.
171        */
172       autofocus: {
173         type: Boolean
174       },
176       /**
177        * Bind this to the `<input is="iron-input">`'s `inputmode` property.
178        */
179       inputmode: {
180         type: String
181       },
183       /**
184        * Bind this to the `<input is="iron-input">`'s `minlength` property.
185        */
186       minlength: {
187         type: Number
188       },
190       /**
191        * Bind this to the `<input is="iron-input">`'s `name` property.
192        */
193       name: {
194         type: String
195       },
197       /**
198        * A placeholder string in addition to the label. If this is set, the label will always float.
199        */
200       placeholder: {
201         type: String,
202         // need to set a default so _computeAlwaysFloatLabel is run
203         value: ''
204       },
206       /**
207        * Bind this to the `<input is="iron-input">`'s `readonly` property.
208        */
209       readonly: {
210         type: Boolean,
211         value: false
212       },
214       /**
215        * Bind this to the `<input is="iron-input">`'s `size` property.
216        */
217       size: {
218         type: Number
219       },
221       // Nonstandard attributes for binding if needed
223       /**
224        * Bind this to the `<input is="iron-input">`'s `autocapitalize` property.
225        */
226       autocapitalize: {
227         type: String,
228         value: 'none'
229       },
231       /**
232        * Bind this to the `<input is="iron-input">`'s `autocorrect` property.
233        */
234       autocorrect: {
235         type: String,
236         value: 'off'
237       },
239       _ariaDescribedBy: {
240         type: String,
241         value: ''
242       }
244     },
246     listeners: {
247       'addon-attached': '_onAddonAttached'
248     },
250     observers: [
251       '_focusedControlStateChanged(focused)'
252     ],
254     /**
255      * Returns a reference to the input element.
256      */
257     get inputElement() {
258       return this.$.input;
259     },
261     attached: function() {
262       this._updateAriaLabelledBy();
263     },
265     _appendStringWithSpace: function(str, more) {
266       if (str) {
267         str = str + ' ' + more;
268       } else {
269         str = more;
270       }
271       return str;
272     },
274     _onAddonAttached: function(event) {
275       var target = event.path ? event.path[0] : event.target;
276       if (target.id) {
277         this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, target.id);
278       } else {
279         var id = 'paper-input-add-on-' + Math.floor((Math.random() * 100000));
280         target.id = id;
281         this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, id);
282       }
283     },
285     /**
286      * Validates the input element and sets an error style if needed.
287      */
288      validate: function() {
289        return this.inputElement.validate();
290      },
292     /**
293      * Restores the cursor to its original position after updating the value.
294      * @param {string} newValue The value that should be saved.
295      */
296     updateValueAndPreserveCaret: function(newValue) {
297       // Not all elements might have selection, and even if they have the
298       // right properties, accessing them might throw an exception (like for
299       // <input type=number>)
300       try {
301         var start = this.inputElement.selectionStart;
302         this.value = newValue;
304         // The cursor automatically jumps to the end after re-setting the value,
305         // so restore it to its original position.
306         this.inputElement.selectionStart = start;
307         this.inputElement.selectionEnd = start;
308       } catch (e) {
309         // Just set the value and give up on the caret.
310         this.value = newValue;
311       }
312     },
314     _computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) {
315       return placeholder || alwaysFloatLabel;
316     },
318     _focusedControlStateChanged: function(focused) {
319       // IronControlState stops the focus and blur events in order to redispatch them on the host
320       // element, but paper-input-container listens to those events. Since there are more
321       // pending work on focus/blur in IronControlState, I'm putting in this hack to get the
322       // input focus state working for now.
323       if (!this.$.container) {
324         this.$.container = Polymer.dom(this.root).querySelector('paper-input-container');
325         if (!this.$.container) {
326           return;
327         }
328       }
329       if (focused) {
330         this.$.container._onFocus();
331       } else {
332         this.$.container._onBlur();
333       }
334     },
336     _updateAriaLabelledBy: function() {
337       var label = Polymer.dom(this.root).querySelector('label');
338       if (!label) {
339         this._ariaLabelledBy = '';
340         return;
341       }
342       var labelledBy;
343       if (label.id) {
344         labelledBy = label.id;
345       } else {
346         labelledBy = 'paper-input-label-' + new Date().getUTCMilliseconds();
347         label.id = labelledBy;
348       }
349       this._ariaLabelledBy = labelledBy;
350     }
352   };
354   /** @polymerBehavior */
355   Polymer.PaperInputBehavior = [Polymer.IronControlState, Polymer.PaperInputBehaviorImpl];