Skip to content

Instantly share code, notes, and snippets.

@dacur
Created June 13, 2014 16:14
Show Gist options
  • Select an option

  • Save dacur/feb7304f183aec72b731 to your computer and use it in GitHub Desktop.

Select an option

Save dacur/feb7304f183aec72b731 to your computer and use it in GitHub Desktop.
Autogrow.js allows a textbox to grow in size vertically instead of populating a scroll bar and hiding text while you continue to type. Example below is used in conjunction with Bootstrap and AJAX. The last few lines of code reset the box size each time "submit" button is clicked; otherwise, the text box remains the last (larger) size after click…
(function($){
//pass in just the context as a $(obj) or a settings JS object
$.fn.autogrow = function(opts) {
var that = $(this).css({overflow: 'hidden', resize: 'none'}) //prevent scrollies
, selector = that.selector
, defaults = {
context: $(document) //what to wire events to
, animate: true //if you want the size change to animate
, speed: 200 //speed of animation
, fixMinHeight: true //if you don't want the box to shrink below its initial size
, cloneClass: 'autogrowclone' //helper CSS class for clone if you need to add special rules
}
;
opts = $.isPlainObject(opts) ? opts : {context: opts ? opts : $(document)};
opts = $.extend({}, defaults, opts);
that.each(function(i, elem){
var min, clone;
elem = $(elem);
//if the element is "invisible", we get an incorrect height value
//to get correct value, clone and append to the body.
if (elem.is(':visible') || parseInt(elem.css('height'), 10) > 0) {
min = parseInt(elem.css('height'), 10) || elem.innerHeight();
} else {
clone = elem.clone()
.addClass(opts.cloneClass)
.val(elem.val())
.css({
position: 'absolute'
, visibility: 'hidden'
, display: 'block'
})
;
$('body').append(clone);
min = clone.innerHeight();
clone.remove();
}
if (opts.fixMinHeight) {
elem.data('autogrow-start-height', min); //set min height
}
elem.css('height', min);
});
opts.context
.on('keyup paste', selector, resize)
;
function resize (e){
var box = $(this)
, oldHeight = box.innerHeight()
, newHeight = this.scrollHeight
, minHeight = box.data('autogrow-start-height') || 0
, clone
;
if (oldHeight < newHeight) { //user is typing
this.scrollTop = 0; //try to reduce the top of the content hiding for a second
opts.animate ? box.stop().animate({height: newHeight}, opts.speed) : box.innerHeight(newHeight);
} else if (e.which == 8 || e.which == 46 || (e.ctrlKey && e.which == 88)) { //user is deleting, backspacing, or cutting
if (oldHeight > minHeight) { //shrink!
//this cloning part is not particularly necessary. however, it helps with animation
//since the only way to cleanly calculate where to shrink the box to is to incrementally
//reduce the height of the box until the $.innerHeight() and the scrollHeight differ.
//doing this on an exact clone to figure out the height first and then applying it to the
//actual box makes it look cleaner to the user
clone = box.clone()
.addClass(opts.cloneClass) //add clone class for extra css rules
.css({position: 'absolute', zIndex:-10}) //make "invisible"
.val(box.val()) //populate with content for consistent measuring
;
box.after(clone); //append as close to the box as possible for best CSS matching for clone
do { //reduce height until they don't match
newHeight = clone[0].scrollHeight - 1;
clone.innerHeight(newHeight);
} while (newHeight === clone[0].scrollHeight);
newHeight++; //adding one back eliminates a wiggle on deletion
clone.remove();
//if user selects all and deletes or holds down delete til beginning
//user could get here and shrink whole box
newHeight < minHeight && (newHeight = minHeight);
oldHeight > newHeight && opts.animate ? box.stop().animate({height: newHeight}, opts.speed) : box.innerHeight(newHeight);
} else { //just set to the minHeight
box.innerHeight(minHeight);
}
}
}
}
})(jQuery);
$('textarea#comment_comment').autogrow(); //This line calls autogrow on the textbox
//This code below resets the textbox height to 50px after each click/submit of comment/holler
//Without this code, the textbox does not reset size and remains the larger size (whatever size
//it 'autogrew' to be while you type the comment). Comments are added to page via AJAX call.
$(document).ready(function() {
function textarea_reset() {
$('textarea#comment_comment').attr("style", "height: 50px")
}
$('#btn-holler').on('click', textarea_reset);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment