/*

* jQuery Textarea Characters Counter Plugin v 2.0
* Examples and documentation at: http://roy-jin.appspot.com/jsp/textareaCounter.jsp
* Copyright (c) 2010 Roy Jin
* Version: 2.0 (11-JUN-2010)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* Requires: jQuery v1.4.2 or later
*/

(function($){

$.fn.textareaCount = function(options, fn) {   
        var defaults = {  
                maxCharacterSize: -1,  
                originalStyle: 'originalTextareaInfo',
                warningStyle: 'warningTextareaInfo',  
                warningNumber: 20,
                displayFormat: '#input characters | #words words'
        };  
        var options = $.extend(defaults, options);
        var container = $(this);
        $("<div class='charleft'>&nbsp;</div>").insertAfter(container);
        //create charleft css
        var charLeftCss = {
                'width' : container.width()
        };
        var charLeftInfo = getNextCharLeftInformation(container);
        charLeftInfo.addClass(options.originalStyle);
        charLeftInfo.css(charLeftCss);
        var numInput = 0;
        var maxCharacters = options.maxCharacterSize;
        var numLeft = 0;
        var numWords = 0;
        container.bind('keyup', function(event){limitTextAreaByCharacterCount();})
                         .bind('mouseover', function(event){setTimeout(function(){limitTextAreaByCharacterCount();}, 10);})
                         .bind('paste', function(event){setTimeout(function(){limitTextAreaByCharacterCount();}, 10);});
        function limitTextAreaByCharacterCount(){
                charLeftInfo.html(countByCharacters());
                //function call back
                if(typeof fn != 'undefined'){
                        fn.call(this, getInfo());
                }
                return true;
        }
        function countByCharacters(){
                var content = container.val();
                var contentLength = content.length;
                //Start Cut
                if(options.maxCharacterSize > 0){
                        //If copied content is already more than maxCharacterSize, chop it to maxCharacterSize.
                        if(contentLength >= options.maxCharacterSize) {
                                content = content.substring(0, options.maxCharacterSize);                               
                        }
                        var newlineCount = getNewlineCount(content);
                        // newlineCount new line character. For windows, it occupies 2 characters
                        var systemmaxCharacterSize = options.maxCharacterSize - newlineCount;
                        if (!isWin()){
                                 systemmaxCharacterSize = options.maxCharacterSize
                        }
                        if(contentLength > systemmaxCharacterSize){
                                //avoid scroll bar moving
                                var originalScrollTopPosition = this.scrollTop;
                                container.val(content.substring(0, systemmaxCharacterSize));
                                this.scrollTop = originalScrollTopPosition;
                        }
                        charLeftInfo.removeClass(options.warningStyle);
                        if(systemmaxCharacterSize - contentLength <= options.warningNumber){
                                charLeftInfo.addClass(options.warningStyle);
                        }
                        numInput = container.val().length + newlineCount;
                        if(!isWin()){
                                numInput = container.val().length;
                        }
                        numWords = countWord(getCleanedWordString(container.val()));
                        numLeft = maxCharacters - numInput;
                } else {
                        //normal count, no cut
                        var newlineCount = getNewlineCount(content);
                        numInput = container.val().length + newlineCount;
                        if(!isWin()){
                                numInput = container.val().length;
                        }
                        numWords = countWord(getCleanedWordString(container.val()));
                }
                return formatDisplayInfo();
        }
        function formatDisplayInfo(){
                var format = options.displayFormat;
                format = format.replace('#input', numInput);
                format = format.replace('#words', numWords);
                //When maxCharacters <= 0, #max, #left cannot be substituted.
                if(maxCharacters > 0){
                        format = format.replace('#max', maxCharacters);
                        format = format.replace('#left', numLeft);
                }
                return format;
        }
        function getInfo(){
                var info = {
                        input: numInput,
                        max: maxCharacters,
                        left: numLeft,
                        words: numWords
                };
                return info;
        }
        function getNextCharLeftInformation(container){
                        return container.next('.charleft');
        }
        function isWin(){
                var strOS = navigator.appVersion;
                if (strOS.toLowerCase().indexOf('win') != -1){
                        return true;
                }
                return false;
        }
        function getNewlineCount(content){
                var newlineCount = 0;
                for(var i=0; i<content.length;i++){
                        if(content.charAt(i) == '\n'){
                                newlineCount++;
                        }
                }
                return newlineCount;
        }
        function getCleanedWordString(content){
                var fullStr = content + " ";
                var initial_whitespace_rExp = /^[^A-Za-z0-9]+/gi;
                var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, "");
                var non_alphanumerics_rExp = rExp = /[^A-Za-z0-9]+/gi;
                var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " ");
                var splitString = cleanedStr.split(" ");
                return splitString;
        }
        function countWord(cleanedWordString){
                var word_count = cleanedWordString.length-1;
                return word_count;
        }
};

})(jQuery);