/**
*	@name							Elastic
*	@descripton						Elastic is Jquery plugin that grow and shrink your textareas automaticliy
*	@version						1.6.4
*	@requires						Jquery 1.2.6+
*
*	@author							Jan Jarfalk
*	@author-email					jan.jarfalk@unwrongest.com
*	@author-website					http://www.unwrongest.com
*
*	@licens							MIT License - http://www.opensource.org/licenses/mit-license.php
*/

(function (jQuery) {
    jQuery.fn.extend({
        elastic: function () {

            //	We will create a div clone of the textarea
            //	by copying these attributes from the textarea to the div.
            var mimics = [
				'paddingTop',
				'paddingRight',
				'paddingBottom',
				'paddingLeft',
				'fontSize',
				'lineHeight',
				'fontFamily',
				'fontWeight'];

            return this.each(function () {

                // Elastic only works on textareas
                if (this.type != 'textarea') {
                    return false;
                }

                var $textarea = jQuery(this),
					$twin = jQuery('<div class="tw" />').css({ 'position': 'absolute', 'display': 'none', 'word-wrap': 'break-word' }),
					lineHeight = parseInt($textarea.css('line-height'), 10) || parseInt($textarea.css('font-size'), '10'),
                //minheight = parseInt($textarea.css('height'), 10) || lineHeight * 3,
                    minheight = lineHeight,
                maxheight = parseInt($textarea.css('max-height'), 10) || Number.MAX_VALUE,
					goalheight = 0,
					i = 0;

                // Opera returns max-height of -1 if not set
                if (maxheight < 0) { maxheight = Number.MAX_VALUE; }

                // Append the twin to the DOM
                // We are going to meassure the height of this, not the textarea.
                $twin.appendTo($textarea.parent());

                // Copy the essential styles (mimics) from the textarea to the twin
                var i = mimics.length;
                while (i--) {
                    $twin.css(mimics[i].toString(), $textarea.css(mimics[i].toString()));
                }

                var classList = $textarea.attr('class').split(/\s+/);
                for (i = 0; i < classList.length; i++) {
                    $twin.addClass(classList[i]);
                }
                //$twin.attr("id","ghost" + $textarea.attr("id"));

                // Sets a given height and overflow state on the textarea
                function setHeightAndOverflow(height, overflow) {
                    curratedHeight = Math.floor(parseInt(height, 10));
                    if ($textarea.height() != curratedHeight) {
                        $textarea.css({ 'height': curratedHeight + 'px', 'overflow': overflow });

                    }
                }


                // This function will update the height of the textarea if necessary 
                function update() {

                    $twin.appendTo($textarea.parent());


                    // Get curated content from the textarea.
                    var textareaContent = $textarea.val().replace(/&/g, '&amp;').replace(/  /g, '&nbsp;').replace(/<|>/g, '&gt;').replace(/\n/g, '<br />');

                    var twinContent = $twin.html();

                    //if (textareaContent + '&nbsp;' != twinContent) {

                    // Add an extra white space so new rows are added when you are at the end of a row.
                    $twin.html(textareaContent + '&nbsp;');

                    // Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
                    if (Math.abs($twin.height()) > 3) {

                        var goalheight = $twin.height();
                        //                            if (goalheight > lineHeight * 2) {
                        //                                goalheight += lineHeight;
                        //                            }
                        if (goalheight >= maxheight) {
                            setHeightAndOverflow(maxheight, 'auto');
                        } else if (goalheight <= minheight) {
                            setHeightAndOverflow(minheight, 'hidden');
                        } else {
                            setHeightAndOverflow(goalheight, 'hidden');
                        }

                    }
                    else {
                        var x = 1;
                        x++;
                    }
                    //}

                }

                // Hide scrollbars
                $textarea.css({ 'overflow': 'hidden' });

                // Update textarea size on keyup
                $textarea.keyup(function (event) {
                    if (event.keyCode != '13') {
                        update();
                    }
                });

                // And this line is to catch the browser paste event
                $textarea.live('input paste', function (e) { setTimeout(update, 250); });


                $textarea.blur(
                function () {
                    update();
                }
                );

                $textarea.updateHeight = function () { update(); };
                // Run update once when elastic is initialized
                update();

            });

        }
    });
})(jQuery);
