js仿微博實(shí)現(xiàn)統(tǒng)計(jì)字符和本地存儲(chǔ)功能
隨著移動(dòng)設(shè)備和Web應(yīng)用的普及,為了更好的便于用戶(hù)的使用,對(duì)于網(wǎng)頁(yè)或應(yīng)用程序的用戶(hù)體驗(yàn)要求就越來(lái)越高,確實(shí)是這樣,作為用戶(hù)更喜歡選擇用戶(hù)體驗(yàn)效果好的網(wǎng)站或應(yīng)用程序,所以作為開(kāi)發(fā)者的我們就需要開(kāi)發(fā)出更人生化的應(yīng)用程序了。
相信許多人有使用微博的經(jīng)驗(yàn),像微博這樣的社交平臺(tái),好的用戶(hù)體驗(yàn)就變得尤其重要了。
例如:我們?cè)诎l(fā)微博時(shí),文本框會(huì)實(shí)時(shí)地提示我們剩余字符數(shù),這樣人性化的提示方便了用戶(hù)知道微博字?jǐn)?shù)的限制,同時(shí)也限制了用戶(hù)的輸入字?jǐn)?shù)。
有一句話(huà)我們要牢記在心的是:凡是輸入,必有限制;凡是輸入,必須校驗(yàn)。
在接下來(lái)的文章中,我們將介紹如何實(shí)現(xiàn)輸入字符實(shí)時(shí)提示功能和本地存儲(chǔ)(localStorage)技術(shù)。
1、jQuery字符統(tǒng)計(jì)插件
現(xiàn)在,我們以新浪微博發(fā)送微博輸入框?yàn)槔?,介紹使用jQuery實(shí)現(xiàn)實(shí)時(shí)提示用戶(hù)剩余字符數(shù)。
新浪微博是限制140個(gè)中文(280個(gè)英文),當(dāng)然還有各種其他字符空格的情況,在用戶(hù)輸入達(dá)到限制之前或達(dá)到了,好的用戶(hù)體驗(yàn)應(yīng)該提示用戶(hù)接近或達(dá)到了限制,當(dāng)然我們可以通過(guò)使用不同顏色或加粗字體方式提示用戶(hù)。

