comparison lib/assets/javascripts/jquery.autosize.js @ 79:50b8738d6428

Use (modified) autosize to automatically resize textarea.
author Edho Arief <edho@myconan.net>
date Mon, 08 Oct 2012 14:00:36 +0700
parents
children e8a0e82213cd
comparison
equal deleted inserted replaced
78:6ae3333a0251 79:50b8738d6428
1 // Autosize 1.13 - jQuery plugin for textareas
2 // (c) 2012 Jack Moore - jacklmoore.com
3 // license: www.opensource.org/licenses/mit-license.php
4
5 (function ($) {
6 var
7 defaults = {
8 className: 'autosizejs',
9 append: "",
10 callback: false
11 },
12 hidden = 'hidden',
13 borderBox = 'border-box',
14 lineHeight = 'lineHeight',
15 copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
16 // line-height is omitted because IE7/IE8 doesn't return the correct value.
17 copyStyle = [
18 'fontFamily',
19 'fontSize',
20 'fontWeight',
21 'fontStyle',
22 'letterSpacing',
23 'textTransform',
24 'wordSpacing',
25 'textIndent'
26 ],
27 oninput = 'oninput',
28 onpropertychange = 'onpropertychange',
29 test = $(copy)[0];
30
31 // For testing support in old FireFox
32 test.setAttribute(oninput, "return");
33
34 if ($.isFunction(test[oninput]) || onpropertychange in test) {
35
36 // test that line-height can be accurately copied to avoid
37 // incorrect value reporting in old IE and old Opera
38 $(test).css(lineHeight, '99px');
39 if ($(test).css(lineHeight) === '99px') {
40 copyStyle.push(lineHeight);
41 }
42
43 $.fn.autosize = function (options) {
44 options = $.extend({}, defaults, options || {});
45
46 return this.each(function () {
47 var
48 ta = this,
49 $ta = $(ta),
50 mirror,
51 minHeight = $ta.height(),
52 maxHeight = parseInt($ta.css('maxHeight'), 10),
53 active,
54 i = copyStyle.length,
55 resize,
56 boxOffset = 0,
57 value = ta.value,
58 callback = $.isFunction(options.callback);
59
60 if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox){
61 boxOffset = $ta.outerHeight() - $ta.height();
62 }
63
64 if ($ta.data('mirror') || $ta.data('ismirror')) {
65 // if autosize has already been applied, exit.
66 // if autosize is being applied to a mirror element, exit.
67 return;
68 } else {
69 mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
70
71 resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
72
73 $ta.data('mirror', $(mirror)).css({
74 overflow: hidden,
75 overflowY: hidden,
76 wordWrap: 'break-word',
77 resize: resize
78 });
79 }
80
81 // Opera returns '-1px' when max-height is set to 'none'.
82 maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
83
84 // Using mainly bare JS in this function because it is going
85 // to fire very often while typing, and needs to very efficient.
86 function adjust() {
87 var height, overflow, original;
88
89 // the active flag keeps IE from tripping all over itself. Otherwise
90 // actions in the adjust function will cause IE to call adjust again.
91 if (!active) {
92 active = true;
93 mirror.value = ta.value + options.append;
94 mirror.style.overflowY = ta.style.overflowY;
95 original = parseInt(ta.style.height,10);
96
97 // Update the width in case the original textarea width has changed
98 mirror.style.width = $ta.css('width');
99
100 // Needed for IE to reliably return the correct scrollHeight
101 mirror.scrollTop = 0;
102
103 // Set a very high value for scrollTop to be sure the
104 // mirror is scrolled all the way to the bottom.
105 mirror.scrollTop = 9e4;
106
107 height = mirror.scrollTop;
108 overflow = hidden;
109 if (height > maxHeight) {
110 height = maxHeight;
111 overflow = 'scroll';
112 } else if (height < minHeight) {
113 height = minHeight;
114 }
115 height += boxOffset;
116 ta.style.overflowY = overflow;
117
118 if (original !== height) {
119 ta.style.height = height + 'px';
120 if (callback) {
121 options.callback.call(ta);
122 }
123 }
124
125 // This small timeout gives IE a chance to draw it's scrollbar
126 // before adjust can be run again (prevents an infinite loop).
127 setTimeout(function () {
128 active = false;
129 }, 1);
130 }
131 }
132
133 // mirror is a duplicate textarea located off-screen that
134 // is automatically updated to contain the same text as the
135 // original textarea. mirror always has a height of 0.
136 // This gives a cross-browser supported way getting the actual
137 // height of the text, through the scrollTop property.
138 while (i--) {
139 mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
140 }
141
142 $('body').append(mirror);
143
144 if (onpropertychange in ta) {
145 if (oninput in ta) {
146 // Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
147 // so binding to onkeyup to catch most of those occassions. There is no way that I
148 // know of to detect something like 'cut' in IE9.
149 ta[oninput] = ta.onkeyup = adjust;
150 } else {
151 // IE7 / IE8
152 ta[onpropertychange] = adjust;
153 }
154 } else {
155 // Modern Browsers
156 ta[oninput] = adjust;
157
158 // The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
159 // This is a hack to get Chrome to reflow it's text.
160 ta.value = '';
161 ta.value = value;
162 }
163
164 $(window).resize(adjust);
165
166 // Allow for manual triggering if needed.
167 $ta.bind('autosize', adjust);
168
169 // Call adjust in case the textarea already contains text.
170 adjust();
171 });
172 };
173 } else {
174 // Makes no changes for older browsers (FireFox3- and Safari4-)
175 $.fn.autosize = function (callback) {
176 return this;
177 };
178 }
179
180 }(jQuery));