稅號輸入框 將input框中的輸入自動轉化成半角大寫

這兩天出了這麼一個需求,輸入稅號的時候,須要自動將其轉化爲半角大寫,而且阻止標點符號中文漢字的輸入。(下面會有:全半角轉換、文本框選中、光標位置判斷、設置光標位置 這些內容)html

而後我就開始了慢慢查找資料之路。jquery


 

首先查了全半角的區別以及如何轉化。瀏覽器

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]);
       // 除了數字英文以外的文本,包括中文等各國文字。
   }
}

這是二者的區別,將文字轉成unicode以後,進行比較便可,二者均有本身的範圍,半角爲0x20~0x7E,全角爲0xFF01~0xFF5E。(這是16進制,前面的0x是表明是16進制)dom

轉化的話除了空格不一樣以外,其餘均爲全角-半角=65248(0xFEE0)函數

具體的轉化函數以下:(這是網上的一種比較靠譜的方法,可是網上的方法廣泛把SBC和DBC寫反了,我這裏糾正了一下。)學習

//  轉全角字符
function toSBC(str) {
    var result = "";
    var len = str.length;
    for (var i = 0; i < len; i++) {
        var cCode = str.charCodeAt(i);
        //全角與半角相差(除空格外):65248(十進制)
        cCode = (cCode>=0x0021 && cCode<=0x007E)?(cCode + 65248) : cCode;
        //處理空格
        cCode = (cCode==0x0020)?0x03000:cCode;
        result += String.fromCharCode(cCode);
    }
    return result;
}
//  轉半角字符
function toDBC(str) {
    var result = "";
    var len = str.length;
    for (var i = 0; i < len; i++) {
        var cCode = str.charCodeAt(i);
        //全角與半角相差(除空格外):65248(十進制)
        cCode = (cCode>=0xFF01 && cCode<=0xFF5E)?(cCode - 65248) : cCode;
        //處理空格
        cCode = (cCode==0x03000)?0x0020:cCode;
        result += String.fromCharCode(cCode);
    }
    return result;
}

全角半角的區別也找完了,開始想辦法轉化,用的是input方法。ui

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);
    }
});

可是有一個問題,那就是光標有問題,始終在最後一位輸入的時候沒問題,可是在中間輸入,光標始終會跳到最後一位。因而又有了下面的光標相關知識。this


 

在網上找到了下列相關代碼,用來控制光標位置。spa

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();
    }
}

這兩個分別是獲取光標位置以及設置光標位置。這裏用到的是textRange對象。code

TextRange對象是動態HTML(DHTML)的高級特性,使用它能夠實現不少和文本有關的任務,例如搜索和選擇文本。文本範圍讓您能夠選擇性的將字符、單詞和句子從文檔中挑選出來。TextRange對象是在HTML文檔將要顯示的文本流上創建開始和結束位置的抽象對象。

下面是TextRange的經常使用屬性與方法:

屬性:
boundingHeight   獲取綁定TextRange對象的矩形的高度
boundingLeft       獲取綁定TextRange 對象的矩形左邊緣和包含TextRange對象的左側之間的距離
offsetLeft            獲取對象相對於版面或由offsetParent屬性指定的父座標的計算左側位置
offsetTop            獲取對象相對於版面或由offsetParent屬性指定的父座標的計算頂端位置
htmlText            獲取綁定TextRange對象的矩形的寬度
text                   設置或獲取範圍內包含的文本
方法:
moveStart          更改範圍的開始位置
moveEnd            更改範圍的結束位置
collapse             將插入點移動到當前範圍的開始或結尾
move                摺疊給定文本範圍並將空範圍移動給定單元數
execCommand   在當前文檔、當前選中區或給定範圍上執行命令
select                將當前選擇區置爲當前對象
findText             在文本中搜索文本並將範圍的開始和結束點設置爲包圍搜索字符串。

 

具體使用可見其餘人的blog,地址是:http://www.cnblogs.com/poissonnotes/archive/2010/04/15/1712903.html  或者  http://www.dengzhr.com/js/1013?utm_source=tuicool&utm_medium=referral

回到正題,因而我把上述代碼拼進了個人代碼中。

function toDBC(str) {
    var result = "";
    var len = str.length;
    for (var i = 0; i < len; i++) {
        var cCode = str.charCodeAt(i);
        //全角與半角相差(除空格外):65248(十進制)
        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);
    }
});

上述代碼中我本身寫的就是最下面的綁定事件,仔細看一下應該都是能夠看懂的。可是上述代碼有一個bug,其實也算是getCursortPosition這個方法的bug。

那就是在中文輸入法的時候,輸入的字母在input事件執行的時候是選中格式,光標在該字母以前,以致於位置跟想象的有誤差,在正確的時候打出來的字一直在光標以後。

當時我很苦惱感受人生無望啊。。想了幾種方法:

1. 默認觸發鍵盤左箭頭再觸發右箭頭。這樣不論是不是選中光標都應該是正確的位置了。

2. 查看當前頁面中是否有選中的文字。若是有選中的文字,就把返回的光標位置+1。

網上查了一下第一種方法,立馬就放棄了。相關資料也不多,並且侷限性至關大,瀏覽器之間差別也大,怎麼看都不像是會是一種好方法。

而後找到了第二種方法的方法。window.getSelection和document.selection

IE9如下支持:document.selection

IE九、Firefox、Safari、Chrome和Opera支持:window.getSelection()

(因爲咱們公司項目只支持ie9及以上,就沒有嘗試document.selection)

 

我本身試了一下,若是有選中的文字的時候window.getSelection().type === "Range",若是沒有選中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(十進制)
        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);
    }
});

發如今一家公司只要本身多包攬一些活,積極一些,總會有很是多的東西能夠學習的~2017加油~~

相關文章
相關標籤/搜索