圖1新浪微博用戶(hù)輸入限制
字符數(shù)統(tǒng)計(jì)插件會(huì)在輸入框后創(chuàng)建一個(gè)同級(jí)元素span,它用來(lái)顯示當(dāng)前剩余字符數(shù),當(dāng)觸發(fā)輸入框的keyup、keydown和change事件時(shí),實(shí)時(shí)修改span中剩余字符數(shù),如果剩余字符數(shù)接近“warning”(接近零)修改CSS樣式提示用戶(hù)接近輸入限制。
當(dāng)剩余字符達(dá)到“warning”時(shí),在span元素中添加相應(yīng)的樣式類(lèi),當(dāng)剩余字符等于或大于輸入限制時(shí),添加相應(yīng)的樣式類(lèi)提示用戶(hù)已經(jīng)超出字符數(shù)限制。
我們通過(guò)字符數(shù)統(tǒng)計(jì)插件在頁(yè)面中動(dòng)態(tài)地插入如下代碼:
<!-- adds element dynamic --> <span class="counter">140</span>
在默認(rèn)情況下,字符限制是140個(gè),當(dāng)可輸入字符數(shù)少于等于25個(gè)提示用戶(hù),當(dāng)可輸入字符數(shù)少于等于0時(shí),提示用戶(hù)字符數(shù)超出了限制。下面我們定義默認(rèn)情況下條件對(duì)象:
// The default limitation.
var defaults = {
allowed: 140,
warning: 25,
css: 'counter',
counterElement: 'span',
cssWarning: 'warning',
cssExceeded: 'exceeded',
counterText: ''
};
上面,我們定義了defaults對(duì)象,它包含allowed、warning、css、cssWarning和cssExceeded等屬性,通過(guò)修改defaults對(duì)象屬性,我們可以很方便修改字符統(tǒng)計(jì)插件。
- Allowed:允許輸入的字符數(shù)。
- Warning:提示用戶(hù)剩余字符數(shù)接近限零。
- Css:添加到counter元素的CSS樣式類(lèi)名。
- cssWarning:警告提示樣式。
- cssExceeded:超出字符限制提示樣式。
接下來(lái),我們?cè)谧址y(tǒng)計(jì)插件中定義方法calculate(),它計(jì)算當(dāng)前剩余字符數(shù),如果到達(dá)了警告范圍則在頁(yè)面中增加樣式類(lèi)“warning”,當(dāng)剩余字符數(shù)少于等于零時(shí),在頁(yè)面中增加樣式“exceeded”。
/***
* 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(),當(dāng)輸入字符是中文時(shí)totLen加1,如果是英文字符或數(shù)字時(shí)totLen加0.5(默認(rèn)允許輸入140個(gè)中文字符)。
/**
* 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);
}
接下來(lái),我們?cè)诳丶薪壎╧eyup(),keydown()和change()事件方法,當(dāng)頁(yè)面對(duì)象觸發(fā)keyup(),keydown()或change()事件方法時(shí),調(diào)用calculate()方法計(jì)算當(dāng)前剩余的字符數(shù),并且添加相應(yīng)的CSS樣式到頁(yè)面中。
// 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
現(xiàn)在,我們基本實(shí)現(xiàn)了jQuery字符數(shù)統(tǒng)計(jì)插件功能了,相信許多人都注意到,如果我們?cè)诎l(fā)微博時(shí),沒(méi)有發(fā)送出去的微博下次打開(kāi)頁(yè)面,發(fā)送框依然保存著我們未發(fā)送的微博,即使關(guān)閉瀏覽器重新打開(kāi)頁(yè)面,我們沒(méi)發(fā)送的信息依然存在。
其實(shí),要實(shí)現(xiàn)這一個(gè)功能方法是多種多樣的,例如我們可以使用:Cookies,Session等技術(shù)。
隨著HTML5規(guī)范的制定,與此同時(shí)W3C制定了網(wǎng)絡(luò)存儲(chǔ)(Web Storage)的規(guī)范,它提供將數(shù)據(jù)存儲(chǔ)在客戶(hù)端中,直到Session過(guò)期(會(huì)話(huà)存儲(chǔ))或超出本地容量(本地存儲(chǔ)),它比傳統(tǒng)的Cookies存儲(chǔ)功能更強(qiáng)大、更容易實(shí)現(xiàn)和容量更大(大部分瀏覽器支持5M的本地存儲(chǔ))。
會(huì)話(huà)存儲(chǔ)
會(huì)話(huà)存儲(chǔ):它將數(shù)據(jù)保存在會(huì)話(huà)中,一旦我們關(guān)閉瀏覽器選項(xiàng)卡時(shí),會(huì)話(huà)中的數(shù)據(jù)將失效。
本地存儲(chǔ)
本地存儲(chǔ):當(dāng)數(shù)據(jù)需要持久地保存在客戶(hù)端中,這時(shí)我們可以使用本地存儲(chǔ)(Local Storage),它是以key/value 的形式來(lái)存儲(chǔ)數(shù)據(jù)的,如果關(guān)閉了頁(yè)面或?yàn)g覽器后,重新打開(kāi)頁(yè)面數(shù)據(jù)依然存在,它提供了數(shù)據(jù)的持久保存。一個(gè)簡(jiǎn)單的應(yīng)用是:記錄用戶(hù)訪問(wèn)頁(yè)面的次數(shù)。

圖2存儲(chǔ)空間的對(duì)比
接下來(lái),我們將介紹如何使用本地存儲(chǔ)保存用戶(hù)數(shù)據(jù)。
由于,localStorage提供了setItem(),getItem(),removeItem(),key()和clear() 5個(gè)方法,和一個(gè)屬性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();
};
在現(xiàn)代瀏覽器中使用本地存儲(chǔ)是非常的簡(jiǎn)單,我們只需在Javascript代碼中直接調(diào)用localStorage對(duì)象的方法或?qū)傩跃蚈K了。
// stores the username 'jkrush',
// then get the username.
localStorage.setItem('username', 'jkrush');
var userName = localStorage.getItem('username');
上面,我們通過(guò)調(diào)用localStorage的setItem()和getItem()方法實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)和獲取,由于localStorage是以Key/Value形式存儲(chǔ)數(shù)據(jù)的,所以我們?cè)诖鎯?chǔ)時(shí)需要提供Key/Value值,然后調(diào)用getItem()方法獲取存儲(chǔ)在Key中的值。
由于本地存儲(chǔ)是以Key/Value的形式進(jìn)行存儲(chǔ)的,那么我們可以很容易存儲(chǔ)字符串類(lèi)型的數(shù)據(jù),如果我們需要存儲(chǔ)對(duì)象類(lèi)型,那么本地存儲(chǔ)就顯得捉襟見(jiàn)肘了。
假設(shè),我們把一個(gè)student對(duì)象存儲(chǔ)到localStorage中,具體代碼如下:
// Defines a student object.
var student = {
name: 'JK_Rush',
age: '26',
sex: 'male'
};
// Prints student object
console.log(student);
// Stores student object.
// Gets student object again.
localStorage.setItem('student', student);
console.log(localStorage.getItem('student'));

圖3 localStorage存儲(chǔ)對(duì)象
通過(guò)上面示例,我們注意到在Firebug的控制臺(tái)中輸出的并不是真正的student對(duì)象,而是student對(duì)象的信息而已。
那么我們?cè)撊绾伟褜?duì)象存儲(chǔ)到localStorage中呢?其實(shí),我們可以把對(duì)象序列化為JSON數(shù)據(jù)進(jìn)行存儲(chǔ),最后通過(guò)反序列化把JSON數(shù)據(jù)轉(zhuǎn)換為對(duì)象。具體實(shí)現(xiàn)如下:
// 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')));
上面示例中,在存儲(chǔ)student對(duì)象之前,我們使用JSON的stringify()方法序列化對(duì)象為JSON字符串,然后存儲(chǔ)到localStorage中;如果我們要獲取student對(duì)象,只需使用JSON的parse()方法反序列化字符串為對(duì)象。

圖4 localStorage存儲(chǔ)對(duì)象
上面,我們實(shí)現(xiàn)了student對(duì)象轉(zhuǎn)換為JSON格式字符串存儲(chǔ)到localStorage中,接下來(lái),我們?cè)谇懊娴睦又刑砑觢ocalStorage功能,具體代碼如下:
/**
* 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;
}
}
現(xiàn)在我們?cè)谧远x字符統(tǒng)計(jì)插件(jquery.charcount.js)中,添加方法storeWeibo(),首先我們判斷當(dāng)前瀏覽器是否支持localStorage,主流的瀏覽器如:Chrome、Firefox、Opera、Safari以及IE 8都支持本地存儲(chǔ)(localStorage)和會(huì)話(huà)存儲(chǔ)(sessionStorage)。
如果瀏覽器支持本地存儲(chǔ),那么我們可以直接調(diào)用localStorage的setItem()方法,將textarea中的數(shù)據(jù)存儲(chǔ)起來(lái);當(dāng)我們?cè)俅未蜷_(kāi)頁(yè)面或?yàn)g覽器,首先檢查localStorage是否存儲(chǔ)了相應(yīng)的數(shù)據(jù),如果有數(shù)據(jù)存儲(chǔ),那么我們?cè)俅伟褦?shù)據(jù)取出顯示到textarea中。
但由于一些用戶(hù)可能使用舊版的瀏覽器(如:IE6和IE7),考慮到兼容我們必須提供支持舊版瀏覽器的方案。
我們知道舊版瀏覽器(如:IE6和IE7),它們支持Cookies的持久化存儲(chǔ)方式,所以我們使用Cookies實(shí)現(xiàn)getItem(), setItem()和removeItem()等方法。


圖5 主流瀏覽器支持Web Storage
現(xiàn)在,我們已經(jīng)完成了字符統(tǒng)計(jì)插件jquery.charcount.js,由于時(shí)間的關(guān)系我們已經(jīng)把發(fā)送框的界面設(shè)計(jì)好了,具體的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="請(qǐng)F(tuán)un享"></textarea> <span class="counter"></span> <input onclick="SaveCache()" type="submit" value="發(fā)布"> </div> </form> </body>

圖6 發(fā)送框界面設(shè)計(jì)
接下來(lái),我們?cè)陧?yè)面代碼中引用jQuery庫(kù)和自定義字符統(tǒng)計(jì)插件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庫(kù),當(dāng)然我們也把jQuery庫(kù)下載到本地,然后引入到項(xiàng)目中,接下來(lái)我們?cè)贖TML頁(yè)面中添加調(diào)用字符統(tǒng)計(jì)插件的代碼,具體代碼如下:
<!-- When document ready invokes charCount function-->
<script type="text/javascript">
$(document).ready(function () {
// Uses default setting.
$("#weiboMsg").charCount();
});
</script>
上面,我們完成了在頁(yè)面代碼中調(diào)用字符統(tǒng)計(jì)插件,每當(dāng)我們?cè)谖谋究蛑休斎胱址麜r(shí),都會(huì)實(shí)時(shí)地顯示剩余的字符數(shù),而且我們?cè)谖谋究蛑休斎氲淖址紩?huì)保存到localStorage中。
接下來(lái),我們分別在Chrome和Firefox中查看保存在localStorage中的數(shù)據(jù)。
首先,我們打開(kāi)Chrome的“開(kāi)發(fā)者工具”(Ctr+Shift+I),然后我們選擇“Resources”選項(xiàng),這時(shí)我們就可以看到保存在localStorage中的數(shù)據(jù)了。

圖7 Chrome的本地存儲(chǔ)
同樣,我們打開(kāi)Firefox的“Firebug”(F12),然后我們選擇“DOM”選項(xiàng),這時(shí)我們需要查找window的對(duì)象localStorage,這樣就可以看到保存在localStorage中的數(shù)據(jù)了。

圖8 Firefox的本地存儲(chǔ)
我們知道IE8也是支持localStorage對(duì)象的,但是我做測(cè)試時(shí)候發(fā)現(xiàn)IE8中一直提示localStorage對(duì)象未定義,后來(lái)我上Stackoverflow查看了一下,有人說(shuō)在IE8中,localStorage對(duì)象是依賴(lài)于域名的,所以需要運(yùn)行在Web服務(wù)器中才可以成功保存數(shù)據(jù)到localStorage中。
我們注意到微博通過(guò)本地存儲(chǔ)技術(shù),保存用戶(hù)在發(fā)送框中的數(shù)據(jù),一旦數(shù)據(jù)發(fā)送了就清空本地存儲(chǔ),反之保存用戶(hù)的輸入。
本文通過(guò)微博發(fā)送框例子介紹了如何定義jQuery字符統(tǒng)計(jì)插件和本地存儲(chǔ)技術(shù),首先,我們知道限制用戶(hù)輸入是必須的,但如何有效而且人性化提示用戶(hù)輸入限制呢?這里我們通過(guò)定義一個(gè)jQuery插件,動(dòng)態(tài)地統(tǒng)計(jì)剩余字符數(shù),希望對(duì)大家學(xué)習(xí)javascript程序設(shè)計(jì)有所啟發(fā)。
- js實(shí)現(xiàn)統(tǒng)計(jì)字符串中特定字符出現(xiàn)個(gè)數(shù)的方法
- JS查找字符串中出現(xiàn)最多的字符及個(gè)數(shù)統(tǒng)計(jì)
- JavaScript統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)次數(shù)完整實(shí)例
- JS字符串統(tǒng)計(jì)操作示例【遍歷,截取,輸出,計(jì)算】
- JavaScript中統(tǒng)計(jì)Textarea字?jǐn)?shù)并提示還能輸入的字符
- js統(tǒng)計(jì)錄入文本框中字符的個(gè)數(shù)并加以限制不超過(guò)多少
- 統(tǒng)計(jì)出現(xiàn)最多的字符次數(shù)的js代碼
- JavaScript中英文字符長(zhǎng)度統(tǒng)計(jì)方法示例【按照中文占2個(gè)字符】
- JS實(shí)現(xiàn)統(tǒng)計(jì)字符串中字符出現(xiàn)個(gè)數(shù)及最大個(gè)數(shù)功能示例
相關(guān)文章
Bootstrap布局之柵格系統(tǒng)學(xué)習(xí)筆記
這篇文章主要為大家詳細(xì)介紹了Bootstrap布局之柵格系統(tǒng)的學(xué)習(xí)筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
js使用navigator.userAgent判斷當(dāng)前瀏覽器所處的環(huán)境
本文主要介紹了js使用navigator.userAgent判斷當(dāng)前瀏覽器所處的環(huán)境,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
tkinter使用js的canvas實(shí)現(xiàn)漸變色
這篇文章主要為大家介紹了tkinter使用canvas實(shí)現(xiàn)漸變色,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12
JavaScript數(shù)據(jù)結(jié)構(gòu)之二叉查找樹(shù)的定義與表示方法
這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)之二叉查找樹(shù)的定義與表示方法,簡(jiǎn)單講述了二叉查找樹(shù)的概念、特點(diǎn)及javascript針對(duì)二叉查找樹(shù)的創(chuàng)建、插入、遍歷等操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-04-04
簡(jiǎn)單談?wù)凧avascript中類(lèi)型的判斷
這篇文章主要是對(duì)判斷javascript的數(shù)據(jù)類(lèi)型的判斷方式進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2015-10-10
bootstrap confirmation按鈕提示組件使用詳解
這篇文章主要為大家詳細(xì)介紹了bootstrap confirmation按鈕提示組件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
淺析JavaScript中的特殊數(shù)據(jù)類(lèi)型

