What I want is to simulate typing in <input> field using javascript.
I have the following code:
var press = jQuery.Event("keydown");
press.ctrlKey = false;
press.which = 65;
$("#test").trigger(press);
But when I load the page, the #test input field has no typed characters, the keycode of '65' represents 'A', but there is no 'A' input.
Basically what I want is to automatically typing in the website using Greasemonkey.
Please give me some ideas or some library with which I can use to do this.
Thanks a lot!
You can send key events, and anything listening for them will get them, but they will not change the input, so you will not see the letter A appear, for example. This is mostly a security thing; see "Manually firing events" for a discussion about that.
So, if you want the letter to appear, you must alter the input's value as you send the key event. There is a jQuery plugin for that, see "The $.fn.sendkeys Plugin".
You can see how an <input> reacts with user-applied keys, key events, and that plugin at this jsFiddle.
For reference, this is the key piece of code from that jsFiddle:
$("button").click ( function (zEvent) {
if (zEvent.target.id == "simA_plain") {
console.log ("Send Plain key event");
var keyVal = 65;
$("#eventTarg").trigger ( {
type: 'keypress', keyCode: keyVal, which: keyVal, charCode: keyVal
} );
}
else {
console.log ("Use the Plugin to simulate a keystroke");
$("#eventTarg").sendkeys ("B") ;
}
} );
That plugin should be sufficient if you are just trying to "simulate typing on an <input>". However, depending on what you are really trying to do, you may need to do one or more of the following:
Just set the text to what you want it to be.
Send a keydown event, if the page's javascript triggers off of that.
Likewise, send a change event, etc., if the page's javascript triggers off of that.
Just find and call the page's javascript directly. Use script injection, the location hack, unsafeWindow, and/or #grant none mode to do that.
Something else? State your true objective and link to the target page.
Related
I am new to javascript, and am writing a simple bookmarklet for a webpage that has a text input section. Basically what I need is a way to execute the following-
if ( ! (text_section).onkeydown ) {
do whatever
}
I need to ignore key-events when the user is typing inside an input field but otherwise trigger key-events for the entire page whenever the user presses a key. I do know that onkeydown is an event listener/handler I'm just trying to explain what I need to do more accurately.
Use an id for your text-section, for example "myTextSection". Apply the addEventListener to the whole document. If the target is anything else, than the textfield, do whatever:
document.addEventListener("keydown", (event) => {
if(event.target !== document.getElementById("myTextSection")){
//do whatever;
}
});
Note that this behaviour might be irritating for users, that navigate by keyboard (for example tab and space keys) through your page. So you might want to add another if statement checking whether the event.keyCode is alphanumeric. In this case the keyCode is in the ranges
[47-58] (for 0-9),
[64-91] (for A-Z) or
[96-123](for a-z)
You should add an event listener to the target element:
targetElement.addEventListener('keydown', (e) => {
// do something
});
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
It is also possible to use onkeydown property:
targetElement.onkeydown = (e) => {
// do something
}
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onkeydown
I want to automate the login process on a website.
This website login page has a username <input> field with id="username", and type="email", and a password <input> field with id="pwd", and type="password", and a submit button <input> field with id="login", and type="submit".
This website has some built-in JavaScript that handle the keyboard keydown/keyup/input events, they validate the entered characters in the username input field, so that the entered characters must be of xxx#xxx format before initiating the login request.
In my script, I first tried this using jQuery:
$("#username").val("me#hotmail.com");
$("#pwd").val("ticket");
$("#login")[0].click();
This can correctly populate the username field with "me#hotmail.com", but the problem with this approach is the validation code in the built-in script does not get triggered, thus the login failed.
Then I tried these by simulating entering these characters, "a#h":
$('#username').trigger(jQuery.Event('keydown', {KeyCode: 97}));
$('#username').trigger(jQuery.Event('keyup', {KeyCode: 97}));
$('#username').trigger(jQuery.Event('keydown', {KeyCode: 64}));
$('#username').trigger(jQuery.Event('keyup', {KeyCode: 64}));
$('#username').trigger(jQuery.Event('keydown', {KeyCode: 104}));
$('#username').trigger(jQuery.Event('keyup', {KeyCode: 104}));
I can see that these events get triggered successfully by adding event listeners on this field,
$("#username" ).on( "keydown", function(e) { console.log(' key downed: ' + (e.which || e.KeyCode ) ); });
$("#username" ).on( "keyup", function(e) { console.log(' key upped: ' + (e.which || e.KeyCode ) ); });
I can see the log messages, then I removed the above listeners, because they would overwrite the website built-in event handlers on this input field.
When I ran the above code, I can NOT visually see "a#h" in the input although these events get triggered successfully based on the log messages, and the login still failed.
I was testing this on the Chrome browser, I opened the Chrome debugging tools, and enabled Keyboard/keydown/keyup events breakpoint in the "Event Listener Breakpoints" pane. But when I ran the code, those breakpoints did not break, so the built-in validation code did not execute, thus the login still failed.
My question is this:
How do I code the event triggering logic, so that when those events get triggered, the website built-in event handler could be executed, plus, I can visually see those entered characters in the uesrname input field, just as if the computer has been hacked, and you are watching the hacker entering characters into the input field in real-time.
I searched google and came up with the following from other relevant StackOverflow answers:
https://stackoverflow.com/a/2220234/5076162 by Max Shawabkeh
https://stackoverflow.com/a/17881330/5076162 by Paul S.
I take no credit for their work, only that I merged the two methods with a little bit on ingenuity. So please up vote their work before you accept my answer.
Working jsfiddle example: Test Typed automatically
jQuery.fn.simulateKeyPress = function (character) {
// Internally calls jQuery.event.trigger
// with arguments (Event, data, elem). That last arguments is very important!
jQuery(this).trigger({ type: 'keypress', which: character.charCodeAt(0) });
};
jQuery(document).ready(function ($) {
// Bind event handler
$('textarea').keypress(function (e) {
//alert(String.fromCharCode(e.which));
console.log(String.fromCharCode(e.which));
var initialVal = $(this).text();
var newVal = initialVal.toString() + String.fromCharCode(e.which);
$(this).text(newVal);
console.log("New Value: " + newVal);
//String.fromCharCode(e.which)
});
// Simulate the key press
$('textarea').on('focus', function(e) {
//this could have been done with a for loop or the jQuery $.each() method by utilizing strings and arrays.
$(this).simulateKeyPress('t');
$(this).simulateKeyPress('e');
$(this).simulateKeyPress('s');
$(this).simulateKeyPress('t');
});
$('textarea').focus();
});
There's a .checkValidity() API on HTML5 form fields you can use for this purpose. Fill it in with .val() as you were, and the call the checkValidity method on the raw DOM node to trigger the browser's built-in handling. More info: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms_in_HTML
I tried these at Chrome console:
document.getElementById("i0116").value = "h#hotmail.com"
document.getElementById("i0118").value = "123456"
document.getElementById("i0116").checkValidity();
document.getElementById("idSIButton9").click();
Although, checkValidity() returns true, the keydown/up events handler in the site script are still not triggered, the login still failed, it reports error "Please enter your phone number or your email address in the format someone#example.com".
There has to be a way I can programmatically simulate key presses in the input to trigger the validation script.
The site I'm testing is https://login.live.com, the username input has a default overlay of "Email or phone" text on it.
document.getElementById("i0116").value = "h#hotmail.com" would just overlap "Email or phone" with another layer of text "h#hotmail.com" into the input field.
Open "https://login.live.com/" in Chrome, you will see what I mean.
I have a div that operates as a button. Once the button is clicked, I want it to simulate the pressing of a key. Elsewhere on Stackoverflow, people have suggested using jQuery.Event("keydown"); but the suggestions all use a .trigger() bound to the button as opposed to .click. So, my example code looks like this:
var press = jQuery.Event("keydown");
press.which = 69; // # The 'e' key code value
press.keyCode = 69;
$('#btn').click( function() {
$('#testInput').focus();
$(this).trigger(press);
console.info(press);
});
I've set up a dummy example at JSFiddle:
http://jsfiddle.net/ruzel/WsAbS/
Eventually, rather than have the keypress fill in a form element, I just want to register the event as a keypress to the document so that a MelonJS game can have it.
UPDATE: It looks like triggering a keypress with anything other than the keyboard is likely to be ignored by the browser for security reasons. For updating a text input, this very nice Jquery plugin will do the trick: http://bililite.com/blog/2011/01/23/improved-sendkeys/
As for anyone who comes here looking for the solution in the MelonJS case, it's best to use MelonJS's me.input object, like so:
$('#btn').mousedown(function() {
me.input.triggerKeyEvent(me.input.KEY.E, true);
});
$('#btn').mouseup(function() {
me.input.triggerKeyEvent(me.input.KEY.E, false);
});
I'm not sure why, but even though this is triggering the event correctly, it doesn't fill the input with the character.
I've modified the code to show that the document is indeed receiving keypress events when we say $(document).trigger(p)
Try it out:
http://jsfiddle.net/WsAbS/3/
var press = jQuery.Event("keydown");
press.which = 69; // # Some key code value
press.keyCode = 69;
press.target = $('#testInput');
$(document).on('keydown', function(event) {
alert(event.keyCode);
});
$('#btn').click( function() {
$(document).trigger(press);
});
I believe this should be good enough for your end goal of a MelonJS game picking up keypresses.
If you want a virtual keyboard (As the title suggests) you can use this one.
This seems like a simple thing but google hasn't turned up anything for me:
How can I bind to a text / value change event only, excluding an input gaining focus? Ie, given the following:
$(function(){
$('input#target').on('keyup', function(){
alert('Typed something in the input.');
});
});
...the alert would be triggered when the user tabs in and out of an element, whether they actually input text or not. How can you allow a user to keyboard navigate through the form without triggering the event unless they input/change the text in the text field?
Note: I'm showing a simplified version of a script, the reason for not using the change event is that in my real code I have a delay timer so that the event happens after the user stops typing for a second, without them having to change focus to trigger the event.
Store the value, and on any key event check if it's changed, like so:
$(function(){
$('input#target').on('keyup', function(){
if ($(this).data('val')!=this.value) {
alert('Typed something in the input.');
}
$(this).data('val', this.value);
});
});
FIDDLE
Simply use the .change event.
Update: If you want live change notifications then do you have to go through the keyup event, which means that you need to program your handler to ignore those keys that will not result in the value being modified.
You can implement this with a whitelist of key codes that are ignored, but it could get ugly: pressing Del results in the value being changed, unless the cursor is positioned at the end of the input in which case it does not, unless there happens to be a selected range in the input in which case it does.
Another way which I personally find more sane if not as "pure" is to program your handler to remember the old value of the element and only react if it has changed.
$(function() {
// for each input element we are interested in
$("input").each(function () {
// set a property on the element to remember the old value,
// which is initially unknown
this.oldValue = null;
}).focus(function() {
// this condition is true just once, at the time we
// initialize oldValue to start tracking changes
if (this.oldValue === null) {
this.oldValue = this.value;
}
}).keyup(function() {
// if no change, nothing to do
if (this.oldValue == this.value) {
return;
}
// update the cached old value and do your stuff
this.oldValue = this.value;
alert("value changed on " + this.className);
});
});
If you do not want to set properties directly on the DOM element (really, there's nothing wrong with it) then you could substitute $(this).data("oldValue") for this.oldValue whenever it appears. This will technically have the drawback of making the code slower, but I don't believe anyone will notice.
See it in action.
This will do it, set a custom attribute and check against that:
$('input').focus(function(){
$(this).attr('originalvalue',$(this).val());
});
$('input').on('keyup',function(){
if($(this).val()===$(this).attr('originalvalue')) return;
alert('he must\'ve typed something.');
});
Be wary of events firing multiple times.
Here is another version that plainly tests if the input field is empty.
If the input is empty then the action is not performed.
$(function(){
$(selector).on('keyup', function(){
if ($(this).val()!='') {
alert('char was entered');
}
})
});
I need to have an input textbox in which I can click and the cursor starts blinking but the user cannot change any text inside it.
I tried using "readonly" or "disabled" attributes, but they do not allow the cursor to be inside the textbox. So, I was thinking of a solution to implement in JavaScript on a normal textbox. Is there a plugin that already do this? How do I implement this?
EDIT: Thanks for all the answers, but I wanted to make the textarea/input type text as uneditable but selectable at the same time. Pressing Ctrl + A inside the textbox doesn't work. Is it possible to get the changed value and the old value and compare them and then return false if the values are different, but in all other cases return true so that the Ctrl + A, Shift + end, etc. combinations work?
Something like this:
<textarea onkeydown="javascript:return false;"></textarea>
would do the trick. (jsfiddle)
You can also do that at runtime if you want to:
<textarea class="readonly"></textarea>
with
$(".readonly").keydown(function() false);
The onkeydown callback captures keystroke events and cancels them using return false;.
Depending on what you are trying to do, you may want to prevent other kind of events, since it is still possible to change the contents with the mouse, for instance.
Your callback function can accept or cancel events depending of the kind of keystroke. For example, to enable only ctrl-a and ctrl-c (with jQuery):
function keydown(e) {
if(!e.ctrlKey) return false; // Cancel non ctrl-modified keystrokes
if(e.keyCode == 65) return true;// 65 = 'a'
if(e.keyCode == 67) return true;// 67 = 'c'
return false;
}
$(function(){
$("inputSelector").keydown(function(){ return false; });
});
You cannot rely on disabling a <textarea> as a user input, as it's trivial to remove any sort of HTML or javascript disabling with firebug, or other tools. Remember that forms aren't limited to the fields you give them, anyone can submit any data to a page.
Disabled inputs are not submitted with a form anyway, bearing that in mind my advice would be to not use a textarea and just print it out.