2 * jQuery Simply Countable plugin
3 * Provides a character counter for any text input or textarea
6 * @homepage http://github.com/aaronrussell/jquery-simply-countable/
7 * @author Aaron Russell (http://www.aaronrussell.co.uk)
9 * Copyright (c) 2009-2010 Aaron Russell (aaron@gc4.co.uk)
10 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
11 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
16 $.fn
.simplyCountable = function(options
){
20 countType
: 'characters',
24 countDirection
: 'down',
27 thousandSeparator
: ',',
28 onOverCount: function(){},
29 onSafeCount: function(){},
30 onMaxCount: function(){}
34 var counter
= $(options
.counter
);
35 if (!counter
.length
) { return false; }
36 regex
= new RegExp('['+options
.wordSeparator
+']+');
38 var countCheck = function(){
43 var reverseCount = function(ct
){
44 return ct
- (ct
*2) + options
.maxCount
;
47 var countInt = function(){
48 return (options
.countDirection
=== 'up') ? revCount
: count
;
51 var numberFormat = function(ct
){
53 if (options
.thousandSeparator
){
55 // Handle large negative numbers
60 for (var i
= ct
.length
-3; i
> 0; i
-= 3){
61 ct
= ct
.substr(0,i
) + options
.thousandSeparator
+ ct
.substr(i
);
67 /* Calculates count for either words or characters */
68 if (options
.countType
=== 'words'){
69 count
= options
.maxCount
- $.trim(countable
.val()).split(regex
).length
;
70 if (countable
.val() === ''){ count
+= 1; }
72 else { count
= options
.maxCount
- countable
.val().length
; }
73 revCount
= reverseCount(count
);
75 /* If strictMax set restrict further characters */
76 if (options
.strictMax
&& count
<= 0){
77 var content
= countable
.val();
78 if (count
< 0 || content
.match(new RegExp('['+options
.wordSeparator
+']$'))) {
79 options
.onMaxCount(countInt(), countable
, counter
);
81 if (options
.countType
=== 'words'){
82 countable
.val(content
.split(regex
).slice(0, options
.maxCount
).join(options
.wordSeparator
));
84 else { countable
.val(content
.substring(0, options
.maxCount
)); }
85 count
= 0, revCount
= options
.maxCount
;
88 counter
.text(numberFormat(countInt()));
90 /* Set CSS class rules and API callbacks */
91 if (!counter
.hasClass(options
.safeClass
) && !counter
.hasClass(options
.overClass
)){
92 if (count
< 0){ counter
.addClass(options
.overClass
); }
93 else { counter
.addClass(options
.safeClass
); }
95 else if (count
< 0 && counter
.hasClass(options
.safeClass
)){
96 counter
.removeClass(options
.safeClass
).addClass(options
.overClass
);
97 options
.onOverCount(countInt(), countable
, counter
);
99 else if (count
>= 0 && counter
.hasClass(options
.overClass
)){
100 counter
.removeClass(options
.overClass
).addClass(options
.safeClass
);
101 options
.onSafeCount(countInt(), countable
, counter
);
107 countable
.keyup(countCheck
);
108 countable
.bind('paste', function(){
109 // Wait a few miliseconds for the pasting
110 setTimeout(countCheck
, 5);