Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components / iron-autogrow-textarea / iron-autogrow-textarea.html
blobcb1cd3391aeed06d817287af6fb8aab9a37ecca4
1 <!--
2 @license
3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9 -->
11 <link rel="import" href="../polymer/polymer.html">
12 <link rel="import" href="../iron-behaviors/iron-control-state.html">
13 <link rel="import" href="../iron-flex-layout/classes/iron-flex-layout.html">
14 <link rel="import" href="../iron-validatable-behavior/iron-validatable-behavior.html">
15 <link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html">
17 <!--
18 `iron-autogrow-textarea` is an element containing a textarea that grows in height as more
19 lines of input are entered. Unless an explicit height or the `maxRows` property is set, it will
20 never scroll.
22 Example:
24 <iron-autogrow-textarea id="a1">
25 <textarea id="t1"></textarea>
26 </iron-autogrow-textarea>
28 Because the `textarea`'s `value` property is not observable, you should use
29 this element's `bind-value` instead for imperative updates.
31 @group Iron Elements
32 @hero hero.svg
33 @demo demo/index.html
34 -->
36 <dom-module id="iron-autogrow-textarea">
38 <style>
39 :host {
40 display: inline-block;
41 position: relative;
42 width: 400px;
43 border: 1px solid;
44 padding: 2px;
45 -moz-appearance: textarea;
46 -webkit-appearance: textarea;
49 .mirror-text {
50 visibility: hidden;
51 word-wrap: break-word;
54 textarea {
55 position: relative;
56 outline: none;
57 border: none;
58 resize: none;
59 background: inherit;
60 color: inherit;
61 /* see comments in template */
62 width: 100%;
63 height: 100%;
64 font-size: inherit;
65 font-family: inherit;
68 ::content textarea:invalid {
69 box-shadow: none;
72 </style>
73 <template>
74 <!-- the mirror sizes the input/textarea so it grows with typing -->
75 <div id="mirror" class="mirror-text" aria-hidden="true">&nbsp;</div>
77 <!-- size the input/textarea with a div, because the textarea has intrinsic size in ff -->
78 <div class="textarea-container fit">
79 <textarea id="textarea"
80 autocomplete$="[[autocomplete]]"
81 autofocus$="[[autofocus]]"
82 inputmode$="[[inputmode]]"
83 placeholder$="[[placeholder]]"
84 readonly$="[[readonly]]"
85 required$="[[required]]"
86 rows$="[[rows]]"
87 maxlength$="[[maxlength]]"></textarea>
88 </div>
89 </template>
90 </dom-module>
92 <script>
94 Polymer({
96 is: 'iron-autogrow-textarea',
98 behaviors: [
99 Polymer.IronFormElementBehavior,
100 Polymer.IronValidatableBehavior,
101 Polymer.IronControlState
104 properties: {
107 * Use this property instead of `value` for two-way data binding.
109 bindValue: {
110 observer: '_bindValueChanged',
111 type: String
115 * The initial number of rows.
117 * @attribute rows
118 * @type number
119 * @default 1
121 rows: {
122 type: Number,
123 value: 1,
124 observer: '_updateCached'
128 * The maximum number of rows this element can grow to until it
129 * scrolls. 0 means no maximum.
131 * @attribute maxRows
132 * @type number
133 * @default 0
135 maxRows: {
136 type: Number,
137 value: 0,
138 observer: '_updateCached'
142 * Bound to the textarea's `autocomplete` attribute.
144 autocomplete: {
145 type: String,
146 value: 'off'
150 * Bound to the textarea's `autofocus` attribute.
152 autofocus: {
153 type: String,
154 value: 'off'
158 * Bound to the textarea's `inputmode` attribute.
160 inputmode: {
161 type: String
165 * Bound to the textarea's `name` attribute.
167 name: {
168 type: String
172 * The value for this input, same as `bindValue`
174 value: {
175 notify: true,
176 type: String,
177 computed: '_computeValue(bindValue)'
181 * Bound to the textarea's `placeholder` attribute.
183 placeholder: {
184 type: String
188 * Bound to the textarea's `readonly` attribute.
190 readonly: {
191 type: String
195 * Set to true to mark the textarea as required.
197 required: {
198 type: Boolean
202 * The maximum length of the input value.
204 maxlength: {
205 type: Number
210 listeners: {
211 'input': '_onInput'
215 * Returns the underlying textarea.
216 * @type HTMLTextAreaElement
218 get textarea() {
219 return this.$.textarea;
223 * Returns true if `value` is valid. The validator provided in `validator`
224 * will be used first, if it exists; otherwise, the `textarea`'s validity
225 * is used.
226 * @return {boolean} True if the value is valid.
228 validate: function() {
229 // Empty, non-required input is valid.
230 if (!this.required && this.value == '') {
231 this.invalid = false;
232 return true;
235 var valid;
236 if (this.hasValidator()) {
237 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
238 } else {
239 valid = this.$.textarea.validity.valid;
240 this.invalid = !valid;
242 this.fire('iron-input-validate');
243 return valid;
246 _update: function() {
247 this.$.mirror.innerHTML = this._valueForMirror();
249 var textarea = this.textarea;
250 // If the value of the textarea was updated imperatively, then we
251 // need to manually update bindValue as well.
252 if (textarea && this.bindValue != textarea.value) {
253 this.bindValue = textarea.value;
257 _bindValueChanged: function() {
258 var textarea = this.textarea;
259 if (!textarea) {
260 return;
263 textarea.value = this.bindValue;
264 this._update();
265 // manually notify because we don't want to notify until after setting value
266 this.fire('bind-value-changed', {value: this.bindValue});
269 _onInput: function(event) {
270 this.bindValue = event.path ? event.path[0].value : event.target.value;
271 this._update();
274 _constrain: function(tokens) {
275 var _tokens;
276 tokens = tokens || [''];
277 // Enforce the min and max heights for a multiline input to avoid measurement
278 if (this.maxRows > 0 && tokens.length > this.maxRows) {
279 _tokens = tokens.slice(0, this.maxRows);
280 } else {
281 _tokens = tokens.slice(0);
283 while (this.rows > 0 && _tokens.length < this.rows) {
284 _tokens.push('');
286 return _tokens.join('<br>') + '&nbsp;';
289 _valueForMirror: function() {
290 var input = this.textarea;
291 if (!input) {
292 return;
294 this.tokens = (input && input.value) ? input.value.replace(/&/gm, '&amp;').replace(/"/gm, '&quot;').replace(/'/gm, '&#39;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;').split('\n') : [''];
295 return this._constrain(this.tokens);
298 _updateCached: function() {
299 this.$.mirror.innerHTML = this._constrain(this.tokens);
302 _computeValue: function() {
303 return this.bindValue;
306 </script>