Нужно чтобы в input выполнялся атрибут maxlength="1" при вводе с виртуальной клавиатуры на JS

// SCRIPT FOR KEYBOARD

const Keyboard = {
    elements: {
        keys: []
    },

    eventHandlers: {
        oninput: null,
    },

    properties: {
        value: "",
    },

    init() {
        // Create main elements
        this.elements.main = document.createElement("div");
        this.elements.keysContainer = document.createElement("div");

        // Setup main elements
        this.elements.main.classList.add("keyboard", "keyboard--hidden");
        this.elements.keysContainer.classList.add("keyboard__keys");
        this.elements.keysContainer.appendChild(this._createKeys());

        // Add to DOM
        this.elements.main.appendChild(this.elements.keysContainer);
        document.body.appendChild(this.elements.main);

        // Automatically use keyboard for elements with .use-keyboard-input
        document.querySelectorAll(".use-keyboard-input").forEach(element => {
            element.addEventListener("focus", () => {
                this.open(element.value, currentValue => {
                    element.value = currentValue;
                });
            });
        });
    },

    _createKeys() {
        const fragment = document.createDocumentFragment();
        const keyLayout = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "bks"];

        // Creates HTML for an icon
        const createIconHTML = (icon_name) => {
            return `<i class="material-icons">${icon_name}</i>`;
        };

        keyLayout.forEach(key => {
            const keyElement = document.createElement("button");
            const insertLineBreak = ["bks"].indexOf(key) !== -1;

            // Add attributes/classes
            keyElement.setAttribute("type", "button");
            keyElement.classList.add("keyboard__key");

            switch (key) {
                case "bks":
                    // keyElement.classList.add("keyboard__key--wide");
                    keyElement.innerHTML = createIconHTML("bks");

                    keyElement.addEventListener("click", () => {
                        this.properties.value = this.properties.value.substring(0, this.properties.value.length - 1);
                        this._triggerEvent("oninput");
                    });

                    break;

                default:
                    keyElement.textContent = key.toLowerCase();

                    keyElement.addEventListener("click", () => {
                        this.properties.value += this.properties.capsLock ? key.toUpperCase() : key.toLowerCase();
                        this._triggerEvent("oninput");
                    });

                    break;
            }

            fragment.appendChild(keyElement);

            if (insertLineBreak) {
                fragment.appendChild(document.createElement("br"));
            }
        });

        return fragment;
    },

    _triggerEvent(handlerName) {
        if (typeof this.eventHandlers[handlerName] == "function") {
            this.eventHandlers[handlerName](this.properties.value);
        }
    },

    open(initialValue, oninput) {
        this.properties.value = initialValue || "";
        this.eventHandlers.oninput = oninput;
    },

};

window.addEventListener("DOMContentLoaded", function () {
    Keyboard.init();
});
<div id="blok0"> 

    <fieldset >
      <input type="num" readonly style="cursor: pointer" id="number1" class="use-keyboard-input" maxlength="1" />
        <input type="num" readonly style="cursor: pointer" id="number1" class="use-keyboard-input" maxlength="1" />
      <input type="num" readonly style="cursor: pointer" id="number1" class="use-keyboard-input" maxlength="1" />
        <input type="num" readonly style="cursor: pointer" id="number1" class="use-keyboard-input" maxlength="1" />
      <input type="num" readonly style="cursor: pointer" id="number2" class="use-keyboard-input" maxlength="1" />
    </fieldset >

</div>

Добрый день! Нашел в интернете виртуальную клавиатуру на js (сам в js не силен). Прикрутил к своему коду. Работает, но не выполняется атрибут maxlength="1". С аппаратной клавы все нормально. Что нужно и где подправить, чтобы заработало.


Ответы (1 шт):

Автор решения: Дмитрий

Дело в том, что maxlength ограничивает ввод в поле input только когда это делает пользователь с клавиатуры, в данном же случае ввод в поле делается через javascript, изменяя свойство value, поэтому тут атрибут просто игнорируется.

Решить проблему можно добавив в обработчик нажатия на кнопку виртуальной клавиатуры проверку на наличие атрибута maxlength. Например так (для примера установил тут разные значения maxlength для разных полей ввода):

// SCRIPT FOR KEYBOARD

const Keyboard = {
    elements: {
        keys: []
    },

    eventHandlers: {
        oninput: null,
    },

    properties: {
        value: "",
    },

    init() {
        // Create main elements
        this.elements.main = document.createElement("div");
        this.elements.keysContainer = document.createElement("div");

        // Setup main elements
        this.elements.main.classList.add("keyboard", "keyboard--hidden");
        this.elements.keysContainer.classList.add("keyboard__keys");
        this.elements.keysContainer.appendChild(this._createKeys());

        // Add to DOM
        this.elements.main.appendChild(this.elements.keysContainer);
        document.body.appendChild(this.elements.main);

        // Automatically use keyboard for elements with .use-keyboard-input
        document.querySelectorAll(".use-keyboard-input").forEach(element => {
            element.addEventListener("focus", () => {
                this.open(element.value, key => {
                    if (key === "bks") {
                        element.value = element.value.substring(0, element.value.length - 1);
                        return
                    }
                    if (element.getAttribute('maxlength') && element.value.length >= element.getAttribute('maxlength')) {
                        return
                    }
                    element.value += key;
                });
            });
        });
    },

    _createKeys() {
        const fragment = document.createDocumentFragment();
        const keyLayout = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "bks"];

        // Creates HTML for an icon
        const createIconHTML = (icon_name) => {
            return `<i class="material-icons">${icon_name}</i>`;
        };

        keyLayout.forEach(key => {
            const keyElement = document.createElement("button");
            const insertLineBreak = ["bks"].indexOf(key) !== -1;

            // Add attributes/classes
            keyElement.setAttribute("type", "button");

            switch (key) {
                case "bks":
                    keyElement.innerHTML = createIconHTML("bks");
                    break;
                default:
                    keyElement.textContent = key.toLowerCase();
                    break;
            }

            keyElement.addEventListener("click", () => {
                this._triggerEvent("oninput", key);
            });

            fragment.appendChild(keyElement);

            if (insertLineBreak) {
                fragment.appendChild(document.createElement("br"));
            }
        });

        return fragment;
    },

    _triggerEvent(handlerName, key) {
        if (typeof this.eventHandlers[handlerName] == "function") {
            this.eventHandlers[handlerName](key);
        }
    },

    open(initialValue, oninput) {
        this.properties.value = initialValue || "";
        this.eventHandlers.oninput = oninput;
    },

};

window.addEventListener("DOMContentLoaded", function () {
    Keyboard.init();
});
<html lang="en">
<head>
    <script src="main.js"></script>
    <title>test</title>
</head>
<body>
<div id="blok0">
    <fieldset>
        <input type="num" style="cursor: pointer" id="number1" class="use-keyboard-input" maxlength="1"/>
        <input type="num" style="cursor: pointer" id="number2" class="use-keyboard-input" maxlength="2"/>
        <input type="num" style="cursor: pointer" id="number3" class="use-keyboard-input" maxlength="3"/>
        <input type="num" style="cursor: pointer" id="number4" class="use-keyboard-input" maxlength="4"/>
        <input type="num" style="cursor: pointer" id="number5" class="use-keyboard-input" />
    </fieldset>
</div>
</body>
</html>

→ Ссылка