Как отправлять события клавиатуры (например, Backspace, Delete) в Safari из javascript


Я внедряю экранную клавиатуру для javascript-приложения. Текст должен появиться в элементе textarea. У меня нет проблем с созданием текстовых событий, но я чувствую, что не могу создавать нетекстовые события, такие как Backspace. Вот пример кода:


    <html>
    <head>
    <title>Test Textarea Events</title>
    <script type="text/javascript">
    function log(text) {
        var elem = document.getElementById("log");
        if (elem) {
            elem.innerHTML += "<br/>" + text;
        }
    }
    function logEvent(e) {
        log("Type: " + e.type + ", which: " + e.which + ", keyCode: " + e.keyCode + ", charCode: " + e.charCode + ", keyIdentifier: " + e.keyIdentifier + ", data: " + e.data);
    }
    function logClear() {
        var elem = document.getElementById("log");
        if (elem) {
            elem.innerHTML = "";
        }
    }
    function sendBackEvent() {
        var textarea = document.getElementById("textarea");
        if(!textarea) {
            return;
        }
        var ke1 = document.createEvent("KeyboardEvent");
        ke1.initKeyboardEvent("keydown", true, true, window, "U+0008", 0, ""); // U+0008 --> Backspace
        // how to set "keyCode" and "which"?
        //  1. ke1.keyCode = 8; will be ignored due to "writable: false"
        //  2. delete ke1.keyCode will be ignored too
        //     and Object.defineProperty(KeyboardEvent.prototype, "keyCode", ... whatever ...); 
        //     will result in Exception due to "configurable: false"
        //  3. generating a more general Event (e.g. "var e = document.createEvent("Events");")
        //     and setting all necessary props (e.g. "e.initEvent("keydown", true, true);e.keyCode=8;e.which=8;")
        //     will work, but the textarea will ignore the Event
        textarea.dispatchEvent(ke1);

        var ke2 = document.createEvent("KeyboardEvent");
        ke2.initKeyboardEvent("keyup", true, true, window, "U+0008", 0, ""); // U+0008 --> Backspace
        // same question as above
        textarea.dispatchEvent(ke2);
    }
    function init() {
        var textarea = document.getElementById("textarea");
        if(!textarea) {
            return;
        }
        textarea.addEventListener("keydown", logEvent, false);
        textarea.addEventListener("keypress", logEvent, false);
        textarea.addEventListener("keyup", logEvent, false);
        textarea.addEventListener ("textInput", logEvent, false);
    }
    </script>
    </head>
    <body onload="init()">
    <textarea id="textarea" name="text" cols="100" rows="20"></textarea><br/><br/>
    <button onclick="sendBackEvent()">send BackEvent</button>
    <button onclick="logClear()">clear log</button><br/>
    <div id="log"></div>
    </body>
    </html>

Интересной функцией здесь является " sendBackEvent ()". Я изо всех сил пытался получить точно такое же событие, как нажатие кнопки Backspace на физической клавиатуре, но не преуспел. Я знаю, что есть Webkit-баг , но надеялся может быть, есть какой-то другой способ заставить это работать. У кого-нибудь была такая же проблема? Может ли она быть решена? Но как? Предлагаемое решение здесь (вызов new KeyboardEvent(...)) dosn не работает, потому что прямой вызов конструктора KeyboardEvent приводит к следующему исключению:

Exception: TypeError: '[object KeyboardEventConstructor]' is not a constructor (evaluating 'new KeyboardEvent(...)')

Я борюсь здесь уже 2 дня и больше не имею никаких идей.

1 3

1 ответ:

Поскольку выхода, похоже, нет, я оказался вынужден установить свой собственный обработчик событий backspace. Рабочий код (без регистрации сейчас) находится здесь:


    <html>
    <head>
    <title>Test Textarea Events</title>
    <script type="text/javascript">
    function sendBackEvent() {
        var textarea = document.getElementById("textarea");
        if(!textarea) {
            return;
        }
        var ke1 = document.createEvent("Events");
        ke1.initEvent("keydown", true, true);
        ke1.keyCode = ke1.which = 8; // Backspace
        textarea.dispatchEvent(ke1);

        var ke2 = document.createEvent("Events");
        ke2.initEvent("keyup", true, true);
        ke2.keyCode = ke2.which = 8; // Backspace
        textarea.dispatchEvent(ke2);
    }
    function handleBackEvent(e) {
        if(e.keyCode != 8) {
            return;
        }
        if (textarea.value.length == 0) {
            return;
        }
        var text = textarea.value;
        var selectionStart = textarea.selectionStart;
        var selectionEnd = textarea.selectionEnd;
        if (selectionStart < selectionEnd) {
            var text1 = (selectionStart > 0 ? text.slice(0, selectionStart) : "");
            var text2 = (selectionEnd < text.length ? text.slice(selectionEnd) : "");
            textarea.value = text1 + text2;
        }
        else if (selectionStart > 0) {
            var text1 = (selectionStart - 1 > 0 ? text.slice(0, selectionStart - 1) : "");
            var text2 = (selectionStart < text.length ? text.slice(selectionStart) : "");
            textarea.value = text1 + text2;
            selectionStart--;
        }
        textarea.selectionStart = textarea.selectionEnd = selectionStart;
        e.preventDefault();
        e.stopPropagation();
        return false;
    };
    var textarea;
    function init() {
        textarea = document.getElementById("textarea");
        if(!textarea) {
            return;
        }
        textarea.addEventListener("keydown", handleBackEvent, false);
    }
    </script>
    </head>
    <body onload="init()">
    <textarea id="textarea" name="text" cols="100" rows="20"></textarea><br/><br/>
    <button onclick="sendBackEvent()">send BackEvent</button>
    </body>
    </html>

Просто на случай, если кто-то еще попадет в такую же беду.