/*
 * Usendes Auto Expanding Text Areas (2.0)
 * by Ruben Vreeken (www.usendes.nl)
 * ruben.vreeken@usendes.com
 *
 * Special thanks to:
 * Kasper Toth - (www.adowi.eu)
 *
 * Based on:
 * Auto Expanding Text Area (1.02)
 * by Chrys Bader (www.chrysbader.com)
 * chrysb@gmail.com
 *
 * Copyright (c) 2009 Ruben Vreeken (www.usendes.nl)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 *
 * NOTE: This script requires jQuery to work.  Download jQuery at www.jquery.com
 *
 */

(function($) {

  // Plugin
  $.fn.autogrow = function(options) {

    options = $.extend({}, this.autogrow.defaults, options);

    // iterate matched elements
    this.each(function(el) {
      el = $(this);
      setSettings(el, options);
      init(el);
    });

    function setSettings(el, options) {
      el.dummy       = null;
      el.interval    = null;
      el.line_height = parseInt($(el).css('line-height'));
      el.font_size   = parseInt($(el).css('font-size'));
      el.min_height  = parseInt($(el).css('min-height'));
      el.textarea    = $(el);
      el.options     = options;

      // complete options
      if(!el.options.speedExpand)
        el.options.speedExpand = el.options.speed;
      if(!el.options.speedShrink)
        el.options.speedShrink = el.options.speed;
      if(!el.options.easeExpand)
        el.options.easeExpand = el.options.ease;
      if(!el.options.easeShrink)
        el.options.easeShrink = el.options.ease;
      if(!el.options.extraWhitespace)
        el.options.extraWhitespace = (isNaN(el.line_height)) ? ((isNaN(el.font_size)) ? 16 : (el.font_size*1.33)) : el.line_height; // get line-height or font-size*1.33 or 16;
      if(   (!el.options.extraGrowth)
         || (el.options.extraGrowth < el.options.extraWhitespace)) //make sure the expansion matches the permanent extra linespaces required;
        el.options.extraGrowth = el.options.extraWhitespace;
    }

    function init(el) {
      el.textarea.css({overflow: 'hidden', display: 'block'});
      checkExpand(el,true);
      el.textarea.bind('keypress', function() { checkExpand(el,true) } ).bind('focus', function() { startExpand(el) } ).bind('blur', function() { stopExpand(el) });
    }

    function startExpand(el) {
      el.interval = window.setInterval(function() { checkExpand(el) }, el.options.interval);
    }

    function stopExpand(el) {
      clearInterval(el.interval);
    }

    function checkExpand(el,instant) {
      instant = instant || false;
      if (el.dummy == null) {
        el.dummy = $('<div></div>');
        el.dummy.css({
          'font':                     el.textarea.css('font'),
          'font-family':              el.textarea.css('font-family'),
          'font-size':                el.textarea.css('font-size'),
          'font-size-adjust':         el.textarea.css('font-size-adjust'),
          'font-stretch':             el.textarea.css('font-stretch'),
          'font-style':               el.textarea.css('font-style'),
          'font-variant':             el.textarea.css('font-variant'),
          'font-weight':              el.textarea.css('font-weight'),
          'layout-flow':              el.textarea.css('layout-flow'),
          'layout-grid':              el.textarea.css('layout-grid'),
          'layout-grid-char':         el.textarea.css('layout-grid-char'),
          'layout-grid-char-spacing': el.textarea.css('layout-grid-char-spacing'),
          'layout-grid-line':         el.textarea.css('layout-grid-line'),
          'layout-grid-mode':         el.textarea.css('layout-grid-mode'),
          'layout-grid-type':         el.textarea.css('layout-grid-type'),
          'letter-spacing':           el.textarea.css('letter-spacing'),
          'line-height':              el.textarea.css('line-height'),
          'text-align':               el.textarea.css('text-align'),
          'text-align-last':          el.textarea.css('text-align-last'),
          'text-autospace':           el.textarea.css('text-autospace'),
          'text-decoration':          el.textarea.css('text-decoration'),
          'text-indent':              el.textarea.css('text-indent'),
          'text-justify':             el.textarea.css('text-justify'),
          'text-kashida-space':       el.textarea.css('text-kashida-space'),
          'text-overflow':            el.textarea.css('text-overflow'),
          'text-shadow':              el.textarea.css('text-shadow'),
          'text-transform':           el.textarea.css('text-transform'),
          'text-underline-position':  el.textarea.css('text-underline-position'),
          'unicode-bidi':             el.textarea.css('unicode-bidi'),
          'white-space':              el.textarea.css('white-space'),
          'width':                    el.textarea.css('width'),
          'word-break':               el.textarea.css('word-break'),
          'word-spacing':             el.textarea.css('word-spacing'),
          'word-wrap':                el.textarea.css('word-wrap'),
          'writing-mode':             el.textarea.css('writing-mode'),
          'zoom':                     el.textarea.css('zoom'),
          'padding':                  el.textarea.css('padding'),
          'overflow-x':               'hidden',
          'display':                  'none',
          'position':                 'absolute',
          'top':                      0,
          'left':                     '-9999px'
        }).appendTo('body');
      }

      var html = el.textarea.val().replace(/\n/g, '<br>new');
      if(el.dummy.html() != html) {
        el.dummy.html(html);
        // get current height of the text
        var txt_height     = el.dummy.height();
        var area_height    = el.textarea.height();
        var maxed_size     = txt_height + el.options.extraGrowth;
        var minimized_size = txt_height + el.options.extraWhitespace;
        // Shrink if neccesary
        if (area_height > maxed_size) {
          var new_height = (minimized_size > el.min_height) ? minimized_size : el.min_height; // force min-height
          if(instant) {
            el.textarea.stop().height(new_height + 'px');
          } else {
            el.textarea.stop().animate({height: new_height + 'px'}, el.options.speedShrink, el.options.easeShrink);
          }
        }
        // Expand if neccesary
        else if (area_height < minimized_size) {
          if(instant) {
            var new_height = (minimized_size > el.min_height) ? minimized_size : el.min_height; // force min-height
            el.textarea.stop().height(new_height + 'px');
          } else {
            var new_height = (maxed_size > el.min_height) ? maxed_size : el.min_height; // force min-height
            el.textarea.stop().animate({height: new_height + 'px'}, el.options.speedExpand, el.options.easeExpand);
          }
        }
      }
    }

    return this;
  }

  // Defaults
  $.fn.autogrow.defaults = {
    'interval':        500,
    'speed':           250,
    'speedExpand':     '',
    'speedShrink':     '',
    'ease':            'linear',
    'easeExpand':      '',
    'easeShrink':      '',
    'extraGrowth':     '',
    'extraWhitespace': ''
  };

})(jQuery);
