I count characters using NobleCount and the following code:
$('#message').NobleCount('#messageInfo',{
max_chars: getMaxChars(),
on_negative: function(t_obj, char_area, c_settings, char_rem){
}
});
I want a feature like counting SMS, if the limit is reached the next 160 chars are for the second sms and so on. I can use parameters like on_update, on_positive, on_negative and block_negative.
I tried something using modulo but it does开发者_StackOverflow中文版 not work. Any ideas?
Beware that SMS is more complicated than you seem to indicate.
Standard "160-character" SMS uses a strange 7-bit encoding that covers most ASCII, some European accents, misc symbols such as €, some capital Greek letters (the ones that don't look like Roman characters).
If your message uses other characters, it can instead be encoded as Unicode using UCS-2 (like UTF-16 but only BMP), for a limit of 70 characters. Actually, the specification says UCS-2, but emoji (non-BMP Unicode) can be sent in SMS so that implies UTF-16 is being used, in which case each emoji must "use up" 2 characters out of the 70 total.
But some languages can use "national language shift tables" which use an alternative 7-bit encoding. Most notably Turkish, but also Spanish, Portuguese, and ten Indian sub-continent languages. These are relatively new additions to the standard.
Even in the 7-bit encoding, a few characters are "escaped" which means they "use up" 2 characters. In the default 7-bit encoding, these are: {}[]\|^~€
.
If your message goes beyond 160 characters, it can use "concatenated SMS", but then a small header is added to each message, meaning each segment only has room for something like 153 characters. There are two different versions of that header, of different sizes, thus it may not be 153 characters, but 152 (from memory). Similarly for Unicode concatenated SMS, the small header makes it 67 characters per segment.
Good luck with all that!
Firstly, character counting is very easy. You just need to use the length
property on a string. To count the number of SMS messages needed, you'll need to divide by 160 and round up (because 161 characters requires 2 messages). Your code should probably look something like this:
HTML:
<textarea name="message" value="" id="message"></textarea>
<p>
<span id="remaining">160 characters remaining</span>
<span id="messages">1 message(s)</span>
</p>
jQuery:
$(document).ready(function(){
var $remaining = $('#remaining'),
$messages = $remaining.next();
$('#message').keyup(function(){
var chars = this.value.length,
messages = Math.ceil(chars / 160),
remaining = messages * 160 - (chars % (messages * 160) || messages * 160);
$remaining.text(remaining + ' characters remaining');
$messages.text(messages + ' message(s)');
});
});
See jsFiddle example.
Here is small plugin for you. It is my first jQuery plugin i give it for free ;) you just need to start it with:
$('#smsText').smsArea();
The HTML:
<b id="smsCount"></b> SMS (<b id="smsLength"></b>) Characters left
<textarea id="smsText"></textarea>
The Javascript (updated 18.8.2014):
(function($){
$.fn.smsArea = function(options){
var
e = this,
cutStrLength = 0,
s = $.extend({
cut: true,
maxSmsNum: 3,
interval: 400,
counters: {
message: $('#smsCount'),
character: $('#smsLength')
},
lengths: {
ascii: [160, 306, 459],
unicode: [70, 134, 201]
}
}, options);
e.keyup(function(){
clearTimeout(this.timeout);
this.timeout = setTimeout(function(){
var
smsType,
smsLength = 0,
smsCount = -1,
charsLeft = 0,
text = e.val(),
isUnicode = false;
for(var charPos = 0; charPos < text.length; charPos++){
switch(text[charPos]){
case "\n":
case "[":
case "]":
case "\\":
case "^":
case "{":
case "}":
case "|":
case "€":
smsLength += 2;
break;
default:
smsLength += 1;
}
if(text.charCodeAt(charPos) > 127 && text[charPos] != "€") isUnicode = true;
}
if(isUnicode){
smsType = s.lengths.unicode;
}else{
smsType = s.lengths.ascii;
}
for(var sCount = 0; sCount < s.maxSmsNum; sCount++){
cutStrLength = smsType[sCount];
if(smsLength <= smsType[sCount]){
smsCount = sCount + 1;
charsLeft = smsType[sCount] - smsLength;
break
}
}
if(s.cut) e.val(text.substring(0, cutStrLength));
smsCount == -1 && (smsCount = s.maxSmsNum, charsLeft = 0);
s.counters.message.html(smsCount);
s.counters.character.html(charsLeft);
}, s.interval)
}).keyup()
}}(jQuery));
DEMO: http://jsfiddle.net/t32h0gj4/1/
NOTE: there are some basic options
$('#smsText').smsArea({cut:false}); //Do not cut the SMS
$('#smsText').smsArea({maxSmsNum:2}); //2 SMS Max
Once the message has been decoded as Craig McQueen stated in a this thread post and you have your actual character count, to count the needed SMS amount the following is enough:
function cntsms(len){ return len<=0? 0: (len>160? Math.ceil(len/153): 1); }
...I like one-row solutions so much.
I think the following script can produce more accurate calculation of SMS parts:
//field: a text box that contains the SMS Text
//cntField: a text box that will contain the remaining count of characters for each part
//smsCntfield: a text box that will contain the count of parts
//lang: 0 for English, 2 for Arabic
//maxLimit: Maximum count of characters to limit the TextBox, (ex: for 5 SMS in Arabic 331, in English 762
function textCounter(field, cntfield, smsCntfield, lang, maxlimit) {
part1Count = 0;
part2Count = 0;
part3Count = 0;
part4Count = 0;
part5Count = 0;
if (lang == 2) {
// Arabic
part1Count = 70;
part2Count = 63;
part3Count = 66;
part4Count = 66;
part5Count = 66;
} else if (lang == 0) {
// English
part1Count = 160;
part2Count = 145;
part3Count = 152;
part4Count = 152;
part5Count = 152;
}
smsCount = 0;
smsCharCnt = 0;
smsTotalCount = 0;
if (field.value.length <= part1Count) {
smsCount = 1;
smsCharCnt = part1Count;
smsTotalCount = part1Count;
} else if (field.value.length <= (part1Count + part2Count)) {
smsCount = 2;
smsCharCnt = part2Count;
smsTotalCount = (part1Count+part2Count);
} else if (field.value.length <= (part1Count+part2Count+part3Count)) {
smsCount = 3;
smsCharCnt = part3Count;
smsTotalCount = (part1Count+part2Count+part3Count);
} else if (field.value.length <= (part1Count+part2Count+part3Count+part4Count)) {
smsCount = 4;
smsCharCnt = part4Count;
smsTotalCount = (part1Count+part2Count+part3Count+part4Count);
} else if (field.value.length <= (part1Count+part2Count+part3Count+part4Count+part5Count)) {
smsCount = 5;
smsCharCnt = part5Count;
smsTotalCount = (part1Count+part2Count+part3Count+part4Count+part5Count);
}
if (field.value.length > maxlimit) {
// if too long...trim it!
field.value = field.value.substring(0, maxlimit);
} else {
cntfield.value = smsTotalCount - field.value.length;
smsCntfield.value = smsCount;
}
}
example use:
<html:textarea cols="30" rows="5" property="textEn"
title="Text English"
onkeydown="textCounter(document.form.textEn,document.form.remLen2,document.form.smsCount2,0,762)"
onkeyup="textCounter(document.form.textEn,document.form.remLen2,document.form.smsCount2,0,762)" />
<br>
<input type="text" readonly="readonly" name="remLen2"
size="3" maxlength="3" value="160"
title="Char Count">
(
<input type="text" readonly="readonly" name="smsCount2"
size="1" maxlength="1" value="1"
title="SMS Parts' />">
)
Every character from the extension table (GSM Extended Alphabet) is represented by two characters the actual maximum length is dynamically calculated as: 160 - k, where k is the number of extended characters used in the message.
You also have to consider the message length is 153 characters when concatenating messages with a 8bit reference number.
Unicode length is 70 characters, while concatenated 63 characters.
Based on the problems here, I try to write better solution. Adopted from several best answer here.
Javascript
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script>
$(document).ready(function(){
part1Count = 160;
part2Count = 145;
part3Count = 152;
$('#message').keyup(function(){
var chars = $(this).val().length;
messages = 0;
remaining = 0;
total = 0;
if (chars <= part1Count) {
messages = 1;
remaining = part1Count - chars;
} else if (chars <= (part1Count + part2Count)) {
messages = 2;
remaining = part1Count + part2Count - chars;
} else if (chars > (part1Count + part2Count)) {
moreM = Math.ceil((chars - part1Count - part2Count) / part3Count) ;
remaining = part1Count + part2Count + (moreM * part3Count) - chars;
messages = 2 + moreM;
}
$('#remaining').text(remaining);
$('#messages').text(messages);
$('#total').text(chars);
if (remaining > 1) $('.cplural').show();
else $('.cplural').hide();
if (messages > 1) $('.mplural').show();
else $('.mplural').hide();
if (chars > 1) $('.tplural').show();
else $('.tplural').hide();
});
$('#message').keyup();
});
</script>
HTML
<textarea name="message" value="" id="message"></textarea>
<div>
<div><span id="remaining">160</span> Character<span class="cplural">s</span> Remaining</div>
<div>Total <span id="messages">1</span> Message<span class="mplural">s</span> <span id="total">0</span> Character<span class="tplural">s</span></div>
</div>
You can get the code here http://www.mindrestingplace.com/2012/07/18/sms-character-counter/
Hope this will solve your problems. Thanks
I updated the script (for my purposes) to include the subject in the count as well. This is what I came up with:
$(document).ready(function(){
var $remaining = $('#remaining'),
$messages = $remaining.next();
$('#message').keyup(function(){
var chars = this.value.length + document.getElementById('subject').value.length,
messages = Math.ceil(chars / 160),
remaining = messages * 160 - (chars % (messages * 160) || messages * 160);
$remaining.text(remaining);
//$remaining.text(remaining + ' characters remaining');
//$messages.text(messages + ' message(s)');
});
$('#subject').keyup(function(){
var chars = this.value.length + document.getElementById('message').value.length,
messages = Math.ceil(chars / 160),
remaining = messages * 160 - (chars % (messages * 160) || messages * 160);
$remaining.text(remaining);
//$remaining.text(remaining + ' characters remaining');
//$messages.text(messages + ' message(s)');
});
});
I tested and it works. I also change the html a bit:
<p>
<span id="remaining">160</span> characters remaining
<!--<span id="messages">1 message(s)</span>-->
</p>
This is late to the game, but here's what I'm currently putting together.
The character limit is set to 459 to allow for concatenated messages (as set by my service provider), with a text unit tot-up per 160 characters used. Bear in mind this aspect is incomplete as each unit after the initial one would comprise of less than the 160 character template due to message headers and whatnot. I just havent gotten the exact breakdown from the provider yet.
The crucial difference in this script is that the character count is sensitive to non-standard GSM characters, their ascii values specified in the included array. Where a non-standard character is typed, the count is 2, otherwise 1.
$('#sms-message').keyup(function(){
var chars = $(this).val(),
arr_chars = chars.split(''),
remaining = $('#remaining'),
messages = $('#messages'),
count = 0;
$.each(arr_chars, function(i, l){
var ascii = l.charCodeAt(0),
ascii_val = parseInt(ascii),
//array of special chars
arr = [13, 47, 92, 123, 124, 125, 126, 128];
if($.inArray(ascii_val, arr) !== -1) { count = count + 2; }
else { count = count + 1; }
});
//inaccurate count, will have to be finetuned to provider specs
var units = Math.ceil(count / 160),
remaining_chars = 459 - count;
remaining.text(remaining_chars + ' characters remaining');
messages.text(units + ' text unit(s)');
if(remaining_chars < 0) {
$(remaining).css('color', 'red');
}
else {
$(remaining).css('color', 'black');
}
});
For SMS sending character count
Logic / Requirement :- if len <= 160 than send (1 SMS)
- if len > 160 and after every 153 character/len, than send (1++)
- len 1 to 160 = SMS send 1
- len 161 to 313 = SMS send 2
- len 314 to 466 = SMS send 3
And so on...
Script :
function cntsms(len) {
return len <= 0 ? 0 : ( len > 160 ? Math.ceil((len-7)/153) : 1);
}
$(function() {
$('#message').keydown(function() {
var mychars = $('#message').val().length;
var mysms = Math.ceil(mychars / 160);
console.log (mysms);
console.log (mychars +'' + ' characters');
});
});
精彩评论