44

How can I make a "remaining characters" countdown like the one on Twitter with jQuery? And also limit the input to a textarea.

DiMono
  • 3,308
  • 2
  • 19
  • 40
argon
  • 457
  • 1
  • 5
  • 4
  • 4
    Duplicate of http://stackoverflow.com/questions/1250748/countdown-available-spaces-in-a-textarea-with-jquery-or-other – adrianbanks Jan 26 '10 at 00:05

9 Answers9

86

Make a span and textarea and give them unique selectors (using an ID or class) like so:

<textarea class="message" rows="2" cols="30"></textarea>
<span class="countdown"></span>

And then make an update function like so:

function updateCountdown() {
    // 140 is the max message length
    var remaining = 140 - jQuery('.message').val().length;
    jQuery('.countdown').text(remaining + ' characters remaining.');
}

And make that function run when the page is loaded and whenever the message is changed:

jQuery(document).ready(function($) {
    updateCountdown();
    $('.message').change(updateCountdown);
    $('.message').keyup(updateCountdown);
});

Visit an example and view the source. jQuery makes things like this very simple.

Brian McKenna
  • 45,528
  • 6
  • 61
  • 60
  • 2
    +1, good usage of jsbin. it'd be nice if all examples used it. – Corey Ballou Jan 26 '10 at 01:17
  • 8
    It's better to use $('.message').live('input', updateCountdown) than those two methods. The change event won't trigger the function until you click outside the box or another event fires. live on input will catch any event on the text field. – Nathan Wallace Dec 31 '12 at 21:38
  • 9
    `.live()` is now deprecated, use `.on()` to attach events handlers: `$('.message').on('input', function() {...})` – Quentin Dec 16 '13 at 10:24
  • I personally prefer to access elements from a data-* instead of a class name as the latter seems little more brittle – Neil Feb 03 '16 at 13:52
  • It would be totally awesome if you would set maxlength on the textarea and the function took that value as the maxim instead of a hardcoded 140. – Ogier Schelvis Jun 14 '16 at 15:11
  • @OgierSchelvis that's relatively trivial to implement... add `maxlength` attribute to the `textarea`, give it an `id`, and use `document.getElementById("").getAttribute("maxlength");` – Nelson Jun 28 '16 at 02:19
  • @Nelson Already did that in my own implementation when searching for this question. I just used jQuery though. I know it's fun mxing up vanilla javascript with jQuery just because you can but I prefer convenience lol – Ogier Schelvis Jun 28 '16 at 07:04
  • Neither `getElementById` nor `getAttribute` have cross-browser support issues, so calling jQuery to do this is pretty excessive. I'm far more familiar with native JS than jQuery, so I lean towards that. I guess discussing vanilla vs jQuery is out of scope for a comment, but [this question](http://programmers.stackexchange.com/questions/166273/advantages-of-using-pure-javascript-over-jquery) should cover this topic nicely. – Nelson Jun 28 '16 at 07:13
  • jsbin no longer works I created a jsfiddle https://jsfiddle.net/f81jq0hn/ – FullStack Aug 10 '16 at 08:52
18

I've used Aaron Russell's simply countable jQuery plugin with success; though, if I were to have written it, I would have designed it a bit differently (automatic counter div creation, using a data-maxlength attribute instead of a plugin option, etc).

Simple usage:

$('#my_textarea').simplyCountable();

Advanced usage:

$('#my_textarea').simplyCountable({
    counter: '#counter',
    countable: 'characters',
    maxCount: 140,
    strictMax: false,
    countDirection: 'down',
    safeClass: 'safe',
    overClass: 'over',
    thousandSeparator: ','
});
Ryan McGeary
  • 235,892
  • 13
  • 95
  • 104
8

It's a suicide to use jQuery, Mootools or similar for such simple task ... unless you are already using them for something else.

Simple javascript function:

function limitTextCount(limitField_id, limitCount_id, limitNum)
{
    var limitField = document.getElementById(limitField_id);
    var limitCount = document.getElementById(limitCount_id);
    var fieldLEN = limitField.value.length;

    if (fieldLEN > limitNum)
    {
        limitField.value = limitField.value.substring(0, limitNum);
    }
    else
    {
        limitCount.innerHTML = (limitNum - fieldLEN) + ' charachter(s) to go.';
    }
}

The first parameter is id of the input/textarea. The second - id of the div to display characters left. The third is the limit itself.

And simple HTML:

<input type="text" value="" name="title" id="title" maxlength="100" onkeyup="limitTextCount('title', 'divcount', 100);" onkeydown="limitTextCount('title', 'divcount', 100);">
<br>
<div id="divcount">100 charachter(s) to go..</div>
Nikolay Ivanov
  • 5,159
  • 1
  • 26
  • 22
  • 2
    is it suicide if you're already using jQuery in other ways on the same page? I'm assuming you're just saying that it's just bad to load it when you don't need it. – toobulkeh Jan 19 '14 at 23:38
  • Right, if you are already using jQuery or similar, go for such implementation, otherwise is suicide :-) – Nikolay Ivanov Jan 20 '14 at 07:23
