Skip to content

Instantly share code, notes, and snippets.

@phorsfall
Created September 28, 2009 15:16
Show Gist options
  • Save phorsfall/195495 to your computer and use it in GitHub Desktop.
Save phorsfall/195495 to your computer and use it in GitHub Desktop.
/* 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;
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment