├── package.json
├── examples
└── basic-jquery.html
├── LICENSE.txt
├── readme.md
├── sms_counter.js.coffee
├── sms_counter.min.js
└── sms_counter.js
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sms-counter",
3 | "version": "1.0.0",
4 | "description": "Character counter for SMS messages.",
5 | "main": "sms_counter.js",
6 | "directories": {
7 | "example": "examples"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+ssh://git@github.com/danxexe/sms-counter.git"
15 | },
16 | "keywords": [
17 | "sms",
18 | "sms-counter"
19 | ],
20 | "author": "Danilo R. Gonçalves",
21 | "license": "ISC",
22 | "bugs": {
23 | "url": "https://github.com/danxexe/sms-counter/issues"
24 | },
25 | "homepage": "https://github.com/danxexe/sms-counter#readme"
26 | }
27 |
--------------------------------------------------------------------------------
/examples/basic-jquery.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | danxexe/sms-counter sample
6 |
7 |
8 |
9 |
10 |
11 | - Encoding:
12 | - Length:
13 | - Messages:
14 | - Per Message:
15 | - Remaining:
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 danxexe
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | SMS Counter
2 | =============================
3 |
4 | Character counter for SMS messages.
5 |
6 |
7 | Usage
8 | ----------
9 |
10 | ```javascript
11 | SmsCounter.count('content of the SMS')
12 | ```
13 |
14 | This will return the following object:
15 |
16 | ```javascript
17 | {
18 | encoding: "GSM_7BIT",
19 | length: 18,
20 | messages: 1,
21 | per_message: 160,
22 | remaining: 142
23 | }
24 | ```
25 |
26 | jQuery Plugin
27 | ----------
28 |
29 | Given the following markup:
30 |
31 | ```html
32 |
33 |
34 | - Encoding:
35 | - Length:
36 | - Messages:
37 | - Per Message:
38 | - Remaining:
39 |
40 | ```
41 |
42 | You can use the `countSms` jQuery extension to update the count on keyup:
43 |
44 | ```javascript
45 | $('#message').countSms('#sms-counter')
46 | ```
47 |
48 |
49 | TODO
50 | ----
51 |
52 | - Better docs
53 |
54 |
55 | Known Issue
56 | ----
57 |
58 | (none)
59 |
60 |
61 | Other Languages
62 | ----
63 |
64 | - PHP: [https://github.com/acpmasquerade/sms-counter-php](https://github.com/acpmasquerade/sms-counter-php)
65 | - C#: [https://github.com/troll31/sms-counter-csharp](https://github.com/troll31/sms-counter-csharp)
66 |
67 |
68 | ## License
69 |
70 | SMS Counter is released under the [MIT License](LICENSE.txt).
--------------------------------------------------------------------------------
/sms_counter.js.coffee:
--------------------------------------------------------------------------------
1 | window.SmsCounter = class SmsCounter
2 |
3 | @gsm7bitChars = "@£$¥èéùìòÇ\\nØø\\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\\\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà"
4 | @gsm7bitExChar = "\\^{}\\\\\\[~\\]|€"
5 |
6 | @gsm7bitRegExp = RegExp("^[#{(@gsm7bitChars)}]*$")
7 | @gsm7bitExRegExp = RegExp("^[#{ (@gsm7bitChars)}#{(@gsm7bitExChar)}]*$")
8 | @gsm7bitExOnlyRegExp = RegExp("^[\\#{(@gsm7bitExChar)}]*$")
9 |
10 | @GSM_7BIT = 'GSM_7BIT'
11 | @GSM_7BIT_EX = 'GSM_7BIT_EX'
12 | @UTF16 = 'UTF16'
13 |
14 | @messageLength =
15 | GSM_7BIT: 160
16 | GSM_7BIT_EX: 160
17 | UTF16: 70
18 |
19 | @multiMessageLength =
20 | GSM_7BIT: 153
21 | GSM_7BIT_EX: 153
22 | UTF16: 67
23 |
24 | @count: (text) ->
25 | encoding = @detectEncoding(text)
26 |
27 | length = text.length
28 | length += @countGsm7bitEx(text) if encoding == @GSM_7BIT_EX
29 |
30 | per_message = @messageLength[encoding]
31 | per_message = @multiMessageLength[encoding] if length > per_message
32 |
33 | messages = Math.ceil(length / per_message)
34 | remaining = (per_message * messages) - length
35 | remaining = per_message if (remaining == 0 && messages == 0)
36 |
37 | count =
38 | encoding: encoding
39 | length: length
40 | per_message: per_message
41 | remaining: remaining
42 | messages: messages
43 |
44 | @detectEncoding: (text) ->
45 | switch
46 | when text.match(@gsm7bitRegExp)? then @GSM_7BIT
47 | when text.match(@gsm7bitExRegExp)? then @GSM_7BIT_EX
48 | else @UTF16
49 |
50 | @countGsm7bitEx: (text) ->
51 | chars = (char2 for char2 in text when char2.match(@gsm7bitExOnlyRegExp)?)
52 | chars.length
53 |
54 | if jQuery?
55 | $ = jQuery
56 | $.fn.countSms = (target) ->
57 | input = @
58 | target = $(target)
59 | count_sms = ->
60 | count = SmsCounter.count(input.val())
61 | for k, v of count
62 | target.find(".#{k}").text(v)
63 |
64 | @.on 'keyup', count_sms
65 | count_sms()
66 |
--------------------------------------------------------------------------------
/sms_counter.min.js:
--------------------------------------------------------------------------------
1 | !function(){var $,SmsCounter;window.SmsCounter=SmsCounter=function(){function SmsCounter(){}SmsCounter.gsm7bitChars="@£$¥èéùìòÇ\\nØø\\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\\\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà";SmsCounter.gsm7bitExChar="\\^{}\\\\\\[~\\]|€";SmsCounter.gsm7bitRegExp=RegExp("^["+SmsCounter.gsm7bitChars+"]*$");SmsCounter.gsm7bitExRegExp=RegExp("^["+SmsCounter.gsm7bitChars+SmsCounter.gsm7bitExChar+"]*$");SmsCounter.gsm7bitExOnlyRegExp=RegExp("^[\\"+SmsCounter.gsm7bitExChar+"]*$");SmsCounter.GSM_7BIT="GSM_7BIT";SmsCounter.GSM_7BIT_EX="GSM_7BIT_EX";SmsCounter.UTF16="UTF16";SmsCounter.messageLength={GSM_7BIT:160,GSM_7BIT_EX:160,UTF16:70};SmsCounter.multiMessageLength={GSM_7BIT:153,GSM_7BIT_EX:153,UTF16:67};SmsCounter.count=function(text){var count,encoding,length,messages,per_message,remaining;encoding=this.detectEncoding(text);length=text.length;if(encoding===this.GSM_7BIT_EX){length+=this.countGsm7bitEx(text)}per_message=this.messageLength[encoding];if(length>per_message){per_message=this.multiMessageLength[encoding]}messages=Math.ceil(length/per_message);remaining=per_message*messages-length;if(remaining == 0 && messages == 0){remaining = per_message; }return count={encoding:encoding,length:length,per_message:per_message,remaining:remaining,messages:messages}};SmsCounter.detectEncoding=function(text){switch(false){case text.match(this.gsm7bitRegExp)==null:return this.GSM_7BIT;case text.match(this.gsm7bitExRegExp)==null:return this.GSM_7BIT_EX;default:return this.UTF16}};SmsCounter.countGsm7bitEx=function(text){var char2,chars;chars=function(){var _i,_len,_results;_results=[];for(_i=0,_len=text.length;_i<_len;_i++){char2=text[_i];if(char2.match(this.gsm7bitExOnlyRegExp)!=null){_results.push(char2)}}return _results}.call(this);return chars.length};return SmsCounter}();if(typeof jQuery!=="undefined"&&jQuery!==null){$=jQuery;$.fn.countSms=function(target){var count_sms,input;input=this;target=$(target);count_sms=function(){var count,k,v,_results;count=SmsCounter.count(input.val());_results=[];for(k in count){v=count[k];_results.push(target.find("."+k).text(v))}return _results};this.on("keyup",count_sms);return count_sms()}}}.call(this);
--------------------------------------------------------------------------------
/sms_counter.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var $, SmsCounter;
3 |
4 | window.SmsCounter = SmsCounter = (function() {
5 | function SmsCounter() {}
6 |
7 | SmsCounter.gsm7bitChars = "@£$¥èéùìòÇ\\nØø\\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\\\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà";
8 |
9 | SmsCounter.gsm7bitExChar = "\\^{}\\\\\\[~\\]|€";
10 |
11 | SmsCounter.gsm7bitRegExp = RegExp("^[" + SmsCounter.gsm7bitChars + "]*$");
12 |
13 | SmsCounter.gsm7bitExRegExp = RegExp("^[" + SmsCounter.gsm7bitChars + SmsCounter.gsm7bitExChar + "]*$");
14 |
15 | SmsCounter.gsm7bitExOnlyRegExp = RegExp("^[\\" + SmsCounter.gsm7bitExChar + "]*$");
16 |
17 | SmsCounter.GSM_7BIT = 'GSM_7BIT';
18 |
19 | SmsCounter.GSM_7BIT_EX = 'GSM_7BIT_EX';
20 |
21 | SmsCounter.UTF16 = 'UTF16';
22 |
23 | SmsCounter.messageLength = {
24 | GSM_7BIT: 160,
25 | GSM_7BIT_EX: 160,
26 | UTF16: 70
27 | };
28 |
29 | SmsCounter.multiMessageLength = {
30 | GSM_7BIT: 153,
31 | GSM_7BIT_EX: 153,
32 | UTF16: 67
33 | };
34 |
35 | SmsCounter.count = function(text) {
36 | var count, encoding, length, messages, per_message, remaining;
37 | encoding = this.detectEncoding(text);
38 | length = text.length;
39 | if (encoding === this.GSM_7BIT_EX) {
40 | length += this.countGsm7bitEx(text);
41 | }
42 | per_message = this.messageLength[encoding];
43 | if (length > per_message) {
44 | per_message = this.multiMessageLength[encoding];
45 | }
46 | messages = Math.ceil(length / per_message);
47 | remaining = (per_message * messages) - length;
48 | if(remaining == 0 && messages == 0){
49 | remaining = per_message;
50 | }
51 | return count = {
52 | encoding: encoding,
53 | length: length,
54 | per_message: per_message,
55 | remaining: remaining,
56 | messages: messages
57 | };
58 | };
59 |
60 | SmsCounter.detectEncoding = function(text) {
61 | switch (false) {
62 | case text.match(this.gsm7bitRegExp) == null:
63 | return this.GSM_7BIT;
64 | case text.match(this.gsm7bitExRegExp) == null:
65 | return this.GSM_7BIT_EX;
66 | default:
67 | return this.UTF16;
68 | }
69 | };
70 |
71 | SmsCounter.countGsm7bitEx = function(text) {
72 | var char2, chars;
73 | chars = (function() {
74 | var _i, _len, _results;
75 | _results = [];
76 | for (_i = 0, _len = text.length; _i < _len; _i++) {
77 | char2 = text[_i];
78 | if (char2.match(this.gsm7bitExOnlyRegExp) != null) {
79 | _results.push(char2);
80 | }
81 | }
82 | return _results;
83 | }).call(this);
84 | return chars.length;
85 | };
86 |
87 | return SmsCounter;
88 |
89 | })();
90 |
91 | if (typeof jQuery !== "undefined" && jQuery !== null) {
92 | $ = jQuery;
93 | $.fn.countSms = function(target) {
94 | var count_sms, input;
95 | input = this;
96 | target = $(target);
97 | count_sms = function() {
98 | var count, k, v, _results;
99 | count = SmsCounter.count(input.val());
100 | _results = [];
101 | for (k in count) {
102 | v = count[k];
103 | _results.push(target.find("." + k).text(v));
104 | }
105 | return _results;
106 | };
107 | this.on('keyup', count_sms);
108 | return count_sms();
109 | };
110 | }
111 |
112 | }).call(this);
113 |
--------------------------------------------------------------------------------