Written on November 1, 2017, please correct any mistakes or omissions.

The original

In mobile H5 page development, there are sometimes numerical input requirements. If the user needs to easily enter decimal and negative numbers, the easiest way is to use the input box of type number. The soft keyboard switches to a numeric keyboard for easy input (ios is a full keyboard with numbers and allows representations such as 1e5). However, in actual use, there is a problem. When the input content is illegal, for example, 1… Input sets its status to invalid and empties value. We can style this input error with INPUT :invalid in CSS, but on the JS side, we have no way of knowing what the user is typing wrong. The problem is a feature of the DOM itself, regardless of the framework we use. Whether we use Angular, Vue, or React, js has no way of knowing what is wrong with an input of type number and thus helping the user correct the error.

The actual requirements, however, don’t matter. Limiting the range of values the user can enter, precision after the decimal point, allowing negative numbers, and so on are common requirements. So what to do? Recently I saw an article made a very helpless, but really gorgeous attempt: a numeric keyboard caused by the bloody case — mobile terminal H5 input box, cursor, numeric keyboard full false suite implementation. For those interested, this article implements a fake keyboard to handle this logic. A fake keyboard is the ultimate solution for complex interaction and visual requirements. But in my opinion, processing number format, error correction and other problems can not be so troublesome, I will share my ideas.

Set a goal:

  1. Negative numbers allowed
  2. A maximum of five digits can be entered
  3. At most two decimal places are allowed
  4. Automatically clears redundant leading zeros
  5. Automatically replenishes the whole 0 part of the pure decimal

With all these goals in mind, it really boils down to simple string processing as long as you can get the input from the input box. So how do you get input? My method is to have the browser select everything in the input box, then get the selected string in the browser, and finally clear the selected state. There are two ways to select the contents of the input box:

  1. The simplest is to call it directlyinput.select()(HTMLInputElement.select());
  2. This can be used when the input box is already in focus (of course)document.execCommand('SelectAll')To select everything in the input box (The selectAll command).

SelectRange is not allowed for input boxes of type number. Although I can select the contents and get the information in the input box, I have a problem clearing the selected state (maybe I wrote the code wrong), so I use the second method. To get the browser-selected string, use window.getSelection ().tostring () (window.getSelection ()). After obtaining the actual input, we can make a series of logical judgments and numerical corrections. So how do you finally write the correct content back into the input box and clear the checked status? There are many ways:

  1. Write the correct content into the Clipboard and paste it into the selected areadocument.execCommand('copy')anddocument.execCommand('paste')(The copy command,The paste command);
  2. Perform an Undo operation to roll back The input field to The previous correct result (The Undo Command).
  3. Execute The insertText command to insert new text at The selected region (The insertText command).

Most of the preparatory work is done here, try to practice:

<input type="number" id="input"/>
Copy the code
const input = document.querySelector('#input');

const format = / -? (\. \ \ d {0, 5} d} {0, 2)? /;
let lastValue;

input.addEventListener('input', event => {
    document.execCommand('SelectAll');
    let text = window.getSelection().toString();
    if(lastValue ! == text) {const match = text.match(format);
        if(! match) { text =' ';
        }
        else {
            text = match[0]
                .replace(/ ^ (?) 0+(\d)/.'$1 $2') // Delete redundant leading zeros
                .replace(/ ^ (?) / \..'$10.); // Insert the integer 0 for the pure decimal
        }
        lastValue = text;
        document.execCommand('insertText'.false, text); }});Copy the code

Demo