2
\$\begingroup\$

I'm not great with JavaScript. I've written a small jQuery function and I've now got it working, but I just wanted to check if the code looks good or if it can be improved.

I wanted a function so that I can easily add the function to any textarea and input so that it counts characters remaining and so I can just change the max count value so I don't have to keep writing out the whole thing for every input/textarea. I want it to show the max count on focus, add a css warn class to it when it is the last 10, and add a css max-reached class to it when the count has exceeded. Here it is:

var jq = jQuery.noConflict();
jQuery( document ).ready( function() {  

    jq.fn.cmCharactersLeft = function(options) {        

        // defaults
        var defaults = {    
            maxLength: 300,
            selector: '#testform .text-count'
        }; 

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

        jq(this).keyup(function() { 

            // character length variable
            var character_length = jq(this).val().length;

            // Characters left
            if( character_length <= options.maxLength ){
               jq( options.selector ).html( options.maxLength - character_length ).removeClass('max-reached count-warn');
            }
            // Characters left last 10
            if ( character_length >= ( options.maxLength - 10 ) ){
                jq( options.selector ).html( options.maxLength - character_length ).addClass('count-warn').removeClass('max-reached');
            }
            // Max characters reached
            if ( character_length > options.maxLength ){
               jq( options.selector ).html( options.maxLength - character_length ).addClass('max-reached').removeClass('count-warn');;
            }               
        });

        // show 'characters left' on focus too
        jq(this).focus(function() {

            // character length variable
            var character_length = jq(this).val().length;

            // Characters left
            if( character_length < 1 ){
                jq( options.selector ).html( options.maxLength );
            }
        });

    }

});

Then I can use the above function for any textarea/input:

jQuery( document ).ready( function() {  
    jq('#form1 textarea').cmCharactersLeft({
        maxLength: 50,
        selector: '#form1 .text-count'
    }); 
});

jQuery( document ).ready( function() {  
    jq('#form2 textarea').cmCharactersLeft({
        maxLength: 200,
        selector: '#form2 .text-count'
    }); 
});

Example HTML:

<form id="form1">
<textarea></textarea>
<span class="text-count"></span>
<button type="submit">Submit</button>
</form>

Edit

Or, what would be a better way to write this?

\$\endgroup\$
2
\$\begingroup\$

You're misusing what jQuery.noConflict does.

var jq = jQuery.noConflict();

You're using it like it creates another instance of jQuery, or something similar.

What it actually does is relinquish control of the $ variable.

Due to other libraries using $, jQuery needs to be able to return and reset what $ originally was.

Imagine this:

var $ = function(){ console.log(arguments) }; //A debugging function.

//Induction of jQuery here.

$('body'); //Returns a node containing the DOM body element.
$.noConflict();
$('body'); //Returns ['body'].

You're using it wrong.


Using jQuery

jQuery is a framework used by many to simplify processes, but do you really need it?

An important question to ask yourself when designing / architecting a new system is whether you need a library or not.

If you're building a slick, lightning-fast mobile site, you may not have room for massive libraries like jQuery.

Luckily, people realise this and write helpful companion sites you can use like YouMightNotNeedjQuery.com

Consider carefully whether it's better to write a little more code and not use jQuery, or whether it's better to lose a little performance.


Bracket spacing

You shouldn't be adding spaces inside your brackets like the following example:

jQuery( document ).ready( function() {  

It should look like:

jQuery(document).ready(function(){
\$\endgroup\$
  • \$\begingroup\$ I have a WordPress Website and I use plugins that use JQuery, so jquery.js is loaded on each page anyway. The reason why I used jQuery.noConflict() and replaced '$' with 'jq' was because it wasn't working without it. I followed this to fix it: api.jquery.com/jquery.noconflict \$\endgroup\$ – user3438958 Jan 3 '16 at 15:38
  • \$\begingroup\$ Using jQuery everywhere instead of jq should work anyway. \$\endgroup\$ – Quill Jan 3 '16 at 15:41
  • \$\begingroup\$ +1 I've never seen that "YouMightNotNeedjQuery.com" site before, thank you for enlightening me! \$\endgroup\$ – Alex L Jan 3 '16 at 16:54
  • \$\begingroup\$ Notice that, instead of spelling jQuery everywhere, it is better to use (function($){ [code] })(jQuery);. and call $. \$\endgroup\$ – Ismael Miguel Jan 3 '16 at 17:05
  • 1
    \$\begingroup\$ It's not necessarily better, just an alternate way of doing it. Technically, $ is shorthand for jQuery anyway \$\endgroup\$ – Quill Jan 3 '16 at 17:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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