Завоевать поле ввода типа число

внешний интерфейс

Написано 1 ноября 2017 года. Если есть ошибки или неточности, прошу исправить.

оригинальный

При разработке мобильных страниц H5 иногда возникают требования к числовому вводу. Если вам нужно упростить пользователям ввод десятичных и отрицательных чисел, проще всего использовать поле ввода числового типа.При вводе программная клавиатура переключается на цифровую клавиатуру для облегчения ввода (ios — это полноценная клавиатура с цифрами и позволяет отображать 1e5 и т. д.). Но при фактическом использовании возникнет проблема, когда вводимый контент является незаконным, например ввод1...2, в это время вход установит свое собственное состояние в недопустимое и очистит значение. Мы можем передать в cssinput:invalidЧтобы установить стиль ошибки содержимого ввода для этого ввода и на стороне js, мы не можем знать, каково содержание ошибки пользовательского ввода. Эта проблема задается характеристиками самого dom и не имеет ничего общего с используемой нами средой разработки.Используем ли мы angular, vue или react, когда во ввод числового типа вводится недопустимый контент, js не имеет возможности узнать каково содержание ошибки. Нет никакого способа помочь пользователям исправить ошибки ввода.

Однако фактические потребности могут игнорировать это, и очень часто ограничивают диапазон значений, вводимых пользователем, точность после запятой, разрешают ли отрицательные числа и так далее. тогда что нам делать? Я недавно видел статью и сделал очень беспомощную, но действительно великолепную попытку:Кровавый случай, вызванный цифровой клавиатурой - реализация поля ввода мобильного терминала H5, курсора и полной поддельной цифровой клавиатуры.. Если вам интересно, вы можете взглянуть В этой статье реализована поддельная клавиатура для обработки этой логики. При очень сложных взаимодействиях и визуальных требованиях создание поддельной клавиатуры также является идеальным решением. Однако, на мой взгляд, разобраться с цифровым форматом, исправлением ошибок и другими вопросами можно и без таких заморочек, о чем я поделюсь ниже.

Ставим цель:

  1. Допускаются отрицательные числа
  2. Введите до 5 цифр
  3. Допускается до двух знаков после запятой
  4. Автоматически удалять лишние ведущие 0
  5. Автоматически дополнять целую часть чистого десятичного числа 0

Несмотря на то, что было поставлено так много целей, в конечном счете, пока можно получить входное содержимое поля ввода, остальное — простая обработка строк. Итак, как я могу получить входной контент? Мой подход заключается в том, чтобы браузер выбирал все в поле ввода, затем получал строку, выбранную в браузере, и, наконец, очищал выбранное состояние. Существует два способа выбора содержимого поля ввода:

  1. Проще всего позвонить напрямуюinput.select()(HTMLInputElement.select());
  2. Когда поле ввода имеет фокус (конечно), вы можете использоватьdocument.execCommand('SelectAll')чтобы выбрать все в поле ввода (The selectAll command).

Однако на самом деле поле ввода типа number не позволяет оперировать selectRange.Хотя содержимое может быть выбрано и информация в поле ввода может быть получена, я столкнулся с проблемой при очистке выбранного состояния (возможно, мой код написан неправильно), то используйте первые два метода. Чтобы получить строку, выбранную браузером, вы можете использоватьWindow.getSelection().toString()(Window.getSelection()). Получив фактическое входное содержимое, мы можем сделать ряд логических суждений и числовых исправлений. Так как же, наконец, записать правильное содержимое обратно в поле ввода и одновременно очистить выбранное состояние? Есть много способов:

  1. Запишите правильный контент в буфер обмена, а затем вставьте его в выделенную область, в основном используяdocument.execCommand('copy')а такжеdocument.execCommand('paste')(The copy command,The paste command);
  2. Выполните операцию отмены напрямую и верните содержимое поля ввода к предыдущему правильному результату (The undo command);
  3. Выполните команду insertText, чтобы вставить новый текст в выделенную область (The insertText command).

В основном вся подготовительная работа, необходимая здесь, выполнена, попробуйте потренироваться:

<input type="number" id="input"/>
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') // 删除多余的前置0
                .replace(/^(-?)\./, '$10.'); // 插入纯小数的整数0
        }
        lastValue = text;
        document.execCommand('insertText', false, text);
    }
});

Demo