Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
TextArea AutoResizer (Bootstrap jQuery/Zepto Plugin)
var AutoResizer = function (textArea, options) {
var self = this;
this.$textArea = $(textArea);
this.minHeight = this.$textArea.height();
this.options = $.extend({}, $.fn.autoResizer.defaults, options)
this.$shadowArea = $('<div></div>').css({
position: 'absolute',
top: -10000,
left: -10000,
fontSize: this.$textArea.css('fontSize') || 'inherit',
fontFamily: this.$textArea.css('fontFamily') || 'inherit',
lineHeight: this.$textArea.css('lineHeight') || 'inherit',
resize: 'none'
}).appendTo(document.body);
var startWidth = this.$textArea.width() || $(window).width();
this.$shadowArea.width(startWidth);
if (this.options.resizeOnChange) {
function onChange() {
window.setTimeout(function() {
self.checkResize();
}, 0);
}
this.$textArea.change(onChange).keyup(onChange).keydown(onChange).focus(onChange);
}
this.checkResize();
};
AutoResizer.prototype = {
constructor: AutoResizer,
checkResize: function() {
// No sense in auto-growing non-visible textarea, which height of 0 implies
if (this.$textArea.height() === 0) {
return;
}
// If this is first time we've seen text area rendered, remember the height
if (this.minHeight === 0) {
this.minHeight = this.$textArea.height();
}
// If the text area has changed in size past a certain threshold of difference
// like when it becomes visible or viewport changes
if (this.$textArea.width() !== 0 && Math.abs(this.$shadowArea.width() - this.$textArea.width()) > 20) {
this.$shadowArea.width(this.$textArea.width());
}
var val = this.$textArea.val().replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/&/g, '&amp;')
.replace(/\n/g, '<br/>&nbsp;');
if ($.trim(val) === '') {
val = 'a';
}
this.$shadowArea.html(val);
var nextHeight = Math.max(this.$shadowArea[0].offsetHeight + 10, this.minHeight);
if (!this.prevHeight || nextHeight != this.prevHeight) {
this.$textArea.css('height', nextHeight);
this.prevHeight = nextHeight;
}
}
};
$.fn.autoResizer = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('autoresizer')
, options = typeof option == 'object' && option
if (!data) $this.data('autoresizer', (data = new AutoResizer(this, options)))
if (typeof option == 'string') data[option]()
else data.checkResize()
})
}
$.fn.autoResizer.defaults = {
resizeOnChange: true
};
$.fn.autoResizer.Constructor = AutoResizer;

lerouxb commented Mar 22, 2012

Tried to get it to work with box-sizing: border-box; width: 100%; padding and a border:
http://jsfiddle.net/lerouxb/7Mube/

But gave up for now. The height calculations are off by a bit.

rumpl commented Mar 22, 2012

@lerouxb you just need to add 20 instead of 10 on line 61. http://jsfiddle.net/7Mube/2/

lerouxb commented Mar 22, 2012

@rumpl Aah thanks. What does that magic value do? Shouldn't it be dynamic based on line height, font size, border, padding or some setting?

rumpl commented Mar 22, 2012

@lerouxb I think I used to know what the 20 was for, but not any more, will take a look a it son.

Owner

pamelafox commented Mar 22, 2012

Right now the shadow doesn't mimic the padding of the text area, so I imagine the magic number has to do with that. It was good enough for me, but you should try displaying both shadow and text area at same time and you'll see how they differ (and then you can mirror a few more properties over).

lerouxb commented Mar 24, 2012

I happened to notice this commit via the whole svbtle/obtvse thing:
natew/obtvse@648e9a1

 textarea.onkeydown = function() {
    textarea.style.height = ""; /* Reset the height*/
    textarea.style.height = textarea.scrollHeight + "px";
};

Could it really be that simple?

lerouxb commented Mar 24, 2012

Here's a jsfiddle: http://jsfiddle.net/lerouxb/vRSP2/

Apart from being simpler it also has the benefit of not momentarily flashing a scrollbar. It isn't very smart about sizing back down again, though.

rumpl commented Mar 24, 2012

There are some issues with backspace.

rumpl commented Mar 24, 2012

rumpl commented Mar 24, 2012

Ok, sorry for the double post :)

xpachino commented Mar 4, 2015

Why dose the content jump as you continue to press enter? Tried it on facebook post comment textarea and it was seamless.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment