public
Last active

  • Download Gist
textarea-auto-resize.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
/* Nurphy.com textarea auto-resize
*
* Based on implementation here:
* http://stackoverflow.com/questions/7477/autosizing-textarea
*
* Hidden textarea technique inspired by:
* http://james.padolsey.com/javascript/jquery-plugin-autoresize/
*
* Stack Overflow version inspired by:
* http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
*
* Notes:
*
* This will probably need the height of the textarea to be specified in
* pixels via CSS to work in IE. This is because we need to fetch the original
* height of the textarea in pixels, and according to the documentation
* getStyle('height') will return the actual (rather than computed) value in
* IE, which will be in whatever units the style was set in.
*
* http://www.prototypejs.org/api/element/getStyle
*
* Using getHeight() which should return the height in pixels returned
* different results across Safari and Firefox in testing.
*
*-------------------------------------------------------------------------- */
 
if (window.Widget == undefined) window.Widget = {};
 
Widget.Textarea = Class.create({
initialize: function(textarea, options)
{
this.textarea = $(textarea);
this.options = $H({ }).update(options);
 
// Disable scroll bars and Safari resizing.
this.textarea.setStyle({ overflowY: 'hidden', resize: 'none' });
// See notes above.
this.original_height = parseInt(this.textarea.getStyle('height'));
// Used to store the scroll offset of the shadow textarea so that we only
// need to do a resize if there's a change to this value.
this.previous_scroll_top = 0;
// Clone the textarea and copy any styles that will affect the amount of
// space consumed by text.
this._shadow = this.textarea.cloneNode(false).setStyle({
lineHeight: this.textarea.getStyle('lineHeight'),
fontSize: this.textarea.getStyle('fontSize'),
fontFamily: this.textarea.getStyle('fontFamily'),
letterSpacing: this.textarea.getStyle('letterSpacing'),
width: this.textarea.getStyle('width'),
height: this.textarea.getStyle('height'),
position: 'absolute',
top: '-10000px',
left: '-10000px'
}).writeAttribute({ id: null, name: null, disabled: true });
this.textarea.insert({ after: this._shadow });
 
// Could also fire on keydown, but I don't have a strong enough reason to
// do so at present. We'd be doubling the number of calls to refresh().
this.textarea.observe('keyup', this.refresh.bind(this));
this.textarea.observe('change', this.refresh.bind(this));
this.refresh();
},
 
refresh: function()
{
// Update the shadow textarea and scroll to the bottom.
this._shadow.update($F(this.textarea).replace(/</g, '&lt;').replace(/&/g, '&amp;')).scrollTop = 10000;
// Do nothing if the scroll offset hasn't changed.
if(this._shadow.scrollTop == this.previous_scroll_top) { return; }
this.textarea.setStyle({
height: (this._shadow.scrollTop + this.original_height) + 'px'
});
this.previous_scroll_top = this._shadow.scrollTop;
}
});

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.