js 将input框中的输入自动转化成半角大写(税号输入框)


Posted in Javascript onFebruary 16, 2017

这两天出了这么一个需求,输入税号的时候,需要自动将其转化为半角大写,并且阻止标点符号中文汉字的输入。(下面会有:全半角转换、文本框选中、光标位置判断、设置光标位置 这些内容)

然后我就开始了慢慢查找资料之路。

首先查了全半角的区别以及如何转化。

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             在文本中搜索文本并将范围的开始和结束点设置为包围搜索字符串。

具体使用可见其他人的文章,地址是:https://3water.com/article/105787.htm

回到正题,于是我把上述代码拼进了我的代码中。

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

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
Javascript 变量作用域 两个可能会被忽略的小特性
Mar 23 Javascript
bootstrap table 服务器端分页例子分享
Feb 10 Javascript
JS使用ajax从xml文件动态获取数据显示的方法
Mar 24 Javascript
HTML中使背景图片自适应浏览器大小实例详解
Apr 06 Javascript
详解webpack编译多页面vue项目的配置问题
Dec 11 Javascript
微信小程序实现人脸识别
May 25 Javascript
vue加载完成后的回调函数方法
Sep 07 Javascript
JS中判断字符串存在和非空的方法
Sep 12 Javascript
js实现弹出框的拖拽效果实例代码详解
Apr 16 Javascript
vue循环数组改变点击文字的颜色
Oct 14 Javascript
countUp.js实现数字滚动效果
Oct 18 Javascript
es6函数之箭头函数用法实例详解
Apr 25 Javascript
基于JS实现翻书效果的页面切换样式
Feb 16 #Javascript
js实现3d悬浮效果
Feb 16 #Javascript
JavaScript中利用构造器函数模拟类的方法
Feb 16 #Javascript
js实现截图保存图片功能的代码示例
Feb 16 #Javascript
javaScript+turn.js实现图书翻页效果实例代码
Feb 16 #Javascript
原生JS实现图片翻书效果
Feb 16 #Javascript
js 单引号替换成双引号,双引号替换成单引号的实现方法
Feb 16 #Javascript
You might like
ThinkPHP行为扩展Behavior应用实例详解
2014/07/22 PHP
PHP获取表单所有复选框的值的方法
2014/08/28 PHP
php类自动加载器实现方法
2015/07/28 PHP
很酷的javascript loading效果代码
2008/06/18 Javascript
innerHTML 和 getElementsByName 在IE下面的bug 的解决
2010/04/09 Javascript
在js(jquery)中获得文本框焦点和失去焦点的方法
2012/12/04 Javascript
jquery text(),val(),html()方法区别总结
2013/11/04 Javascript
JSONP跨域的原理解析及其实现介绍
2014/03/22 Javascript
IE中的File域无法清空使用jQuery重设File域
2014/04/24 Javascript
Es6 写的文件import 起来解决方案详解
2016/12/13 Javascript
使用nodejs下载风景壁纸
2017/02/05 NodeJs
详解vue组件化开发-vuex状态管理库
2017/04/10 Javascript
angularjs中回车键触发某一事件的方法
2017/04/24 Javascript
解决vuecli3.0热更新失效的问题
2018/09/19 Javascript
p5.js临摹旋转爱心
2019/10/23 Javascript
python处理中文编码和判断编码示例
2014/02/26 Python
Python类的用法实例浅析
2015/05/27 Python
Python+django实现简单的文件上传
2016/08/17 Python
对numpy下的轴交换transpose和swapaxes的示例解读
2019/06/26 Python
解决在pycharm运行代码,调用CMD窗口的命令运行显示乱码问题
2019/08/23 Python
Python爬虫JSON及JSONPath运行原理详解
2020/06/04 Python
python爬虫爬取网页数据并解析数据
2020/09/18 Python
基于Canvas+Vue的弹幕组件的实现
2019/07/23 HTML / CSS
接口的多继承会带来哪些问题
2015/08/17 面试题
解释一下钝化(Swap out)
2016/12/26 面试题
采购内勤岗位职责
2013/12/10 职场文书
部队党性分析材料
2014/02/16 职场文书
中学生的1000字检讨书
2014/10/11 职场文书
给客户的感谢信
2015/01/21 职场文书
骨干教师个人总结
2015/02/11 职场文书
2015年初中生自我评价范文
2015/03/03 职场文书
销售员自我评价
2015/03/11 职场文书
特此通知格式
2015/04/27 职场文书
2015中秋节晚会开场白
2015/07/30 职场文书
python字典的元素访问实例详解
2021/07/21 Python
Rhit高效可视化Nginx日志查看工具
2021/11/01 Servers