1 <!--
2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS
5 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
6 Code distributed by Google as part of the polymer project is also
7 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
8 -->
9
10 <!--
11 `paper-autogrow-textarea` is an element containing a textarea that grows in height as more
12 lines of input are entered. Unless an explicit height or the `maxRows` property is set, it will
13 never scroll.
14
15 Example:
16
17 <paper-autogrow-textarea id="a1">
18 <textarea id="t1"></textarea>
19 </paper-autogrow-textarea>
20
21 Because the `textarea`'s `value` property is not observable, if you set the `value` imperatively
22 you must call `update` to notify this element the value has changed.
23
24 Example:
25
26 /* using example HTML above */
27 t1.value = 'some\ntext';
28 a1.update();
29
30 @group Paper Elements
31 @element paper-autogrow-textarea
32 @status unstable
33 -->
34
35 <link href="../polymer/polymer.html" rel="import">
36
37 <polymer-element name="paper-autogrow-textarea" on-input="{{inputAction}}">
38 <template>
39
40 <style>
41 :host {
42 display: inline-block;
43 position: relative;
44 width: 400px;
45 }
46
47 .mirror-text {
48 visibility: hidden;
49 word-wrap: break-word;
50 }
51
52 ::content textarea {
53 padding: 0;
54 margin: 0;
55 border: none;
56 outline: none;
57 resize: none;
58 /* see comments in template */
59 width: 100%;
60 height: 100%;
61 }
62
63 ::content textarea:invalid {
64 box-shadow: none;
65 }
66 </style>
67
68 <!-- the mirror sizes the input/textarea so it grows with typing -->
69 <div id="mirror" class="mirror-text" aria-hidden="true"> </div>
70
71 <!-- size the input/textarea with a div, because the textarea has intrinsic size in ff -->
72 <div class="textarea-container" fit>
73 <content></content>
74 </div>
75
76 </template>
77 <script>
78
79 Polymer({
80
81 publish: {
82
83 /**
84 * The textarea that should auto grow.
85 *
86 * @attribute target
87 * @type HTMLTextAreaElement
88 * @default null
89 */
90 target: null,
91
92 /**
93 * The initial number of rows.
94 *
95 * @attribute rows
96 * @type number
97 * @default 1
98 */
99 rows: 1,
100
101 /**
102 * The maximum number of rows this element can grow to until it
103 * scrolls. 0 means no maximum.
104 *
105 * @attribute maxRows
106 * @type number
107 * @default 0
108 */
109 maxRows: 0
110 },
111
112 tokens: null,
113
114 observe: {
115 rows: 'updateCached',
116 maxRows: 'updateCached'
117 },
118
119 constrain: function(tokens) {
120 var _tokens;
121 tokens = tokens || [''];
122 // Enforce the min and max heights for a multiline input to avoid measurement
123 if (this.maxRows > 0 && tokens.length > this.maxRows) {
124 _tokens = tokens.slice(0, this.maxRows);
125 } else {
126 _tokens = tokens.slice(0);
127 }
128 while (this.rows > 0 && _tokens.length < this.rows) {
129 _tokens.push('');
130 }
131 return _tokens.join('
') + ' ';
132 },
133
134 valueForMirror: function(input) {
135 this.tokens = (input && input.value) ? input.value.replace(/&/gm, '&').replace(/"/gm, '"').replace(/'/gm, ''').replace(/</gm, '<').replace(/>/gm, '>').split('\n') : [''];
136 return this.constrain(this.tokens);
137 },
138
139 /**
140 * Sizes this element to fit the input value. This function is automatically called
141 * when the user types in new input, but you must call this function if the value
142 * is updated imperatively.
143 *
144 * @method update
145 * @param Element The input
146 */
147 update: function(input) {
148 this.$.mirror.innerHTML = this.valueForMirror(input);
149 },
150
151 updateCached: function() {
152 this.$.mirror.innerHTML = this.constrain(this.tokens);
153 },
154
155 inputAction: function(e) {
156 this.update(e.target);
157 }
158
159 });
160
161 </script>
162 </polymer-element>
163