How can I programmatically generate keypress events from Javascript code running in Safari? It looks like WebKit is using the DOM level 3 model for creating keyboard events from Javascript, and the DOM level 3 keyboard event model does not support the keypress event. Is there another way that I can use?
I'm looking for as pure a Safari/WebKit DOM solution as possible. I'd really prefer not to modify the web page, and I'd also rather not add dependencies on external libraries. I need to activate any existing keypress handlers, so it won't work to add a new handler and directly call it.
It looks like WebKit has the keyCode and charCode properties of the keypress event defined in its UIEvent class, but they are read-only. Is there any way to set those properties? The following does not work:
var evt = document.createEvent('UIEvents');
evt.initUIEvent('keypress', true, true, window, 0);
evt.keyCode = 114; // 'r'
evt.charCode = 114;
alert("keyCode = " + evt.keyCode + ", charCode = " + evt.charCode); // both 0
Setting the detail property in the call to initUIEvent also seems to have no effect.
Use the TextEvent (introduced by DOM3). Since you're looking to generate keypress events, I'm guessing you're working with characters. In the code below, textToInsert is a string, and textarea the element I'm dispatching the event to.
var eventObject = document.createEvent('TextEvent');
eventObject.initTextEvent('textInput',
true,
true,
null,
textToInsert);
textarea.dispatchEvent(eventObject);
This works on Safari 3.1.2 (consequently on Chrome).
Sounds like a very similar (non browser specific) question was asked and answered already:
Trigger a keypress with jQuery...and specify which key was pressed
I have had the same problem. I wanted to be able to write a test that when the enter key is pressed on the GUI a line item (li) is added to a list. For then, I needed to "generate" a keypress. Having tried to generate the event, simulate an event, mock out the event (jqMock), here's a very simple solution.
I can continue on with BDDing my code using jsSpec and jQuery code. This test would be a little harder if you used a plugin to manage the keypresses (eg hotkeys jQuery plugin)
Here's what I want to do:
describe 'I need to be able to edit items in a list', {
... [setup code and other tests]
'should create a new item if I press enter': function(){
value_of($('#todo').items().size()).should_be(7)
// be on the last item in the list
task = $('#todo').items().filter(':last').focus()
// press enter
task.__keypress(13)
// check that an item was added
value_of($('#todo').tasks().size()).should_be(8)
},
}
Here's the code that binds the handler. Note with this solution I intercept the event and only pass through the which
code - this allows me to pass in the value from the test. That is all I need at the moment. Obviously, if I wanted to intercept more I would need to expand what is passed in (for example, see jquery.hotkeys plugin):
$().items().bind('keypress', function(event){$().__keypress(event.which)})
And here's the handler:
__keypress: function(which){
switch(which)
{
...
case 13: // enter
[my code that creates a new item]
break;
default:
}
},
ps: if anyone is able to mock window.event let me know. I didn't have any luck using jqMock.
http://docs.jquery.com/Events/keypress#fn
In other words, you attach a keypress event to some element. Using an element with the ID of "someid", for example:
<script language="text/javascript" src="jquery.js"></script>
<script language="text/javascript">
$(function() {
// add a keypress handler
$("#someid").keypress(function(e){
alert('you just pressed ' + e.which);
});
// imitate the keypress
$("#someid").keypress();
});
</script>