0

I've been working on adding a character counter to a TEXTAREA field. There are many, many solutions available online for this task.

"Stop-at-Zero" Solution
The problem I'm having is that practically all solutions terminate user input at 0. That's effective, I guess, but it's not optimal in terms of user-friendliness. For example, if a user pastes text into the TEXTAREA, and the text exceeds the field's limitation, this stop-at-zero solution will abruptly truncate the excess text. The user then has to work to find the missing content and then edit their message, submit a second form, or some other burden.

"Negative Character Count" Solution
Other solutions allow the user to enter all they want. The character counter will go from positive to negative. The problem with these counters is lack of enforcement: They allow users to submit the form even with a negative character count.

Twitter Solution
I think Twitter has it right. They let users input all they want and highlight the excess text with a negative character count (and a colored background, which I don't need to have). They disable the submit button while the count is negative.

enter image description here

My (Incomplete) Solution
Working with third-party code I found through Google, I've devised a character counter that works perfectly in terms of the count. But being somewhat new to JS I haven't been able to code the enforcement part.

Here's my question:
How do I get the code to prevent submission of the form when the counter is a negative number?

HTML

<form action="" method="post">

<div>
<textarea name="comments" id="comments" cols="50" rows="10"></textarea>
</div>

<div>
<input type="submit">
</div>

</form>

CSS

form div {
    position: relative;
}

form .counter {
    position: absolute;
    left: 300px;
    bottom: -25px;
    font-size: 25px;
    font-weight: bold;
    color: #ccc;
    }

form .warning {color: orange;}

form .exceeded {color: red;}

JavaScript

<script src="/js/jquery.js"></script>

<script>

(function($) {

    $.fn.charCount = function(options){

        // default configuration properties
        var defaults = {    
            allowed: 100,       
            warning: 25,
            css: 'counter',
            counterElement: 'span',
            cssWarning: 'warning',
            cssExceeded: 'exceeded',
            counterText: ''
        }; 

        var options = $.extend(defaults, options); 

        function calculate(obj){
            var count = $(obj).val().length;
            var available = options.allowed - count;
            if(available <= options.warning && available >= 0){
                $(obj).next().addClass(options.cssWarning);
            } else {
                $(obj).next().removeClass(options.cssWarning);
            }
            if(available < 0){
                $(obj).next().addClass(options.cssExceeded);
            } else {
                $(obj).next().removeClass(options.cssExceeded);
            }
            $(obj).next().html(options.counterText + available);
        };

        this.each(function() {              
            $(this).after('<'+ options.counterElement +' class="' + options.css + '">'+ options.counterText +'</'+ options.counterElement +'>');
            calculate(this);
            $(this).keyup(function(){calculate(this)});
            $(this).change(function(){calculate(this)});
        });

    };

})(jQuery);

</script>

<script>
    $(document).ready(function(){   
        $("#comments").charCount();
    });
</script>

https://jsfiddle.net/nyc212/sk5kfopw/

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701

2 Answers2

1

I would try either by disabling the submit button using the disabled attribute, or preventing the form from submitting using e.preventDefault. I updated your fiddle...just uncomment either of the options

https://jsfiddle.net/sk5kfopw/1/

ACruz
  • 101
  • 2
  • Thanks for this response. One glitch I discovered with the disabled option is that once the excess characters are deleted and the character counter is back in positive territory, the submit button remains disabled. – Michael Benjamin Apr 12 '15 at 01:31
  • 1
    @mbnyc ah right sorry. You would have to remove the disabled attribute once if the character count falls back into the acceptable range. Here is the updated fiddle: https://jsfiddle.net/sk5kfopw/3/ – ACruz Apr 12 '15 at 20:49
1

I have modified your plugin to take the submit button as first parameter. If you want it to be more dynamic:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <title></title>
 <style>
  form div {
   position: relative;
  }

  form .counter {
   position: absolute;
   left: 300px;
   bottom: -25px;
   font-size: 25px;
   font-weight: bold;
   color: #ccc;
  }

  form .warning {
   color: orange;
  }

  form .exceeded {
   color: red;
  }
 </style>
 <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
 <script>
  (function($) {

   $.fn.charCount = function(btnsub, options){
   
    this.btnsub = btnsub;
        
    // default configuration properties
    var defaults = { 
     allowed: 100,  
     warning: 25,
     css: 'counter',
     counterElement: 'span',
     cssWarning: 'warning',
     cssExceeded: 'exceeded',
     counterText: ''
    }; 
   
    var options = $.extend(defaults, options); 
  
    function calculate(obj,btnsub){
    
     btnsub.attr("disabled", "disabled");

     var count = $(obj).val().length;
     var available = options.allowed - count;
     if(available <= options.warning && available >= 0){
      $(obj).next().addClass(options.cssWarning);
     } else {
      $(obj).next().removeClass(options.cssWarning);
     }
     if(available < 0){
      $(obj).next().addClass(options.cssExceeded);
     } else {
      $(obj).next().removeClass(options.cssExceeded);
      btnsub.removeAttr("disabled");
     }
     
     $(obj).next().html(options.counterText + available);
    };
    
    this.each(function() {     
     $(this).after('<'+ options.counterElement +' class="' + options.css + '">'+ options.counterText +'</'+ options.counterElement +'>');
     
     calculate(this, btnsub);

     $(this).keyup(function(){calculate(this,btnsub)});
     $(this).change(function(){calculate(this,btnsub)});
    });
   
   };

  })(jQuery);

  $(document).ready(function(){ 
   $("#comments").charCount($("#btnsub"));
  });

 </script>
</head>
<body>
 <form method="post">

  <div>
   <textarea name="comments" id="comments" cols="50" rows="10"></textarea>
  </div>

  <div>
   <input type="submit" id="btnsub">
  </div>

 </form>
</body>
</html>
Legends
  • 21,202
  • 16
  • 97
  • 123