统筹pc和挪动端的textarea字数监控的完成要领

一、需求论述和经常运用的处置惩罚方案

制造一个文本框限定最大字数,及时监听当前已输入的字数,并显现出来。期初我完成这个功用的要领很简单:给textarea控件增加onkeyup事宜要领,在要领中将textarea值的长度打印出来,并给textarea增加一个maxlength属性设置长度限定即可。代码以下:

<div class="form-group needCount">        
    <textarea id="txt0" maxlength="10"></textarea>
    <p><span id="txtNum0">0</span>/10</p>
</div>
var txt0 = document.getElementById("txt0");
var txtNum0 = document.getElementById("txtNum0");
txt0.addEventListener("keyup",function(){
    txtNum0.textContent = txt0.value.length;
});

二、存在的题目

如许貌似很简单就完成了,在英文输入法下一切还都ok,但当我们用输入法输入中文时,题目很快就来了,比方我们要输入“文章”一词就要输入“wenzhang”浏览器会监听到8词keyup事宜。在一些浏览器(如safari)中,假如这个历程凌驾maxlength甚至会阻挠你继承输入。因而纯真的监听keyup事宜显现是不够的。

《统筹pc和挪动端的textarea字数监控的完成要领》
每次按下键盘就会触发监听事宜

三、题目的处置惩罚

经由查阅先辈们的处置惩罚方案,发现了两个之前没有听说过的属性“compositionstart”和“compositionend”。
MDN上的诠释:compositionstart 事宜触发于一段笔墨的输入之前(类似于 keydown 事宜,然则该事宜仅在多少可见字符的输入之前,而这些可见字符的输入能够须要一连串的键盘操纵、语音辨认或许点击输入法的备选词)。
compositionend就是对应的就是一段笔墨输入的事宜。

有了这两个事宜,我们就能够做一个“开关”,一旦检测到开始运用输入法输入一段笔墨了,就把这个“开关翻开”,检测到一段笔墨输入终了了,就封闭这个“开关”。接下来我们在之前的keyup要领中增加一个剖断前提,假如开关封闭,一般打印出textaarea值的长度;假如开关翻开,住手打印。而输入一段笔墨时,监听输入完成的事宜“compositionend”,将textarea的值的长度打印出来。如许不管是不是开启了输入法都能准确的打印出控件值的长度了。

代码以下:(个中变量chnIpt就是代表是不是开启了输入法举行输入的症结变量“开关”)

    var txt0 = document.getElementById("txt0");
    var txtNum0 = document.getElementById("txtNum0");
    var chnIpt0 = false;

    txt0.addEventListener("keyup",function(){
        if(chnIpt0 ==false){
            countTxt();
        }
    });
    txt0.addEventListener("compositionstart",function(){
        chnIpt0 = true;
    })
    txt0.addEventListener("compositionend",function(){
        chnIpt0 = false;
        countTxt();
    })
    function countTxt(){
        if(chnIpt0 == false){
            txtNum0.textContent = txt0.value.length;
        }
    }

云云完成的结果就是英文输入法下没摊开键盘就会举行一次字数统计,输入法输入中文时,输入结束时才会统计字数。

四、完成复用

固然一个完整的插件一定是能够复用的。假如页面里须要多个文本框都要限定字数怎样完成。
我们须要斟酌以下几个题目:

  1. 症结元素(文本框txt和用于显现字数的txtNum)的变量建立和元素猎取怎样完成?
  2. 同是监听“keyup”和“compositionend”怎样辨别差别的textarea

要处置惩罚题目1,起首想到建立一个数组,数组中的每个元素经由过程差别的Id猎取一个元素。一个自力的历程当中我们须要猎取两个元素:txt和txtNun,一个症结变量chnIpt,因而我们要建立三个数组。为了轻易明白,假定页面中有须要三组控件:

    <div class="form-group needCount">        
        <textarea id="txt0" maxlength="10" onfocus="ff(0)"></textarea>
        <p><span id="txtNum0">0</span>/10</p>
    </div>
    <div class="form-group needCount">        
        <textarea id="txt1" maxlength="10" onfocus="ff(1)"></textarea>
        <p><span id="txtNum1">0</span>/10</p>
    </div>
    <div class="form-group needCount">        
        <textarea id="txt2" maxlength="10" onfocus="ff(2)"></textarea>
        <p><span id="txtNum2">0</span>/10</p>
    </div>

