How to send Keyboard events (e.g. Backspace, Delete) in Safari from javascript

i'm implementing an on-screen Keyboard for a javascript-Application. The text should appear in a textarea-Element. I've no problem creating text-events but feel unable to create non-text events such as the Backspace. Here is some sample code:


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

The interesting function here is "sendBackEvent()". I tried hard to get exactly the same event like pressing the Backspace-Button on the physical Keyboard but didn't succeed. I know there is a Webkit-Bug but hoped there could be some other way to get this working. Has anyone had the same problem? Could it be solved? How? The proposed solution here (calling new KeyboardEvent(...) ) dosn't work because directly calling the KeyboardEvent constructor results in following exception:

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

I'm struggeling here since 2 days and has no more Ideas.


Since there seem to no way out, i found myself constrained to install my own backspace event handler. The working code (without logging now) is here:


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

Just in case someone else run into same trouble.

链接地址: http://www.djcxy.com/p/49178.html

上一篇: 64位系统上的NULL定义问题

下一篇: 如何在Safari中发送键盘事件(例如Backspace,Delete)