Fix OOP <webview> resize and autosize.
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components-chromium / iron-autogrow-textarea / iron-autogrow-textarea-extracted.js
blob216df53b92fffcce2e836782931f9bfb238d1283
1 Polymer({
3     is: 'iron-autogrow-textarea',
5     behaviors: [
6       Polymer.IronFormElementBehavior,
7       Polymer.IronValidatableBehavior,
8       Polymer.IronControlState
9     ],
11     properties: {
13       /**
14        * Use this property instead of `value` for two-way data binding.
15        */
16       bindValue: {
17         observer: '_bindValueChanged',
18         type: String
19       },
21       /**
22        * The initial number of rows.
23        *
24        * @attribute rows
25        * @type number
26        * @default 1
27        */
28       rows: {
29         type: Number,
30         value: 1,
31         observer: '_updateCached'
32       },
34       /**
35        * The maximum number of rows this element can grow to until it
36        * scrolls. 0 means no maximum.
37        *
38        * @attribute maxRows
39        * @type number
40        * @default 0
41        */
42       maxRows: {
43        type: Number,
44        value: 0,
45        observer: '_updateCached'
46       },
48       /**
49        * Bound to the textarea's `autocomplete` attribute.
50        */
51       autocomplete: {
52         type: String,
53         value: 'off'
54       },
56       /**
57        * Bound to the textarea's `autofocus` attribute.
58        */
59       autofocus: {
60         type: Boolean,
61         value: false
62       },
64       /**
65        * Bound to the textarea's `inputmode` attribute.
66        */
67       inputmode: {
68         type: String
69       },
71       /**
72        * Bound to the textarea's `name` attribute.
73        */
74       name: {
75         type: String
76       },
78       /**
79        * The value for this input, same as `bindValue`
80        */
81       value: {
82         notify: true,
83         type: String,
84         computed: '_computeValue(bindValue)'
85       },
87       /**
88        * Bound to the textarea's `placeholder` attribute.
89        */
90       placeholder: {
91         type: String
92       },
94       /**
95        * Bound to the textarea's `readonly` attribute.
96        */
97       readonly: {
98         type: String
99       },
101       /**
102        * Set to true to mark the textarea as required.
103        */
104       required: {
105         type: Boolean
106       },
108       /**
109        * The maximum length of the input value.
110        */
111       maxlength: {
112         type: Number
113       }
115     },
117     listeners: {
118       'input': '_onInput'
119     },
121     /**
122      * Returns the underlying textarea.
123      * @type HTMLTextAreaElement
124      */
125     get textarea() {
126       return this.$.textarea;
127     },
129     /**
130      * Returns true if `value` is valid. The validator provided in `validator`
131      * will be used first, if it exists; otherwise, the `textarea`'s validity
132      * is used.
133      * @return {boolean} True if the value is valid.
134      */
135     validate: function() {
136       // Empty, non-required input is valid.
137       if (!this.required && this.value == '') {
138         this.invalid = false;
139         return true;
140       }
142       var valid;
143       if (this.hasValidator()) {
144         valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
145       } else {
146         valid = this.$.textarea.validity.valid;
147         this.invalid = !valid;
148       }
149       this.fire('iron-input-validate');
150       return valid;
151     },
153     _bindValueChanged: function() {
154       var textarea = this.textarea;
155       if (!textarea) {
156         return;
157       }
159       textarea.value = this.bindValue;
160       this.$.mirror.innerHTML = this._valueForMirror();
161       // manually notify because we don't want to notify until after setting value
162       this.fire('bind-value-changed', {value: this.bindValue});
163     },
165     _onInput: function(event) {
166       this.bindValue = event.path ? event.path[0].value : event.target.value;
167     },
169     _constrain: function(tokens) {
170       var _tokens;
171       tokens = tokens || [''];
172       // Enforce the min and max heights for a multiline input to avoid measurement
173       if (this.maxRows > 0 && tokens.length > this.maxRows) {
174         _tokens = tokens.slice(0, this.maxRows);
175       } else {
176         _tokens = tokens.slice(0);
177       }
178       while (this.rows > 0 && _tokens.length < this.rows) {
179         _tokens.push('');
180       }
181       return _tokens.join('<br>') + '&nbsp;';
182     },
184     _valueForMirror: function() {
185       var input = this.textarea;
186       if (!input) {
187         return;
188       }
189       this.tokens = (input && input.value) ? input.value.replace(/&/gm, '&amp;').replace(/"/gm, '&quot;').replace(/'/gm, '&#39;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;').split('\n') : [''];
190       return this._constrain(this.tokens);
191     },
193     _updateCached: function() {
194       this.$.mirror.innerHTML = this._constrain(this.tokens);
195     },
197     _computeValue: function() {
198       return this.bindValue;
199     }
200   });