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 相关文章推荐
jQuery Tab插件 用于在Tab中显示iframe,附源码和详细说明
Jun 27 Javascript
Array.prototype.concat不是通用方法反驳[译]
Sep 20 Javascript
jQuery中DOM操作实例分析
Jan 23 Javascript
JS常见问题之为什么点击弹出的i总是最后一个
Jan 05 Javascript
简单谈谈javascript中this的隐式绑定
Feb 22 Javascript
Express之get,pos请求参数的获取
May 02 Javascript
详解Vue 开发模式下跨域问题
Jun 06 Javascript
node.js通过axios实现网络请求的方法
Mar 05 Javascript
浅谈Webpack 是如何加载模块的
May 24 Javascript
Vue实现按钮级权限方案
Nov 21 Javascript
微信小程序语音同步智能识别的实现案例代码解析
May 29 Javascript
token 机制和实现方式
Dec 15 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
用PHP控制用户的浏览器--ob*函数的使用说明
2007/03/16 PHP
PHP实现将视频转成MP4并获取视频预览图的方法
2015/03/12 PHP
PHP封装的Twitter访问类实例
2015/07/18 PHP
JavaScript 异步调用框架 (Part 5 - 链式实现)
2009/08/04 Javascript
Jquery练习之表单验证实现代码
2010/12/14 Javascript
js中关于new Object时传参的一些细节分析
2011/03/13 Javascript
Javscript删除数组中指定元素并返回新数组
2014/03/06 Javascript
JS实现网页背景颜色与select框中颜色同时变化的方法
2015/02/27 Javascript
jQuery模拟新浪微博首页滚动效果的方法
2015/03/11 Javascript
vue移动端裁剪图片结合插件Cropper的使用实例代码
2017/07/10 Javascript
用VueJS写一个Chrome浏览器插件的实现方法
2019/02/27 Javascript
深入了解Hybrid App技术的相关知识
2019/07/17 Javascript
Vue使用Clipboard.JS在h5页面中复制内容实例详解
2019/09/03 Javascript
使用xampp将angular项目运行在web服务器的教程
2019/09/16 Javascript
LayUI switch 开关监听 获取属性值、更改状态的方法
2019/09/21 Javascript
解决angular 使用原生拖拽页面卡顿及表单控件输入延迟问题
2020/04/21 Javascript
React+EggJs实现断点续传的示例代码
2020/07/07 Javascript
Vue 样式切换及三元判断样式关联操作
2020/08/09 Javascript
python 日志增量抓取实现方法
2018/04/28 Python
python打开使用的方法
2019/09/30 Python
TensorFlow梯度求解tf.gradients实例
2020/02/04 Python
Python线程threading模块用法详解
2020/02/26 Python
python批量检查两个对应的txt文件的行数是否一致的实例代码
2020/10/31 Python
Python的信号库Blinker用法详解
2020/12/31 Python
让IE9以下版本的浏览器兼容HTML5的方法
2014/03/12 HTML / CSS
怎样实现H5+CSS3手指滑动切换图片的示例代码
2019/05/05 HTML / CSS
爱尔兰灯和灯具网上商店:Lights.ie
2018/03/26 全球购物
奥林匹亚体育:Olympia Sports
2020/12/30 全球购物
.net开发工程师面试题
2014/02/25 面试题
青年创业培训欢迎词
2014/01/10 职场文书
幼儿园英语教学反思
2014/01/30 职场文书
创业者迈进成功第一步:如何写创业计划书?
2014/03/22 职场文书
如何写好自荐信
2014/04/07 职场文书
爱耳日活动总结
2014/04/30 职场文书
Pytest之测试命名规则的使用
2021/04/16 Python
Java如何实现树的同构?
2021/06/22 Java/Android