patternjavascriptMinor
Words Counter using the revealing module pattern
Viewed 0 times
thewordsmodulerevealingusingcounterpattern
Problem
Is the following a good way to use the revealing module pattern?
`$(document).ready(function() {
var wordsCounter = (function() {
function init() {
bindEvents();
}
// cache dom
var $textArea = $('#textArea');
var $words = $('#words'); //a span
var $chars = $('#chars'); //a span
function bindEvents() {
$textArea.on('keyup', updateWordsCount);
}
// $textArea keyup callback function
function updateWordsCount() {
var text = $textArea.val();
var numOfChars = text.length;
var numOfWords = countWords(text);
$chars.html(numOfChars);
$words.html(numOfWords);
}
// counts words for a given string
function countWords(str){
var cnt = 0;
var flag = true;
for(var i = 0; i
What are other good ways I can structure this code?
Also if i'm working on a larger project, should it all be in a one IIFE like this or should I divide it into more than one IIFE each one doing related things?
`$(document).ready(function() {
var wordsCounter = (function() {
function init() {
bindEvents();
}
// cache dom
var $textArea = $('#textArea');
var $words = $('#words'); //a span
var $chars = $('#chars'); //a span
function bindEvents() {
$textArea.on('keyup', updateWordsCount);
}
// $textArea keyup callback function
function updateWordsCount() {
var text = $textArea.val();
var numOfChars = text.length;
var numOfWords = countWords(text);
$chars.html(numOfChars);
$words.html(numOfWords);
}
// counts words for a given string
function countWords(str){
var cnt = 0;
var flag = true;
for(var i = 0; i
What are other good ways I can structure this code?
Also if i'm working on a larger project, should it all be in a one IIFE like this or should I divide it into more than one IIFE each one doing related things?
Solution
function bindEvents() {
$textArea.on('keyup', updateWordsCount);
}
// $textArea keyup callback function
function updateWordsCount() {
var text = $textArea.val();
var numOfChars = text.length;
var numOfWords = countWords(text);
$chars.html(numOfChars);
$words.html(numOfWords);
}The handler is unnecessarily split from the code that binds it. It's not often you see an event handler split off from it's binding. In most cases, the handler code is very specific to the binding, it cannot be reused and therefore makes no sense splitting off. Inline the handler instead.
var $textArea = $('#textArea');
var $words = $('#words'); //a span
var $chars = $('#chars'); //a spanI would discourage the use of
$ indicating that a variable is a jQuery instance. Whether it's a jQuery instance, or some other constructors instance, a variable is a variable regardless of what it's bound to.Another problem is that this piece of code isn't reusable. The selector uses an ID. IDs are supposed to be unique. That means this code can only bind to 3 unique elements, and no more. If you want to make this word counter reusable, use a class.
var flag = true;flag is a poorly named variable. It's not telling me what it's supposed to be, what it is for, and why it is there.// counts words for a given string
function countWords(str){
var cnt = 0;
var flag = true;
for(var i = 0; i < str.length; i++){
if(str[i] !== " " && flag){
flag = false;
cnt++;
}else if(str[i] === " "){
flag = true;
}
}
return cnt;
};I think this is overcomplicated. A simple word count can be done by exploding the string into array by spaces, and getting the length of the resulting array.
return str.split(' ').length what you are looking for.For this simple task, a jQuery "plugin" would do. I would expect the plugin to accept an element containing your input and output elements, and a set of options asking for which elements are the input and output inside that group.
jQuery.fn.wordCounter = function(options){
// For each found group
return this.each(function(){
// Look for the input and output under that group
var input = $(options.input, this);
var output = $(options.output, this);
// Counter event and handler
input.on('keyup', function(){
output.text(input.val().split(' ').filter(text => text !== '').length);
});
});
};
$('.input-group').wordCounter({
input: '.input-group__input',
output: '.input-group__count',
});
In larger scale projects, consider using a small framework. vue.js, Ractive.js and riot.js are good candidates for quick-and-easy UI-related operations.
Code Snippets
function bindEvents() {
$textArea.on('keyup', updateWordsCount);
}
// $textArea keyup callback function
function updateWordsCount() {
var text = $textArea.val();
var numOfChars = text.length;
var numOfWords = countWords(text);
$chars.html(numOfChars);
$words.html(numOfWords);
}var $textArea = $('#textArea');
var $words = $('#words'); //a span
var $chars = $('#chars'); //a spanvar flag = true;// counts words for a given string
function countWords(str){
var cnt = 0;
var flag = true;
for(var i = 0; i < str.length; i++){
if(str[i] !== " " && flag){
flag = false;
cnt++;
}else if(str[i] === " "){
flag = true;
}
}
return cnt;
};Context
StackExchange Code Review Q#140986, answer score: 2
Revisions (0)
No revisions yet.