则建立数组的历程:

    var txt0 = document.getElementById("txt0");
    var txt1 = document.getElementById("txt1");
    var txt2 = document.getElementById("txt2");

    var txtNum0 = document.getElementById("txtNum0");
    var txtNum1 = document.getElementById("txtNum1");
    var txtNum2 = document.getElementById("txtNum2");

    var chnIpt0 = false;
    var chnIpt1 = false;
    var chnIpt2 = false;

    var txt=[txt0,txt1,txt2];
    var txtNum=[txtNum0,txtNum1,txtNum2];
    var chnIpt=[chnIpt0,chnIpt1,chnIpt2];

如许txt就是textarea控件的数组,txtNum就是实际字数的标签的数组,chnIpt就是推断“开关”的症结变量数组,以待挪用。

如今思索第二个题目“同是监听“keyup”和“compositionend”怎样辨别差别的textarea”。或许说,我们怎样推断当前输入的textarea是txt元素中的第几个呢。

这里就须要表单控件都具有的focus事宜举行区分,在focus事宜的要领中传入代表数组索引的参数,从而挑选挪用数组中响应谁人元素。

代码以下:(ff(i)即为focus事宜挪用的要领参数为索引值)

function ff(i){
    txt[i].addEventListener("keyup",function(){
        if(chnIpt[i] ==false){
            txtNum[i].textContent = txt[i].value.length;
        }
    });
    txt[i].addEventListener("compositionstart",function(){
        chnIpt[i] = true;
    });
    txt[i].addEventListener("compositionend",function(){
        chnIpt[i] = false;
        txtNum[i].textContent = txt[i].value.length;
    });
}

我们再来斟酌末了一个题目。现在是已知页面中须要几组文本框的状况,我们能够手动建立,费时辛苦代码也不美观。

进一步优化一下建立数组的历程:给每个自力的组件一个class,猎取具有这个class的元素的长度,轮回这个class的长度,给数组中增加元素即可。云云处置惩罚,援用一段剧本没必要再做变动,只须要在html中增加响应的组件即可。
JS代码以下

var txt = [],txtNum = [],chnIpt = [];
var needCount = document.getElementsByClassName("needCount");

for(var i=0;i<needCount.length;i++){
    txt[i] = document.getElementById("txt"+i);
    txtNum[i] = document.getElementById("txtNum"+i);
    chnIpt[i] = false;
}

终究完整的JS代码:

var txt = [],txtNum = [],chnIpt = [];
var needCount = document.getElementsByClassName("needCount");

for(var i=0;i<needCount.length;i++){
    txt[i] = document.getElementById("txt"+i);
    txtNum[i] = document.getElementById("txtNum"+i);
    chnIpt[i] = false;
}

function ff(i){
    txt[i].addEventListener("keyup",function(){
        if(chnIpt[i] ==false){
            txtNum[i].textContent = txt[i].value.length;
        }
    });
    txt[i].addEventListener("compositionstart",function(){
        chnIpt[i] = true;
    });
    txt[i].addEventListener("compositionend",function(){
        chnIpt[i] = false;
        txtNum[i].textContent = txt[i].value.length;
    });
}

《统筹pc和挪动端的textarea字数监控的完成要领》
一组字符输入完整之前不会监听自述变化

demo链接:点我

五、兼容性

云云完成学问该组件我尝试以来最为靠近预期的完成要领,在pc端主流浏览器(ie9以上),安卓、ios的原生键盘输入、“讯飞语音”的语音输入法结果优越。但在一些特定状况下仍然会出现题目,比如:

  1. 没法监听ios自带输入法的语音辨认输入
  2. 猎豹浏览器下运用鼠标点选词组会结算“keyup”而不是“compositionend”,而且会使maxlength失效。再次监听到“keyup”恢复一般。

以上两个题目至今没有找到处置惩罚,以及,我发如今火狐浏览器下会实行两次“compositionend”,但并不影响字数统计。诸如这些疑问还烦请网上的列位高人如碰到类似题目赋予鄙人指正与指导。

末了我想说一句话:“假如事宜不再有浏览器之间的差别,天下将变成优美的人世!”

    原文作者:Vict911
    原文地址: https://segmentfault.com/a/1190000009766117
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