textarea resizer

by lerouxb

HTML

<textarea>type stuff here</textarea>

CSS

textarea {
/* Try and go 100% while supporting padding and borders. */
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;

/* Best to set all three of these or something will be 'inherit' and cause problems. */    
font-size: 16px;
line-height: 20px;
font-family: helvetica;

/* The reason for using border-box. */
width: 100%;
padding: 10px;
border: none;
color: #999;

resize: none;

/*
I probably wouldn't really be using a border in this kind of situation. It is just here for testing.
*/
border: 10px solid #eee;
}

textarea:focus {
outline: none;
color: #333;
}

JavaScript

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',

      // This helps for box-sizing: border-box textarea:
      
      paddingTop: this.$textArea.css('paddingTop') || 'inherit',
      paddingBottom: this.$textArea.css('paddingBottom') || 'inherit',
      paddingLeft: this.$textArea.css('paddingLeft') || 'inherit',
      paddingRight: this.$textArea.css('paddingRight') || 'inherit',

      borderTopWidth: this.$textArea.css('borderTopWidth') || 'inherit',
      borderBottomWidth: this.$textArea.css('borderBottomWidth') || 'inherit',
      borderLeftWidth: this.$textArea.css('borderLeftWidth') || 'inherit',
      borderRightWidth: this.$textArea.css('borderRightWidth') || '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...