功能
产品需求:input 需要限制字符长度为 10。(中文 2 个字符英文 1 个字符)
考虑场景:input 中文问题、光标定位问题、字符串截取问题。
实现思路
实现上述需求需监听 3 个事件:input compositionupdate compositionend
获取光标位置
function getCursortPosition(obj) {
var cursorIndex = 0;
if (document.selection) {
// IE Support
obj.focus();
var range = document.selection.createRange();
range.moveStart("character", -obj.value.length);
cursorIndex = range.text.length;
} else if (obj.selectionStart || obj.selectionStart == 0) {
// another support
cursorIndex = obj.selectionStart;
}
return cursorIndex;
}
功能实现
let flag = true; //设定全局变量在输入中文过程中不执行赋值操作
$("#input")
.on("input", function(e) {
setMaxlen(this);
})
.on("compositionupdate", function() {
flag = false;
})
.on("compositionend", function() {
flag = true;
setMaxlen(this);
});
/**
* @param {object} el DOM元素
*/
function setMaxlen(el) {
let val = $(el).val(), //获取value
maxLen = $(el).data("max"), //获取限制输入的最大值
len = val.replace(/[^\x00-\xff]/g, "**").length, //获取input长度
startLen = getCursortPosition(el), //获取光标位置
endLen = val.substring(startLen).replace(/[^\x00-\xff]/g, "**").length; //光标后面有几个字符(计算后的)
if (flag && len > maxLen) {
let num = maxLen - endLen,//求出光标前面剩余的字符长度
str = val.substring(0, maxLen - endLen);//截取长度
while (str.replace(/[^\x00-\xff]/g, "**").length > num) {//因涉及中文,循环截取
if (str.length === 0) {
str = "";
break;
}
str = str.substring(0, str.length - 1);
}
$(el).val(str + val.substring(startLen));//设置value
//设置完value后需要重新设置下光标的位置。
let newStrLen = $(el).val().length,//获取设置完value后的长度
setEnd = val.substring(startLen).length;//获取原input光标后有几个字符
el.setSelectionRange(newStrLen - setEnd, newStrLen - setEnd);//设置光标位置
}
}
参考文献