4

I added a simple pluralize function, cus nobody likes bad grammar.

function pluralize(count, word){
  if (count == 1 || count == -1){
    return String(count) + ' ' + word;
  }else{
    return String(count) + ' ' + word + 's';
  }
}

function updateCountdown() {
    // 140 is the max message length
    var remaining = 140 - jQuery('#micropost_content').val().length;
    jQuery('.countdown').text(pluralize(remaining,'character') + ' remaining');
}

...
dstandish
  • 2,328
  • 18
  • 34
4

I Updated @Brian McKenna version for multiple textarea/textbox with maxlegth attribute.

Demo here

<textarea class="message" rows="2" cols="30" maxlength="60"></textarea>
<span class="countdown"></span>

<textarea class="message" rows="2" cols="30"  maxlength="100"></textarea>
<span class="countdown"></span>

On page load update all count.

jQuery(document).ready(function($) {
    updateCountdownAll();
    $('.message').live('input', updateCountdown);

});

Make two function for update count.

function updateCountdownAll() {
        $('.message').each(function () {
            updateCountdown(this);
        });
    }

    function updateCountdown(e) {

        var currentElement;
        if (e.target) {
            currentElement = e.target;
        }
        else {
            currentElement = e;
        }

        var maxLengh = $(currentElement).attr('maxlength');
        var remaining = maxLengh - $(currentElement).val().length;
        $(currentElement).nextAll('.countdown:first').text(remaining + ' character(s) remaining.');
    }
Rikin Patel
  • 8,848
  • 7
  • 70
  • 78
3

We ended up doing a custom JS solution that operates on any input with class "limited". It uses an HTML5 custom data attribute ("data-maxlength") to specify the length. Of course, this is not nearly as full-featured as the plugin Ryan mentioned. But we needed multiple, dynamically added counters which didn't seem to be supported by the plugin. Hope that helps.

function addCharacterCount(input) {
  var $input    = $(input),                                                                     
      maxLength = $input.data('maxlength'),
      remaining = maxLength - $input.val().length;                                              
  $('<label><input type="text" id="' + input.id + '-counter" size="3" value="' + remaining + '" /> Characters remaining (max ' + maxLength + ')</label>').insertAfter(input);
}

$('form .limited').each(function () {                                                           
  addCharacterCount(this);                                                                      
}); 

$('form .limited').live('keyup', function() {                                                   
  var $element = $(this),
      maxLength = $element.data('maxlength');
  $("#" + this.id + "-counter").val(maxLength - $element.val().length);
});
Mat Schaffer
  • 1,634
  • 1
  • 15
  • 24
1

HTML:

<form>
    <!-- remember to markup your forms properly using labels! -->
    <label for="textareaChars">No more than 100 characters</label>

    <textarea id="textareaChars" maxlength="100"></textarea>

    <p><span id="chars">100</span> characters remaining</p>

</form>

JS:

$( document ).ready(function() {
    var maxLength = 100;
    $('textarea').keyup(function() {
        var length = $(this).val().length;
        var length = maxLength-length;
        $('#chars').text(length);
    });
});
1

In my implementation, I added the following JS function:

function charactersRemaining(elementID, messageElementID, maxCharacters)
{
    var remaining = maxCharacters - $('#' + elementID).val().length;
    $('#' + messageElementID).text(remaining + ' characters remaining.');
}

Then I could reuse that function all over the application (for example, if I had the following HTML):

<textarea class="form-control" asp-for="Comments" rows="3"></textarea>
<span id="commentsCharsRemaining" class="text-primary"></span>

Just add these 2 jquery statements to make it work:

$('#Comments').change(function () {
    charactersRemaining('Comments', 'commentsCharsRemaining', 2000)
});
$('#Comments').keyup(function () {
    charactersRemaining('Comments', 'commentsCharsRemaining', 2000)
});
Brian Edwards
  • 413
  • 7
  • 15
0

use jquery

save this as jquery.textlimiter.js

(function($) {
    $.fn.extend( {
        limiter: function(limit, elem) {
            $(this).on("keyup focus", function() {
                setCount(this, elem);
            });
            function setCount(src, elem) {
                var chars = src.value.length;
                if (chars > limit) {
                    src.value = src.value.substr(0, limit);
                    chars = limit;
                }
                elem.html( limit - chars );
            }
            setCount($(this)[0], elem);
        }
    });
})(jQuery);

usage

<textarea id="text" maxlength="100" cols="50" rows="5" placeholder="Enter Text"></textarea>
    <div id="chars">100</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="path/to/jquery.textlimiter.js"></script>
<script>
$(document).ready( function() {
    var elem = $("#chars");
    $("#text").limiter(100, elem);
});
</script>
Sujay sreedhar
  • 3,498
  • 2
  • 21
  • 28