
(function($) {

    var limitFn = null;

    $.fn.addCharCounter = function(targetId_, maxLength_) {

        var inputElement = this;

        var targetId = targetId_;

        var maxLength = maxLength_;

        function start() {
            updateMaxLength();
            addChangeListeners();
            updateCharsLeft();
        }

        function updateMaxLength() {
            if (maxLength != undefined) {
                return;   
            }
            maxLength = inputElement.attr('maxlength');
            if (maxLength == undefined) {
                throw Error('Error getting max length for ' + inputElement[0]);
            }
        }

        function addChangeListeners() {
            if (inputElement[0].tagName.toLowerCase() == 'textarea') {
                limitFn = function(event) { limitLength(event); };
                //inputElement.keypress(limitFn);
                inputElement.keyup(limitFn);
            }
            inputElement.everyTime('300 ms', function() { updateCharsLeft(); }, 0, true);
        }

        function limitLength(event) {
            var key = event.which;
            //all keys including return.
            if(key >= 32 || key == 13) {
                var length = inputElement.val().length;
                if(length >= maxLength) {
                    event.preventDefault();
                    inputElement.val(inputElement.val().substring(0, maxLength));
                }
            }
        }

        function updateCharsLeft() {
            var length = inputElement.val().length;
            $('#' + targetId).html(maxLength - length);
        }

        start();
        return this;
    };

    $.fn.removeCharCounter = function() {

        var inputElement = this;

        function removeChangeListeners() {
            if (limitFn) {
                inputElement.unbind('keypress', limitFn);
            }
            inputElement.stopTime();
        }

        removeChangeListeners();
        return this;
    };

})(jQuery);
