I want to dispatch user actions on a text input field. I want it to be as if an actual person has used their keyboard to click a text input field, hit the spacebar, and then hit the backspace key. With the code I used nothing has happened.
THE JSFIDDLE https://jsfiddle.net/zvrhfq9j/
THE HTML
<input type="text" name="psychTree-savedNodes" style="width:20%" />
THE JS
$('input[name="psychTree-savedNodes"]').focus();
$('input[name="psychTree-savedNodes"]').trigger({type: 'keypress', which: 32, keyCode: 32});
$('input[name="psychTree-savedNodes"]').trigger({type: 'keyup', which: 32, keyCode: 32});
$('input[name="psychTree-savedNodes"]').trigger({type: 'keydown', which: 32, keyCode: 32});
$('input[name="psychTree-savedNodes"]').trigger({type: 'keypress', which: 8, keyCode: 8});
$('input[name="psychTree-savedNodes"]').trigger({type: 'keyup', which: 8, keyCode: 8});
$('input[name="psychTree-savedNodes"]').trigger({type: 'keydown', which: 8, keyCode: 8});
THE SOLUTION: was to actually dispatch the events. Thanks for those that actually answered!
You can simulate user actions, but they won't perform the default functions because it will set isTrusted to false (for security reasons).
For instance, you can build an event to dispatch to a text field that "types the letter 'a'". It will (err, should) trigger any custom functions bound to that event handler (el.onkeydown(e){ if( e.key == 'a' ) …), but it will not type the letter a into the text field, or otherwise process default browser functionality based on that keystroke.
It's a browser implementation, and not something you can get around. So while you can't "type" directly into fields, you can run events based off the event handlers that are attached to those specific events.
I've whipped up a codepen example to show what I mean: https://codepen.io/xhynk/pen/jOPbWzz
The page loads blue, with 2 fields
In 1 second, it will run a function that "simulates" a "click > space > backspace" chain of events.
The events will display what they did inside the "no" input
The page turns green to show it went off.
If you're so inclined, you can change the event codes to letters to see that the actual keystrokes never appear in the "yes" input. I've added the "no" box that has keydown and onclick event handlers to show what events fired and in what order by changing the value of it.
You can also manually click on the "yes" input, then hit "space" and "backspace" and see they too fire the event handler functions (the event functions will run like they did when they were simulated) but this time they will actually show up in the box (because you actually did them, so they are trusted events).
Long story short, you can't fully simulate "typing" keypress events that are trusted, but you can handle those specific keypress events however you want (even changing the value of the current input if you so choose).
Edit: I see a chain of comments has spawned up at the top. This is a browser function that you can't get around, unless you find (or build) a browser that handles untrusted isTrusted:false events. This doesn't have anything to do with local or sandbox programming environments.
Related
I want to write using javascript in an HTML input element using keyboard events.
In the HTML I have:
<body>
<form>
<input type="text" name="myname" value='XX--'>
</form>
</body>
I'm in a test phase so in the console i write:
let evt = new KeyboardEvent('keydown',
{code: 'Space', key: ' ', keyCode: 32, which: 32, bubbles: true, view: window});
and then:
document.activeElement.dispatchEvent(evt);
Of course, first I click inside the text of the control to focus there.
The event seems to arrive at control but the character (space) is not written. I have even tried to use both keydown and keyup events in succession to no avail.
The thing is that I don't want to add event listeners. The real target is a text editor (Monaco editor) and I will not modify it. I need to write in the editor and I also want the event to go through its onKeyDown event handler. That's why I want to simulate a keyboard as realistic as possible.
I use currently Chrome but would be nice to have something that works for other browsers as well (Firefox, IE, etc).
I’ve built a Chrome extension (https://chrome.google.com/webstore/detail/omnibear/cjieakdeocmiimmphkfhdfbihhncoocn). It adds an item to the context menu, so the user can right-click an element on the page and reply to the associated “entry” on their blog.
My problem is, whether or not I can find an “entry” depends on where they click, and involves traversing up the DOM tree. I have the code in place that highlights the entry when the contextmenu event is fired, but this is too late to update the text in the context menu. Is there a way to update the context menu text dynamically as it is opened?
(e.g., I would like it to say “Reply to page” if no entry is found, or “Reply to tweet” if a tweet is found)
No, in a Chrome extension/Firefox WebExtension, there is no way to have your JavaScript make dynamic changes to the context menu at the time the context menu opens. The only thing that dynamically changes at the time the context menu opens is: if you have added a context menu item that has the selection context for its ContextType, then you can specify %s in the title, which will be replaced with the current selection.
Change the context menu before it begins to open
Mouse events
To do what you desire, you need to make the changes to the context menu prior to the beginning of the context menu being opened. This can be accomplished by having a content script that listens to the mouseup event. You may have to end up using the mousedown event, or one or more of the mouseenter/mouseleave/mouseover/mouseout events. If you do need to use mousedown, once that event fires you should then start listening to some of the mouseenter/mouseleave/mouseover/mouseout events to tell when the element the mouse is over changes, or just assume the user releases the button on the same element on which they pressed it down.
If the mouseup/mousedown event is for button=2, then you will need to message your background script to change the context menu with contextMenus.update(). There are multiple asynchronous portions of this process. This may make for various race conditions, and may necessitate using events which give you earlier notification than mouseup (e.g. mousedown, mouseenter/mouseleave/mouseover/mouseout).
What events you need to watch for may be operating system/platform/windowing system dependent. You will need to test to determine what is needed in each environment you plan to support.
Keyboard events
The context menu can also be opened using a few keyboard sequences. You will need to listen for and perform the same messaging as is needed for mouse events. You will need to determine what these events are in all operating systems/platforms/windowing systems which you are supporting.
Linux
On Linux it appears to vary at least based on platform.
OSX
On OSX, it appears that a keyboard shortcut is only available if enabled.
Windows
On Windows, the keyboard shortcuts to open the context menu are:
Context Menu key
You will need to detect the following event sequence:
keydown { target: <body>, key: "ContextMenu", charCode: 0, keyCode: 93 }
keypress { target: <body>, key: "ContextMenu", charCode: 0, keyCode: 93 }
keyup { target: <body>, key: "ContextMenu", charCode: 0, keyCode: 93 }
The context menu does not open until around the same time the keyup event fires. I did not test to see if the keyup happens early enough for you to make changes to the context menu prior to it opening.
Keyboard combination: Shift-F10
You will need to detect the following event sequence:
keydown Shift { target: <body>, key: "Shift", charCode: 0, keyCode: 16, shiftKey: true }
keydown Shift { target: <body>, key: "F10", charCode: 0, keyCode: 121, shiftKey: true }
keypress Shift { target: <body>, key: "F10", charCode: 0, keyCode: 121, shiftKey: true }
In this case, the context menu opens at around the same time as the shifted F10 keydown/keypress events fire. No keyup event fires for this keyboard sequence.
Note this question. I see that there are other approaches besides just triggering the tab keypress event, but I'd still like to know why triggering the tab key press event doesn't move focus to the next input field.
Code Pen
HTML
<textarea></textarea>
<textarea></textarea>
<textarea></textarea>
JS
$('textarea').on('keydown', function(e) {
if (e.metaKey && e.which === 40) {
console.log('test');
$(this).trigger({
type: 'keypress',
which: 9
});
}
});
Because the tab event is a native browser event/action for changing focus. The .trigger() function only triggers the event handlers that are assigned to it. Note there is more information given from jQuery's site:
The .trigger() function cannot be used to mimic native browser events, such as clicking on a file input box or an anchor tag. This is because, there is no event handler attached using jQuery's event system that corresponds to these events.
There is a plug-in for this though called jquery-simulate to handle this. That being said the tab key changing focus is actually a default action in the web browser. Firing a browsers native event does not mean it will do it's default action, as the documentation for KeyboardEvents mentions:
Note that manually firing an event does not generate the default action associated with that event. For example, manually firing a key event does not cause that letter to appear in a focused text input. In the case of UI events, this is important for security reasons, as it prevents scripts from simulating user actions that interact with the browser itself.
On a JavaScript page, I pop up an alert if the user hits the enter key by using
if(evt.keyCode == 13){
alert("Return Key Pressed");
}
but the event does not fire when I hit the return key on the iPad. How do I catch the event?
The iPad keyboard does fire the keypress event with a key code of 13 if you press return. This sounds like you've got something else going awry
Here's a quick jsfiddle to verify with: http://jsfiddle.net/359wG/
According to https://api.jquery.com/keypress/
The keypress event is sent to an element when the browser registers
keyboard input. This is similar to the keydown event, except that
modifier and non-printing keys such as Shift, Esc, and delete trigger
keydown events but not keypress events. Other differences between the
two events may arise depending on platform and browser.
A keypress event handler can be attached to any element, but the event
is only sent to the element that has the focus. Focusable elements can
vary between browsers, but form controls can always get focus so are
reasonable candidates for this event type.
I moved my return-key listener to an anchor tag, which on IPad is treated as a 'focusable element' similar to form controls.
as we know there is a lot of events will be triggered when we typing.
such as keyup, keydown, keypress or something else.
Is there any other event will be triggered only when the content in the text field is changed? and if there is not,how to write some javasrcipt code to accomplish this feature
The change event might help?
I've created a simple fiddle to determine what happens when a text node in a contenteditable element is modified by a key press. As I was doing that, I decided to check what happens when using ibus because I use ibus for my own work. I determined that when ibus is used, the only keyboard event generated is a keyup event with a which value which is useless.
Here is the fiddle I created:
http://jsfiddle.net/lddubeau/jWnL3/
Go to that fiddle.
Turn on your Javascript console.
Click run.
Click between the 2dn and third character of the word "toto".
Type something using ibus. For instance, type 我.
The output varies depending on your browser. On Chrome 29 each keystroke is recorded so if I type 我 using the tonepy method I get keyup and keydown for each of the "w" "o" "3" and "1". (The pinyin, the tone and then hitting 1 to select the first choice.) The final event is:
event type: keyup
which: 229
keyCode: 229
charCode: 0
node value:
to我to
The events before this one all have the same values except that some are of the "keydown" type and of course the node value shows "toto" until the last event.
On Firefox 23 only one event is registered:
"event type:" "keyup"
"which:" 49
"keyCode:" 49
"charCode:" 0
"node value:" "
to我to
"
No keydown or keypress events are generated. (When typing characters within the ascii range, you get keydown, keypress and keyup for each key.)
The values of which and keyCode do not seem to correspond to anything sensible. I've examined the event object passed to the event handler and did not see any field which would indicate that the user just typed 我.