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).
Related
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.
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.
Im sending keys to a input filter using sendkeys and supposed to be it will update the contents of the table, I check its screenshot and it placed the characters on the field. unfortunately after sendkeys, it doesnt trigger either keyup/keydown.
How to trigger keyup or keydown on casper?
Code:
this.sendKeys('input[name=\"filterString\"]', 'string');
casper.sendKeys() should have triggered the keyup and keydown events, because it uses native browser events which should be indistinguishable from user input in other browsers.
You trigger it yourself by keeping focus and then triggering those events:
this.sendKeys('input[name=\"filterString\"]', 'string', {keepFocus: true});
this.page.sendEvent("keydown");
this.page.sendEvent("keyup");
this.page.sendEvent("keypress");
For this you can use the underlying PhantomJS function page.sendEvent().
Context
I have a backbone app with an event listener for focus events on a textarea. Backbone uses jQuery events, so core of my question centers around jQuery focus events.
Question
Is there a way to tell how an element came into focus, be it by click or tab?
The behavior of how the cursor gets positioned needs to be handled differently between these two cases, however there doesn't seem to be a way to distinguish between the two offhand.
I could listen to click events, however will still need to listen to focus to capture tabbing - this will overlap with click event as it will also focus the textarea resulting in double events.
I may to rethink this entirely.
JSBin Example
$('textarea')
.focus(function(event){
console.log('You focused me by' + event.type);
// Here I wish I know if the focus came from a 'click' or 'tab' events
});
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<form>
<input placeholder="focus me, then tab" type="text"><br>
<textarea>Focus me via click. Now try via tabbing.</textarea>
</form>
</body>
</html>
.onfocus() listener can get called in a number of ways which makes it a tricky even to bind to.
Click on element
Tab or Shift-Tab to element
jQuery programatic focus $( "#target" ).focus();
Switching between programs, and refocusing the internet browser
There is no unique identifier in the onfocus event to determine how it came into focus.
From what I found it is best to be more explicit and listen to click() and onkeyup() events to handle unique behaviors between them and avoid unexpected function calls (like the browser is refocused).
onkeyup() is great for capturing tab events as the tab key will be released 'up' when tabbing in, but not when tabbing out.
JSBin
$('textarea')
.click(focusedBy)
.keyup(checkTab);
function checkTab(event){
if (event.keyCode === 9) {
focusedBy(event);
}
}
function focusedBy (event){
console.log('You focused me by ' + event.type);
}
you will need a combo of focus, click and blur events to determine the origin of "getting focus". click->set value, focus -> check if that clickvalue was set -> do what you must -> reset on blur. you might also want to be looking out for ontouchdown
You could set a clicked variable on mousedown.
You'll need to blur the textarea on mousedown so that focus will will be triggered on mouseup:
var clicked= false;
$('textarea')
.focus(function(event) {
if(clicked) {
$('#status').html('clicked');
clicked= false;
}
else {
$('#status').html('tabbed');
}
})
.mousedown(function(event) {
clicked= true;
$(this).blur();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input placeholder="focus me, then tab" type="text"><br>
<textarea>Focus me via click. Now try via tabbing.</textarea>
</form>
<div id="status"></div>
here's a scaling way to do it without rerouting events or simulating extra actions:
var targ=$('textarea');
targ.focus(function(event){
console.log('You focused me by ' + targ.eventType);
// Here I wish I know if the focus came from a 'click' or 'tab' events
});
$("body").mousedown(function(e){
targ.eventType="mouse";
}).keydown(function(e){
targ.eventType="keyboard";
});
this uses the jQuery collection to store the last event type, which is set by document-wide handlers.
if you need to re-use this functionality on other input types, just add more selectors to targ and differentiate in the handler using event.target.
http://jsbin.com/ruqekequva/2/edit
I'm giving a value to a textbox and then giving focus to it.
document.getElementById('textbox').value="abcd";
document.getElementById('textbox').focus();
Then, I am creating a keyboard event and trying to fire the CTRL+A key combination (trying to select the text inside the textbox) by writing the following code:
var myEvent = document.createEvent('KeyboardEvent');
myEvent.initKeyEvent("keypress", true, true, window, true, false, false, false, 0, 97);
document.getElementById('textbox').dispatchEvent(myEvent);
But the above code doesn't select the text inside the textbox.
How to select the text creating the keyboard event ?
You can't trigger browser keypress behavior with JavaScript simulated keypresses. You can only trigger your own function. What that means if that if you add a keypress event listener that checks if the a key is pressed and then does something, you can trigger that behavior, but you can't for example make the browser pull up it's "find" bar when you trigger ctrl+F. That would be a security issue.
The appropriate way would be to write your own function for selecting and fire it whenever you need it.
This should do what you're looking for: Live demo (click).
<input type="text" id="my-input" value="Some text.">
JavaScript:
var myInput = document.getElementById('my-input');
myInput.addEventListener('click', function() {
this.focus();
this.select();
});
var event = new Event('click');
myInput.dispatchEvent(event);