Reputation: 71
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(...)
) doesn't work because directly calling the KeyboardEvent constructor results in following exception:
Exception: TypeError: '[object KeyboardEventConstructor]' is not a constructor (evaluating 'new KeyboardEvent(...)')
I have no more ideas.
Upvotes: 4
Views: 5386
Reputation: 71
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.
Upvotes: 3