
图1新浪微博用户输入限制
字符数统计插件会在输入框后创建一个同级元素span,它用来显示当前剩余字符数,当触发输入框的keyup、keydown和change事件时,实时修改span中剩余字符数,如果剩余字符数接近“warning”(接近零)修改CSS样式提示用户接近输入限制。
当剩余字符达到“warning”时,在span元素中添加相应的样式类,当剩余字符等于或大于输入限制时,添加相应的样式类提示用户已经超出字符数限制。
我们通过字符数统计插件在页面中动态地插入如下代码:
<!-- adds element dynamic --><span class="counter">140</span>在默认情况下,字符限制是140个,当可输入字符数少于等于25个提示用户,当可输入字符数少于等于0时,提示用户字符数超出了限制。下面我们定义默认情况下条件对象:
// The default limitation.var defaults = { allowed: 140, warning: 25, css: "counter", counterElement: "span", cssWarning: "warning", cssExceeded: "exceeded", counterText: ""};上面,我们定义了defaults对象,它包含allowed、warning、css、cssWarning和cssExceeded等属性,通过修改defaults对象属性,我们可以很方便修改字符统计插件。/**** Calculates the char* @param obj*/function calculate(obj) { // Get the count. var count = getLength($(obj).val()); var available = options.allowed - count; if (available <= options.warning && available >= 0) {$(obj).next().addClass(options.cssWarning); } else {$(obj).next().removeClass(options.cssWarning); } if (available < 0) {$(obj).next().addClass(options.cssExceeded); } else {$(obj).next().removeClass(options.cssExceeded); } $(obj).next().html(options.counterText + available);}我们又定义方法getLength(),当输入字符是中文时totLen加1,如果是英文字符或数字时totLen加0.5(默认允许输入140个中文字符)。/*** Get the length of char.* @param str* @return {Number}*/function getLength(str) { var totLen = 0; for (var i = 0; i < str.length; i++) {// If the char is Chinese.if (str.charCodeAt(i) > 256) { totLen += 1;}else { totLen += 0.5;} } return Math.floor(totLen);}接下来,我们在控件中绑定keyup(),keydown()和change()事件方法,当页面对象触发keyup(),keydown()或change()事件方法时,调用calculate()方法计算当前剩余的字符数,并且添加相应的CSS样式到页面中。// Binds text area keyup, keydown and change event.this.each(function() { $(this).after("<" + options.counterElement + " class="" + options.css + "">" + options.counterText + "</" +options.counterElement + ">"); calculate(this); $(this).keyup(function() { calculate(this), storeWeibo(this) }); $(this).keydown(function() { calculate(this), storeWeibo(this) }); $(this).change(function() { calculatea(this) });});2、Web Storage
图2存储空间的对比
接下来,我们将介绍如何使用本地存储保存用户数据。
由于,localStorage提供了setItem(),getItem(),removeItem(),key()和clear() 5个方法,和一个属性length,具体定义如下:
// Storage definition.interface Storage { readonly attribute unsigned long length; DOMString key(in unsigned long index); getter any getItem(in DOMString key); setter creator void setItem(in DOMString key, in any value); deleter void removeItem(in DOMString key); void clear();};在现代浏览器中使用本地存储是非常的简单,我们只需在Javascript代码中直接调用localStorage对象的方法或属性就OK了。// stores the username "jkrush",// then get the username.localStorage.setItem("username", "jkrush");var userName = localStorage.getItem("username");上面,我们通过调用localStorage的setItem()和getItem()方法实现数据的存储和获取,由于localStorage是以Key/Value形式存储数据的,所以我们在存储时需要提供Key/Value值,然后调用getItem()方法获取存储在Key中的值。
// Defines a student object.var student = { name: "JK_Rush", age: "26", sex: "male"};// Prints student objectconsole.log(student);// Stores student object.// Gets student object again.localStorage.setItem("student", student);console.log(localStorage.getItem("student"));
图3 localStorage存储对象
通过上面示例,我们注意到在Firebug的控制台中输出的并不是真正的student对象,而是student对象的信息而已。
那么我们该如何把对象存储到localStorage中呢?其实,我们可以把对象序列化为JSON数据进行存储,最后通过反序列化把JSON数据转换为对象。具体实现如下:
// Defines a student object.var student = { name: "JK_Rush", age: "26", sex: "male"};console.log(student);// Serializes the object to json string.localStorage.setItem("student", JSON.stringify(student));// Deserializes the json string to object.console.log(JSON.parse(localStorage.getItem("student")));上面示例中,在存储student对象之前,我们使用JSON的stringify()方法序列化对象为JSON字符串,然后存储到localStorage中;如果我们要获取student对象,只需使用JSON的parse()方法反序列化字符串为对象。
图4 localStorage存储对象
上面,我们实现了student对象转换为JSON格式字符串存储到localStorage中,接下来,我们在前面的例子中添加localStorage功能,具体代码如下:
/*** Store user data into local storage.* @param obj*/function storeWeibo(obj) { // Checks the browser supports local storage or not. if (window.localStorage) {localStorage.setItem("publisherTop_word", $(obj).val()); } else {// For instance, ie 6 and 7 do not support local storage,// so we need to provider other way.window.localStorage = { getItem: function(sKey) {if (!sKey || !this.hasOwnProperty(sKey)) { return null; }return unescape(document.cookie.replace(new RegExp("(?:^|.*;\s*)" + escape(sKey).replace(/[-.+*]/g, "\$&") + "\s*\=\s*((?:[^;](?!;))*[^;]?).*"), "$1")); }, key: function(nKeyId) {return unescape(document.cookie.replace(/s*=(?:.(?!;))*$/, "").split(/s*=(?:[^;](?!;))*[^;]?;s*/)[nKeyId]); }, setItem: function(sKey, sValue) {if (!sKey) { return; }document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";this.length = document.cookie.match(/=/g).length; }, length: 0, removeItem: function(sKey) {if (!sKey || !this.hasOwnProperty(sKey)) { return; }document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";this.length--; }, hasOwnProperty: function(sKey) {return (new RegExp("(?:^|;\s*)" + escape(sKey).replace(/[-.+*]/g, "\$&") + "\s*\=")).test(document.cookie); }};window.localStorage.length = (document.cookie.match(/=/g) || window.localStorage).length; }}现在我们在自定义字符统计插件(jquery.charcount.js)中,添加方法storeWeibo(),首先我们判断当前浏览器是否支持localStorage,主流的浏览器如:Chrome、Firefox、Opera、Safari以及IE 8都支持本地存储(localStorage)和会话存储(sessionStorage)。

图5 主流浏览器支持Web Storage
现在,我们已经完成了字符统计插件jquery.charcount.js,由于时间的关系我们已经把发送框的界面设计好了,具体的HTML代码如下:
<!-- From design--><body> <form id="form" method="post"> <h2>有什么新鲜事想告诉大家?</h2> <div><label class="mali_oglas_kategorija" for="message"> 有什么新鲜事想告诉大家?<b></b></label><textarea id="weiboMsg" placeholder="请Fun享"></textarea><span class="counter"></span><input onclick="SaveCache()" type="submit" value="发布"> </div> </form></body>

图6 发送框界面设计
接下来,我们在页面代码中引用jQuery库和自定义字符统计插件jquery.charcount.js,具体代码如下:
<!-- Adds Javascript reference --><script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script><script type="text/javascript" src="./js/jquery.charcount.js"></script>上面,我们直接引用Google提供的jQuery库,当然我们也把jQuery库下载到本地,然后引入到项目中,接下来我们在HTML页面中添加调用字符统计插件的代码,具体代码如下:
<!-- When document ready invokes charCount function--><script type="text/javascript"> $(document).ready(function () {// Uses default setting.$("#weiboMsg").charCount(); });</script>上面,我们完成了在页面代码中调用字符统计插件,每当我们在文本框中输入字符时,都会实时地显示剩余的字符数,而且我们在文本框中输入的字符都会保存到localStorage中。
图7 Chrome的本地存储
同样,我们打开Firefox的“Firebug”(F12),然后我们选择“DOM”选项,这时我们需要查找window的对象localStorage,这样就可以看到保存在localStorage中的数据了。

图8 Firefox的本地存储
我们知道IE8也是支持localStorage对象的,但是我做测试时候发现IE8中一直提示localStorage对象未定义,后来我上Stackoverflow查看了一下,有人说在IE8中,localStorage对象是依赖于域名的,所以需要运行在Web服务器中才可以成功保存数据到localStorage中。
我们注意到微博通过本地存储技术,保存用户在发送框中的数据,一旦数据发送了就清空本地存储,反之保存用户的输入。
本文通过微博发送框例子介绍了如何定义jQuery字符统计插件和本地存储技术,首先,我们知道限制用户输入是必须的,但如何有效而且人性化提示用户输入限制呢?这里我们通过定义一个jQuery插件,动态地统计剩余字符数,希望对大家学习javascript程序设计有所启发。