Implementation of textarea word number monitoring based on both pc and mobile

Keywords: Javascript iOS Attribute Android Firefox

I. Requirement Description and Common Solutions

Make a text box to limit the maximum number of words, real-time monitor the number of currently entered words, and display. At the beginning of this period, I realized this function by adding onkeyup event method to textarea control, printing out the length of textarea value in the method, and adding a maxlength attribute to textarea to set the length limit. The code is as follows:

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

II. Problems

This seems to be a very simple implementation. Everything is ok under the English input method, but when we input Chinese with the input method, the problem soon arises. For example, if we want to enter the word "article", we need to enter the word "wenzhang" browser to listen to the 8-word keyup event. In some browsers, such as safari, if this process exceeds maxlength, it may even prevent you from continuing to type. So simply listening for keyup event display is not enough.

3. Solution of the Problem

After consulting the solutions of our predecessors, we found two previously unheard-of attributes, "composition start" and "composition end".
Interpretation on MDN: Composition start event triggers before a text input (similar to keydown event, but only before several visible characters are entered, which may require a series of keyboard operations, speech recognition or click input alternatives).
compositionend corresponds to an event of text input.

With these two events, we can make a "switch". Once we detect that we are starting to input a paragraph of text using the input method, we turn on the "switch". When we detect that a paragraph of text has been input, we can watch the "switch". Next, we add a criterion in the previous keyup method. If the switch is turned off, the length of the textaarea value will be printed normally; if the switch is turned on, the print will stop. When you enter a paragraph of text, listen for the completed event "composition end" and print out the length of the value of textarea. In this way, whether the input method is turned on or not, the length of the control value can be correctly printed out.

The code is as follows: (where the variable chnIpt represents whether the key variable "switch" for input method is turned on or not)

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

The effect of this is that the number of words will be counted once the keyboard is not opened in the English input method. When the input method enters Chinese, the number of words will be counted at the end of the input.

IV. Realizing Reuse

Of course, a complete plug-in must be reusable. If multiple text boxes are needed in a page, limit how many words are implemented.
We need to consider the following issues:

  1. How can variable creation and element acquisition of key elements (text box txt and txtNum for displaying word numbers) be implemented?

  2. It's also about listening for "keyup" and "composition end" to distinguish different textarea s

To solve problem 1, first of all, I want to create an array, each element in the array gets an element through a different Id. In an independent process, we need to get two elements: txt and txtNun, a key variable chnIpt, so we need to create three arrays. For ease of understanding, assume that there are three sets of controls in the page:

    <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>

The process of creating an array:

    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];

In this way, txt is an array of textarea controls, txtNum is an array of labels for real numbers, chnIpt is an array of key variables for judging "switches" to be invoked.

Now consider the second question, "How to distinguish different textareas by listening for"keyup"and"composition end". In other words, how do we judge that the textarea currently entered is the number one in the txt element?

Here, we need to distinguish the focus events that form controls all have. In the method of focus events, we pass in the parameters representing the index of the array, so that we can select the corresponding element in the call array.

The code is as follows: (ff(i) The method parameter invoked for the focus event is the index value)

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

Let's consider the last question. At present, it is known that several sets of text boxes are needed in a page. We can create them manually, and the time-consuming and laborious code is not beautiful.

Further optimize the process of creating arrays: give each individual component a class, get the length of the element with the class, loop the length of the class, and add elements to the array. In this way, there is no need to change the reference script, just add the corresponding components in html.
The JS code is as follows

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

The final complete JS code:

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

demo link:Point me

V. Compatibility

This component is the closest to the expected implementation method since I tried. In the mainstream browser on the pc side (ie9 or above), the native keyboard input of Android and ios, and the voice input method of "Xunfei voice" have achieved good results. However, problems still arise in some specific situations, such as:

  1. Unable to monitor speech recognition input with ios input method

  2. Using mouse-click phrases under cheetah browser clears "keyup" instead of "composition end" and invalidates maxlength. The Keyup was again monitored to return to normal.

These two problems have not yet been solved, and I found that in Firefox browser will be executed twice "composition end", but does not affect the word count. For example, these questions are also bothersome to ask the senior people on the Internet if they encounter similar problems to give the following corrections and suggestions.

Finally, I want to say a word: "If there is no difference between browsers, the world will become a beautiful world!"

Posted by rallan on Sat, 22 Jun 2019 14:46:59 -0700