/**
 *	@name           Elastic
 *	@descripton     Elastic is Jquery plugin that grow and shrink your textareas automaticliy
 *	@version        1.6.5
 *	@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',
            'width',
            'fontWeight'];

            return this.each( function() {

                // Elastic only works on textareas
                if ( this.type != 'textarea' ) {
                    return false;
                }

                var $textarea = jQuery(this),
                    twinId    = $textarea.attr('id') + '-twin',
                    $twin     = $('<div>', {
                        'id': twinId,
                        css: {
                            'height': 'auto', // svata
                            'display': 'none',
                            'position': 'absolute',
                            'word-wrap':'break-word'
                        },
                        data: {
                            'original-height': $textarea.height()
                        }
                    });

                // Prevent duplicate $twin element
                $('#' + twinId).remove();

                var lineHeight	=	parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'),
                    minheight	=	parseInt($textarea.css('height'),10) || lineHeight*3,
                    maxheight	=	parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE,
                    goalheight	=	0,
                    i		=	0,
                    $widthCheck =       false,
                    forceUpdating = true; //forcing update of textarea either if there were no changes
                                
                // 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
                i = mimics.length;
                while(i--){
                    $twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));
                }

                // 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({
                            'overflow': overflow,
                            'height': curratedHeight + 'px'
                        });
                    }
                }

                // reset the twin's height (may be needed if source textarea was hidden in IE)
                function resetWidth() {
                    if ( !$widthCheck && $twin.width() != $textarea.width() ) {
                        $twin.width($textarea.width());
                        $widthCheck = true;
                    }
                }
				
                // This function will update the height of the textarea if necessary 
                function update() {
                    // reset the width if needed
                    resetWidth();
                                        
                    // Get curated content from the textarea.
                    var textareaContent = $textarea.val().replace(/&/g,'&amp;').replace(/  /g, '&nbsp;').replace(/<|>/g, '&gt;').replace(/\n/g, '<br />');
					
                    // Compare curated content with curated twin.
                    var twinContent = $twin.html().replace(/<br>/ig,'<br />');
					
                    if(textareaContent+'&nbsp;' != twinContent || forceUpdating){
					
                        // Add an extra white space so new rows are added when you are at the end of a row.
                        $twin.html(textareaContent+'&nbsp;');
						
                        var twinheight = $twin.height(),
                            originalHeight = $twin.data('original-height');

                        // Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
                        if(Math.abs(twinheight + lineHeight - $textarea.height()) > 3) {

                            var goalheight = twinheight + lineHeight;

                            if ((twinheight - originalHeight) < 3) {
                                goalheight = originalHeight;
                            }
                                                        
                            if(goalheight >= maxheight) {
                                setHeightAndOverflow(maxheight,'auto');
                            } else if(goalheight <= minheight) {
                                setHeightAndOverflow(minheight,'hidden');
                            } else {
                                setHeightAndOverflow(goalheight,'hidden');
                            }	
                        }
						
                    }
					
                }
				
                // Hide scrollbars
                $textarea.css({
                    'overflow':'hidden'
                }).bind('keyup change cut paste', function(){
                    // Update textarea size on keyup, change, cut and paste
                    update(false); 
                }).bind('click',function(){
                    //add mouse click = textarea entering event
                    update(true);
                }).bind('blur',function(){
                    // Compact textarea on blur
                    // Lets animate this....
                    if( forceUpdating )
                    {
                        update(true);
                        return;
                    }
                    var twinheight = $twin.height();
                    if( twinheight < maxheight){
                        if(twinheight > minheight) {
                            $textarea.height(twinheight);
                        } else {
                            $textarea.height(minheight);
                        }
                    }
                }).live('input paste',function(e){
                    // And this line is to catch the browser paste event
                    setTimeout(update, 250);
                });				

                // Run update once when elastic is initialized
                update(true);
				
            });
	
        } 
    }); 
})(jQuery);
