Reputation: 31
I have this script to limit the words on a textarea but I want to use the same function to a form that contains multiple textarea tags.
What is the best way to reuse this and make an independent word counter and limiter for every textarea tag in the same form?
Thanks a lot in advance.
var wordLimit = 5;
var words = 0;
var jqContainer = $(".my-container");
var jqElt = $(".my-textarea");
function charLimit()
{
var words = 0;
var wordmatch = jqElt.val().match(/[^\s]+\s+/g);
words = wordmatch?wordmatch.length:0;
if (words > wordLimit) {
var trimmed = jqElt.val().split(/(?=[^\s]\s+)/, wordLimit).join("");
var lastChar = jqElt.val()[trimmed.length];
jqElt.val(trimmed + lastChar);
}
$('.word-count', jqContainer).text(words);
$('.words-left', jqContainer).text(Math.max(wordLimit-words, 0));
}
jqElt.on("keyup", charLimit);
charLimit();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="my-container">
<textarea class="my-textarea"></textarea>
<span class="words-left"></span> words left
<div>
Upvotes: 0
Views: 293
Reputation: 590
This is how I will normally do it:
refreshMaxWords()
<textarea data-max-words="5"></textarea>
(function($) {
var refreshMaxWords = function ($el) {
var wordLimit = parseInt($el.data('max-words')) || false,
wordmatch = $el.val().match(/[^\s]+\s+/g),
words = wordmatch ? wordmatch.length : 0,
// You can change how to get the "words-left" div here
$wordsLeft = $el.parent().find('.words-left');
if (wordLimit !== false) {
if (words > wordLimit) {
var trimmed = $el.val().split(/(?=[^\s]\s+)/, wordLimit).join("");
var lastChar = $el.val()[trimmed.length];
$el.val(trimmed + lastChar);
}
}
if ($wordsLeft.length > 0) {
$wordsLeft.html(Math.max(wordLimit - words, 0));
}
};
$(function () {
$(document).on('keyup.count-words', '[data-max-words]', function (e) {
refreshMaxWords($(this));
});
});
})(jQuery);
This is with assumption of HTML that looks like the following:
<div class="form-group">
<label>Input #1</label>
<textarea class="form-control" data-max-words="5"></textarea>
<p class="help-block"><span class="words-left">5</span> words left.</p>
</div>
<div class="form-group">
<label>Input #2</label>
<textarea class="form-control" data-max-words="10"></textarea>
<p class="help-block"><span class="words-left">10</span> words left.</p>
</div>
The benefits of this approach are:
Notes: You don't really need to wrap the javascript in
(function($) {
// your code here
})(jQuery);
I like doing it because it ensures that there won't be any conflict by accident.
Upvotes: 0
Reputation: 86
if you need to use that same implementation you could add an id to each text area you are going to put in the form, then add an attribute for=
to the corresponding spans pointing to the corresponding text area like this:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="my-container">
<textarea id="textarea-1" class="my-textarea" onkeyup="charLimit(this)"></textarea>
<span for="textarea-1" class="words-left"></span> words left
<textarea id="textarea-2" class="my-textarea" onkeyup="charLimit(this)"></textarea>
<span class="words-left" for="textarea-2"></span> words left
<div>
var wordLimit = 5;
var words = 0;
var jqContainer = $(".my-container");
function charLimit(elem)
{
var elm = $(elem)
var words = 0;
var wordmatch = elm.val().match(/[^\s]+\s+/g);
words = wordmatch?wordmatch.length:0;
if (words > wordLimit) {
var trimmed = elm.val().split(/(?=[^\s]\s+)/, wordLimit).join("");
var lastChar = elm.val()[trimmed.length];
elm.val(trimmed + lastChar);
}
$('.word-count', jqContainer).text(words);
$('[for='+ elm.attr('id') +']', jqContainer).text(Math.max(wordLimit-words, 0));
}
Upvotes: 0
Reputation: 4350
You can use a generic function ($this
) is the textarea element changed.
For relative elements, you can use the function .next(selector)
Also you can read parameters from attributes (maxwords
for example).
var jqContainer = $(".my-container");
function charLimit()
{
var words = 0;
var jqElt=$(this);
var wordLimit = jqElt.attr("maxwords");
var words = 0;
var wordmatch = jqElt.val().match(/[^\s]+\s+/g);
words = wordmatch?wordmatch.length:0;
if (words > wordLimit) {
var trimmed = jqElt.val().split(/(?=[^\s]\s+)/, wordLimit).join("");
var lastChar = jqElt.val()[trimmed.length];
jqElt.val(trimmed + lastChar);
}
jqElt.next('.words-left').text(Math.max(wordLimit-words, 0));
}
$(".my-textarea", jqContainer).on("keyup", charLimit).keyup();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="my-container">
<textarea id="text1" class="my-textarea" maxwords="5"></textarea>
<span class="words-left"></span> words left
<textarea id="text1" class="my-textarea" maxwords="10"></textarea>
<span class="words-left"></span> words left
<div>
Upvotes: 1
Reputation: 7780
You can wrap your logic up in a function and reuse that function.
See example:
function wordCounter(container, limit) {
var wordLimit = limit;
var jqContainer = $(container);
var jqElt = $("textarea", jqContainer);
function charLimit()
{
var words = 0;
var wordmatch = jqElt.val().match(/[^\s]+\s+/g);
words = wordmatch?wordmatch.length:0;
if (words > wordLimit) {
var trimmed = jqElt.val().split(/(?=[^\s]\s+)/, wordLimit).join("");
var lastChar = jqElt.val()[trimmed.length];
jqElt.val(trimmed + lastChar);
}
$('.word-count', jqContainer).text(words);
$('.words-left', jqContainer).text(Math.max(wordLimit-words, 0));
}
jqElt.on("keyup", charLimit);
charLimit();
}
wordCounter(".my-container1", 5);
wordCounter(".my-container2", 10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="my-container1">
<textarea class="my-textarea"></textarea>
<span class="words-left"></span> words left
</div>
<div class="my-container2">
<textarea class="my-textarea"></textarea>
<span class="words-left"></span> words left
</div>
Note that you had an issue in your example where the div
tag wasn't closed.
Upvotes: 0