Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I wrote my first jQuery plugin. It counts characters in a similar way to what StackExchange uses for comment entries. You can see it in action with this fiddle.

I feel that it's messy, but I can't explain why. One of the default options is defined outside the defaults hash because it uses a self-reference, and the method for flashing the text seems out of place. I'm also a little worried about how it handles form submission, and its prevention when the minimum number of characters is not met.

I'm not very fluent with jQuery so I expect this to be atrocious. I would love to hear some feedback as to why, or how it could be improved.

The form is submitted via ajax, using Rails' unobtrusive js.

(function ($) {
    "use strict";

    $.fn.counter = function (options) {
        var defaults = {
            minimumSize: 15,
            minimumWarning: " more to go...",
            maximumSize: 25,
            maximumWarning: " characters remaining...",
            warningSize: 20,
            targetClass: '.help-block'
        };

        defaults.defaultText = "Enter at least " + defaults.minimumSize + " characters.";    
        options = $.extend(defaults, options);

        function count(elem) {
            var size = elem.val().length, target = elem.siblings(options.targetClass);
            if (size === 0) {
                target.html(options.defaultText);
            } else if (size < options.minimumSize) {
                target.html((options.minimumSize - size) + options.minimumWarning);
            } else if (size >= options.minimumSize && size < options.warningSize) {
                target.html('&nbsp;');
            } else if (size >= options.warningSize && size < options.maximumSize) {
                target.html((options.maximumSize - size) + options.maximumWarning);
            } else if (size >= options.maximumSize) {
                elem.val(elem.val().substring(0, options.maximumSize));
                target.html("0" + options.maximumWarning);
            }
        }

        this.each(function () {
            var elem = $(this);
            count(elem);
            elem.keyup(function () {
                count(elem);
            });
            elem.closest('form').submit(function () {
                if (elem.val().length < options.minimumSize) {
                    $(this).find(options.targetClass).fadeOut('fast').fadeIn('fast').fadeOut('fast').fadeIn('fast');
                    return false;
                }
            });
            return elem;
        });
    };
})(jQuery);
share|improve this question

1 Answer 1

up vote 1 down vote accepted

I suggest storing your defaults in a location that can be reached by the developers, and automatically filling in the minsize if minsize is included in the default text. For example,

(function ($) {
    "use strict";

    $.fn.counter = function (options) {
        options = $.extend($.fn.counter.defaults, options);

        function defaultText() {
            return options.defaultText.replace(/minsize/ig,options.minimumSize);
        }
        function count(elem) {
            var size = elem.val().length, target = elem.siblings(options.targetClass);
            if (size === 0) {
                target.html(defaultText());
            } else if (size < options.minimumSize) {
                target.html((options.minimumSize - size) + options.minimumWarning);
            } else if (size >= options.minimumSize && size < options.warningSize) {
                target.html('&nbsp;');
            } else if (size >= options.warningSize && size < options.maximumSize) {
                target.html((options.maximumSize - size) + options.maximumWarning);
            } else if (size >= options.maximumSize) {
                elem.val(elem.val().substring(0, options.maximumSize));
                target.html("0" + options.maximumWarning);
            }
        }

        this.each(function () {
            var elem = $(this);
            count(elem);
            elem.keyup(function () {
                count(elem);
            });
            elem.closest('form').submit(function () {
                if (elem.val().length < options.minimumSize) {
                    $(this).find(options.targetClass).fadeOut('fast').fadeIn('fast').fadeOut('fast').fadeIn('fast');
                    return false;
                }
            });
            return elem;
        });
    };

    $.fn.counter.defaults = {
        minimumSize: 15,
        minimumWarning: ' more to go...',
        maximumSize: 25,
        maximumWarning: ' characters remaining...',
        warningSize: 20,
        targetClass: '.help-block',
        defaultText: 'Enter at least minsize characters.'
    };
})(jQuery);
share|improve this answer
    
Thanks, that's a good idea! –  Mohamad Nov 27 '12 at 21:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.