2 * Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-container>`. This
3 * behavior is implemented by `<paper-input>`. It exposes a number of properties from
4 * `<paper-input-container>` and `<input is="iron-input">` and they should be bound in your
7 * The input element can be accessed by the `inputElement` property if you need to access
8 * properties or methods that are not exposed.
9 * @polymerBehavior Polymer.PaperInputBehavior
11 Polymer.PaperInputBehaviorImpl = {
16 * The label for this input. Bind this to `<paper-input-container>`'s `label` property.
23 * The value for this input. Bind this to the `<input is="iron-input">`'s `bindValue`
24 * property, or the value property of your input that is `notify:true`.
32 * Set to true to disable this input. Bind this to both the `<paper-input-container>`'s
33 * and the input's `disabled` property.
41 * Returns true if the value is invalid. Bind this to both the `<paper-input-container>`'s
42 * and the input's `invalid` property.
50 * Set to true to prevent the user from entering invalid input. Bind this to the
51 * `<input is="iron-input">`'s `preventInvalidInput` property.
53 preventInvalidInput: {
58 * Set this to specify the pattern allowed by `preventInvalidInput`. Bind this to the
59 * `<input is="iron-input">`'s `allowedPattern` property.
66 * The type of the input. The supported types are `text`, `number` and `password`. Bind this
67 * to the `<input is="iron-input">`'s `type` property.
74 * The datalist of the input (if any). This should match the id of an existing <datalist>. Bind this
75 * to the `<input is="iron-input">`'s `list` property.
82 * A pattern to validate the `input` with. Bind this to the `<input is="iron-input">`'s
90 * Set to true to mark the input as required. Bind this to the `<input is="iron-input">`'s
91 * `required` property.
99 * The error message to display when the input is invalid. Bind this to the
100 * `<paper-input-error>`'s content, if using.
107 * Set to true to show a character counter.
115 * Set to true to disable the floating label. Bind this to the `<paper-input-container>`'s
116 * `noLabelFloat` property.
124 * Set to true to always float the label. Bind this to the `<paper-input-container>`'s
125 * `alwaysFloatLabel` property.
133 * Set to true to auto-validate the input value. Bind this to the `<paper-input-container>`'s
134 * `autoValidate` property.
142 * Name of the validator to use. Bind this to the `<input is="iron-input">`'s `validator`
149 // HTMLInputElement attributes for binding if needed
152 * Bind this to the `<input is="iron-input">`'s `autocomplete` property.
160 * Bind this to the `<input is="iron-input">`'s `autofocus` property.
167 * Bind this to the `<input is="iron-input">`'s `inputmode` property.
174 * Bind this to the `<input is="iron-input">`'s `minlength` property.
181 * The maximum length of the input value. Bind this to the `<input is="iron-input">`'s
182 * `maxlength` property.
189 * The minimum (numeric or date-time) input value.
190 * Bind this to the `<input is="iron-input">`'s `min` property.
197 * The maximum (numeric or date-time) input value.
198 * Can be a String (e.g. `"2000-1-1"`) or a Number (e.g. `2`).
199 * Bind this to the `<input is="iron-input">`'s `max` property.
206 * Limits the numeric or date-time increments.
207 * Bind this to the `<input is="iron-input">`'s `step` property.
214 * Bind this to the `<input is="iron-input">`'s `name` property.
221 * A placeholder string in addition to the label. If this is set, the label will always float.
225 // need to set a default so _computeAlwaysFloatLabel is run
230 * Bind this to the `<input is="iron-input">`'s `readonly` property.
238 * Bind this to the `<input is="iron-input">`'s `size` property.
244 // Nonstandard attributes for binding if needed
247 * Bind this to the `<input is="iron-input">`'s `autocapitalize` property.
255 * Bind this to the `<input is="iron-input">`'s `autocorrect` property.
270 'addon-attached': '_onAddonAttached'
274 '_focusedControlStateChanged(focused)'
278 * Returns a reference to the input element.
284 attached: function() {
285 this._updateAriaLabelledBy();
288 _appendStringWithSpace: function(str, more) {
290 str = str + ' ' + more;
297 _onAddonAttached: function(event) {
298 var target = event.path ? event.path[0] : event.target;
300 this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, target.id);
302 var id = 'paper-input-add-on-' + Math.floor((Math.random() * 100000));
304 this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedBy, id);
309 * Validates the input element and sets an error style if needed.
311 validate: function() {
312 return this.inputElement.validate();
316 * Restores the cursor to its original position after updating the value.
317 * @param {string} newValue The value that should be saved.
319 updateValueAndPreserveCaret: function(newValue) {
320 // Not all elements might have selection, and even if they have the
321 // right properties, accessing them might throw an exception (like for
322 // <input type=number>)
324 var start = this.inputElement.selectionStart;
325 this.value = newValue;
327 // The cursor automatically jumps to the end after re-setting the value,
328 // so restore it to its original position.
329 this.inputElement.selectionStart = start;
330 this.inputElement.selectionEnd = start;
332 // Just set the value and give up on the caret.
333 this.value = newValue;
337 _computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) {
338 return placeholder || alwaysFloatLabel;
341 _focusedControlStateChanged: function(focused) {
342 // IronControlState stops the focus and blur events in order to redispatch them on the host
343 // element, but paper-input-container listens to those events. Since there are more
344 // pending work on focus/blur in IronControlState, I'm putting in this hack to get the
345 // input focus state working for now.
346 if (!this.$.container) {
347 this.$.container = Polymer.dom(this.root).querySelector('paper-input-container');
348 if (!this.$.container) {
353 this.$.container._onFocus();
355 this.$.container._onBlur();
359 _updateAriaLabelledBy: function() {
360 var label = Polymer.dom(this.root).querySelector('label');
362 this._ariaLabelledBy = '';
367 labelledBy = label.id;
369 labelledBy = 'paper-input-label-' + new Date().getUTCMilliseconds();
370 label.id = labelledBy;
372 this._ariaLabelledBy = labelledBy;
377 /** @polymerBehavior */
378 Polymer.PaperInputBehavior = [Polymer.IronControlState, Polymer.PaperInputBehaviorImpl];