How can I generate a keypress event in Safari with

2019-02-10 09:14发布

问题:

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.

回答1:

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



回答2:

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



回答3:

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.



回答4:

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>