js 將input框中的輸入自動(dòng)轉(zhuǎn)化成半角大寫(稅號(hào)輸入框)
這兩天出了這么一個(gè)需求,輸入稅號(hào)的時(shí)候,需要自動(dòng)將其轉(zhuǎn)化為半角大寫,并且阻止標(biāo)點(diǎn)符號(hào)中文漢字的輸入。(下面會(huì)有:全半角轉(zhuǎn)換、文本框選中、光標(biāo)位置判斷、設(shè)置光標(biāo)位置 這些內(nèi)容)
然后我就開始了慢慢查找資料之路。
首先查了全半角的區(qū)別以及如何轉(zhuǎn)化。
var str = "中文;;a"; for (var i = 0; i < str.length; i++) { if (str[i].match(/[\u0000-\u00ff]/)) { console.log("半角字符"); } else if (str[i].match(/[\uff00-\uffff]/)) { console.log("全角字符 " + str[i] + " " + toSBC(str[i])); } else { console.log(str[i]); // 除了數(shù)字英文之外的文本,包括中文等各國(guó)文字。 } }
這是兩者的區(qū)別,將文字轉(zhuǎn)成unicode之后,進(jìn)行比較即可,兩者均有自己的范圍,半角為0x20~0x7E,全角為0xFF01~0xFF5E。(這是16進(jìn)制,前面的0x是代表是16進(jìn)制)
轉(zhuǎn)化的話除了空格不同之外,其他均為全角-半角=65248(0xFEE0)
具體的轉(zhuǎn)化函數(shù)如下:(這是網(wǎng)上的一種比較靠譜的方法,但是網(wǎng)上的方法普遍把SBC和DBC寫反了,我這里糾正了一下。)
// 轉(zhuǎn)全角字符 function toSBC(str) { var result = ""; var len = str.length; for (var i = 0; i < len; i++) { var cCode = str.charCodeAt(i); //全角與半角相差(除空格外):65248(十進(jìn)制) cCode = (cCode>=0x0021 && cCode<=0x007E)?(cCode + 65248) : cCode; //處理空格 cCode = (cCode==0x0020)?0x03000:cCode; result += String.fromCharCode(cCode); } return result; } // 轉(zhuǎn)半角字符 function toDBC(str) { var result = ""; var len = str.length; for (var i = 0; i < len; i++) { var cCode = str.charCodeAt(i); //全角與半角相差(除空格外):65248(十進(jìn)制) cCode = (cCode>=0xFF01 && cCode<=0xFF5E)?(cCode - 65248) : cCode; //處理空格 cCode = (cCode==0x03000)?0x0020:cCode; result += String.fromCharCode(cCode); } return result; }
全角半角的區(qū)別也找完了,開始想辦法轉(zhuǎn)化,用的是input方法。
var oldValue = ""; var $thisDom; // 假裝有jquery的dom元素 $thisDom.unbind().bind("input", function (e) { var reg = /^[0-9A-Za-z]*$/; var str = toDBC(e.target.value).toUpperCase(); if (reg.test(str)) { oldValue = str; $(this).val(str); } else { $(this).val(oldValue); } });
但是有一個(gè)問(wèn)題,那就是光標(biāo)有問(wèn)題,始終在最后一位輸入的時(shí)候沒(méi)問(wèn)題,但是在中間輸入,光標(biāo)始終會(huì)跳到最后一位。于是又有了下面的光標(biāo)相關(guān)知識(shí)。
在網(wǎng)上找到了下列相關(guān)代碼,用來(lái)控制光標(biāo)位置。
function getCursortPosition(ctrl){ var CaretPos = 0; if (document.selection) { ctrl.focus(); var Sel = document.selection.createRange(); Sel.moveStart('character', -ctrl.value.length); CaretPos = Sel.text.length; } else if (ctrl.selectionStart || ctrl.selectionStart == '0') { CaretPos = ctrl.selectionStart; } return (CaretPos); } function setCaretPosition(ctrl, pos){ if (ctrl.setSelectionRange) { ctrl.focus(); ctrl.setSelectionRange(pos, pos); } else if (ctrl.createTextRange) { var range = ctrl.createTextRange(); range.collapse(true); range.moveEnd('character', pos); range.moveStart('character', pos); range.select(); } }
這兩個(gè)分別是獲取光標(biāo)位置以及設(shè)置光標(biāo)位置。這里用到的是textRange對(duì)象。
TextRange對(duì)象是動(dòng)態(tài)HTML(DHTML)的高級(jí)特性,使用它可以實(shí)現(xiàn)很多和文本有關(guān)的任務(wù),例如搜索和選擇文本。文本范圍讓您可以選擇性的將字符、單詞和句子從文檔中挑選出來(lái)。TextRange對(duì)象是在HTML文檔將要顯示的文本流上建立開始和結(jié)束位置的抽象對(duì)象。
下面是TextRange的常用屬性與方法:
屬性:
boundingHeight 獲取綁定TextRange對(duì)象的矩形的高度
boundingLeft 獲取綁定TextRange 對(duì)象的矩形左邊緣和包含TextRange對(duì)象的左側(cè)之間的距離
offsetLeft 獲取對(duì)象相對(duì)于版面或由offsetParent屬性指定的父坐標(biāo)的計(jì)算左側(cè)位置
offsetTop 獲取對(duì)象相對(duì)于版面或由offsetParent屬性指定的父坐標(biāo)的計(jì)算頂端位置
htmlText 獲取綁定TextRange對(duì)象的矩形的寬度
text 設(shè)置或獲取范圍內(nèi)包含的文本
方法:
moveStart 更改范圍的開始位置
moveEnd 更改范圍的結(jié)束位置
collapse 將插入點(diǎn)移動(dòng)到當(dāng)前范圍的開始或結(jié)尾
move 折疊給定文本范圍并將空范圍移動(dòng)給定單元數(shù)
execCommand 在當(dāng)前文檔、當(dāng)前選中區(qū)或給定范圍上執(zhí)行命令
select 將當(dāng)前選擇區(qū)置為當(dāng)前對(duì)象
findText 在文本中搜索文本并將范圍的開始和結(jié)束點(diǎn)設(shè)置為包圍搜索字符串。
具體使用可見(jiàn)其他人的文章,地址是:http://www.dbjr.com.cn/article/105787.htm
回到正題,于是我把上述代碼拼進(jìn)了我的代碼中。
function toDBC(str) { var result = ""; var len = str.length; for (var i = 0; i < len; i++) { var cCode = str.charCodeAt(i); //全角與半角相差(除空格外):65248(十進(jìn)制) cCode = (cCode>=0xFF01 && cCode<=0xFF5E)?(cCode - 65248) : cCode; //處理空格 cCode = (cCode==0x03000)?0x0020:cCode; result += String.fromCharCode(cCode); } return result; } function getCursortPosition(ctrl){ var CaretPos = 0; if (document.selection) { ctrl.focus(); var Sel = document.selection.createRange(); Sel.moveStart('character', -ctrl.value.length); CaretPos = Sel.text.length; } else if (ctrl.selectionStart || ctrl.selectionStart == '0') { CaretPos = ctrl.selectionStart; } return (CaretPos); } function setCaretPosition(ctrl, pos){ if (ctrl.setSelectionRange) { ctrl.focus(); ctrl.setSelectionRange(pos, pos); } else if (ctrl.createTextRange) { var range = ctrl.createTextRange(); range.collapse(true); range.moveEnd('character', pos); range.moveStart('character', pos); range.select(); } } var oldValue = this.model.get("taxNo"); $taxNoDom.unbind().bind("input", function (e) { var reg = /^[0-9A-Za-z]*$/; var position = getCursortPosition($taxNoDom[0]); var str = toDBC(e.target.value).toUpperCase(); if (reg.test(str) && str.length <= 25) { oldValue = str; $(this).val(str); setCaretPosition($taxNoDom[0], position); } else { $(this).val(oldValue); setCaretPosition($taxNoDom[0], position - 1); } });
上述代碼中我自己寫的就是最下面的綁定事件,仔細(xì)看一下應(yīng)該都是可以看懂的。但是上述代碼有一個(gè)bug,其實(shí)也算是getCursortPosition這個(gè)方法的bug。
那就是在中文輸入法的時(shí)候,輸入的字母在input事件執(zhí)行的時(shí)候是選中格式,光標(biāo)在該字母之前,以至于位置跟想象的有偏差,在正確的時(shí)候打出來(lái)的字一直在光標(biāo)之后。
當(dāng)時(shí)我很苦惱感覺(jué)人生無(wú)望啊。。想了幾種方法:
1. 默認(rèn)觸發(fā)鍵盤左箭頭再觸發(fā)右箭頭。這樣不管是不是選中光標(biāo)都應(yīng)該是正確的位置了。
2. 查看當(dāng)前頁(yè)面中是否有選中的文字。如果有選中的文字,就把返回的光標(biāo)位置+1。
網(wǎng)上查了一下第一種方法,立馬就放棄了。相關(guān)資料也很少,而且局限性相當(dāng)大,瀏覽器之間差異也大,怎么看都不像是會(huì)是一種好方法。
然后找到了第二種方法的方法。window.getSelection和document.selection
IE9以下支持:document.selection
IE9、Firefox、Safari、Chrome和Opera支持:window.getSelection()
(由于我們公司項(xiàng)目只支持ie9及以上,就沒(méi)有嘗試document.selection)
我自己試了一下,如果有選中的文字的時(shí)候window.getSelection().type === "Range",如果沒(méi)有選中window.getSelection().type === "Caret"。
于是最終的代碼如下:
function toDBC(str) { var result = ""; var len = str.length; for (var i = 0; i < len; i++) { var cCode = str.charCodeAt(i); //全角與半角相差(除空格外):65248(十進(jìn)制) cCode = (cCode>=0xFF01 && cCode<=0xFF5E)?(cCode - 65248) : cCode; //處理空格 cCode = (cCode==0x03000)?0x0020:cCode; result += String.fromCharCode(cCode); } return result; } function getCursortPosition(ctrl){ var CaretPos = 0; if (document.selection) { ctrl.focus(); var Sel = document.selection.createRange(); Sel.moveStart('character', -ctrl.value.length); CaretPos = Sel.text.length; } else if (ctrl.selectionStart || ctrl.selectionStart == '0') { if (window.getSelection().type === "Range") { CaretPos = ctrl.selectionStart + 1; } else { CaretPos = ctrl.selectionStart; } } return (CaretPos); } function setCaretPosition(ctrl, pos){ if (ctrl.setSelectionRange) { ctrl.focus(); ctrl.setSelectionRange(pos, pos); } else if (ctrl.createTextRange) { var range = ctrl.createTextRange(); range.collapse(true); range.moveEnd('character', pos); range.moveStart('character', pos); range.select(); } } var oldValue = this.model.get("commercialTax").taxNo; $taxNoDom.unbind().bind("input", function (e) { var reg = /^[0-9A-Za-z]*$/; var position = getCursortPosition($taxNoDom[0]); var str = toDBC(e.target.value).toUpperCase(); if (reg.test(str) && str.length <= 25) { oldValue = str; $(this).val(str); setCaretPosition($taxNoDom[0], position); } else { $(this).val(oldValue); setCaretPosition($taxNoDom[0], position - 1); } });
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
js面向?qū)ο笾?、私有、靜態(tài)屬性和方法詳解
這篇文章主要詳細(xì)介紹了js面向?qū)ο笾?、私有、靜態(tài)屬性和方法,并附上詳細(xì)的示例,非常的細(xì)致全面,這里推薦給大家,有需要的小伙伴可以參考下2015-04-04javascript稀疏數(shù)組(sparse array)和密集數(shù)組用法分析
這篇文章主要介紹了javascript稀疏數(shù)組(sparse array)和密集數(shù)組用法,分析javascript稀疏數(shù)組和密集數(shù)組的功能、定義與使用方法,需要的朋友可以參考下2016-12-12JavaScript必知必會(huì)(六) delete in instanceof
這篇文章主要介紹了JavaScript必知必會(huì)(六) delete in instanceof的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06JS 循環(huán)li添加點(diǎn)擊事件 (閉包的應(yīng)用)
這篇文章主要介紹了js循環(huán)li添加點(diǎn)擊事件 (閉包的應(yīng)用)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12JavaScript基于自定義函數(shù)判斷變量類型的實(shí)現(xiàn)方法
這篇文章主要介紹了JavaScript基于自定義函數(shù)判斷變量類型的實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了javascript判斷變量類型的自定義函數(shù)定義與使用方法,并針對(duì)不同瀏覽器給出了相關(guān)的分析與說(shuō)明,需要的朋友可以參考下2016-11-11淺談addEventListener和attachEvent的區(qū)別
下面小編就為大家?guī)?lái)一篇淺談addEventListener和attachEvent的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07typescript使用 ?. ?? ??= 運(yùn)算符的方法步驟
本文主要介紹了typescript使用 ?. ?? ??= 運(yùn)算符的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01JS如何將數(shù)字類型轉(zhuǎn)化為沒(méi)3個(gè)一個(gè)逗號(hào)的金錢格式
本文為大家介紹下如何將數(shù)字類型轉(zhuǎn)化為沒(méi)3個(gè)一個(gè)逗號(hào)的金錢格式,下面是具體的實(shí)現(xiàn)2014-01-01