js 将input框中的输入自动转化成半角大写(税号输入框)
这两天出了这么一个需求,输入税号的时候,需要自动将其转化为半角大写,并且阻止标点符号中文汉字的输入。(下面会有:全半角转换、文本框选中、光标位置判断、设置光标位置 这些内容)
然后我就开始了慢慢查找资料之路。
首先查了全半角的区别以及如何转化。
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进制)
转化的话除了空格不同之外,其他均为全角-半角=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方法。
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); } });
但是有一个问题,那就是光标有问题,始终在最后一位输入的时候没问题,但是在中间输入,光标始终会跳到最后一位。于是又有了下面的光标相关知识。
在网上找到了下列相关代码,用来控制光标位置。
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对象。
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 在文本中搜索文本并将范围的开始和结束点设置为包围搜索字符串。
具体使用可见其他人的文章,地址是:
回到正题,于是我把上述代码拼进了我的代码中。
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
ie9、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); } });
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
上一篇: 快速自学Linux命令的4种方法
下一篇: js实现截图保存图片功能的代码示例