This post is obsolete. Please see the updated post.

The phone pad below is messed up in Internet Explorer. I know. I don't care anymore. The plugin, however, works.


	$('div.test input:button').click(function(){
		$('.output').sendkeys($('div.test input:text').val());
	});
	$('.phonepad input').click(function(){
		$('.output').sendkeys(this.name || this.value);
	});
	$('.output:first').bind('keypress', function(evt){
		$('#keypress').text($('#keypress').text()+' '+evt.which);
	}).bind('sendkeys', function(evt){
		$('#sendkeys').text($('#sendkeys').text()+' '+evt.which);
	});

<div>
<textarea class="output"></textarea>
<br/>
<input type="text" class="output" />
<div class="phonepad"><input type="button" name="{leftarrow}" value="&larr;"/><input type="button" name="{rightarrow}" value="&rarr;"/><input type="button" name="{backspace}" value="BS"/><input type="button" value="7" /><input type="button" value="8" /><input type="button" value="9" /><input type="button" value="4" /><input type="button" value="5" /><input type="button" value="6" /><input type="button" value="1" /><input type="button" value="2" /><input type="button" value="3" /><input type="button" value="*" /><input type="button" value="0" /><input type="button" value="#" /></div>
<div class="test"><input type="text" /><input type="button" value="test"/></div>
<div id="keypress">keypress event.which:</div>
<div id="sendkeys">sendkeys event.which:</div>
</div>

The $.fn.sendkeys Plugin

I wanted to make a general-purpose onscreen keypad, and wasted a huge amount of time trying to find a way to simulate a keypress. $(element).trigger("keypress",...) won't work. Neither will keyup or keydown. For security reasons, I guess, you can't tell an element to pretend a key was pressed. The browser is too worried that you will access menus or something.

So I wrote my own plugin and named it after Microsoft's sendkeys which does similar things. For any element elem that is a <textarea> or <input type="text">, $(elem).sendkeys(string) inserts string at the insertion point or selection. It's the insertion point sensitivity that makes it more sophisticated than elem.value += string.

Downloads

Download $.fn.sendkeys.

You can use it on more than one element at a time, like any plugin, but it looks funny, since the insertion point only blinks on the last element (see the example above).

Internet Explorer (of course!) causes a bit of trouble, since input elements do not retain the location of the insertion point when focus returns to them. I have to store the insertion point in $.data(elem, 'sendkeys.selection'), which works, but on first use it always appends to the string rather than inserting.

In the example above, the "test" button will insert whatever is in the text field into the output on top.

It might work on other elements, but there are no guarantees.

Special keys

Some special keys are defined, namely {backspace} to delete backwards, {del} to delete forwards, and {rightarrow} and {leftarrow} to move the insertion point. {selectall} selects the entire field. {{} inserts a { by itself. So $(elem).sendkeys('1234') inserts 1234, $(elem).sendkeys('123{backspace}4') inserts 124, and $(elem).sendkeys('1234{leftarrow}{leftarrow}{leftarrow}{del}') inserts 134.

I used Microsoft's key-escaping notation rather than backslashes because putting backslashes in strings means escaping them, and I always get lost in the forest of slashes. Unlike the Microsoft function, this does not use metacharacters (+^%~).

Options

There are no options to the plugin call itself, but the $.fn.sendkeys.defaults object contains the functions to deal with special keys. It defaults to:


$.fn.sendkeys.defaults = {
	'{backspace}': backspace,
	'{rightarrow}': rightarrow,
	'{leftarrow}': leftarrow,
	'{del}': del,
	'{{}': function() {simplechar.call(this, '{')},
	'simplechar': simplechar // the default function
};

where the backspace, rightarrow, leftarrow and del functions are browser-specific. You can create synonyms easily, like $.fn.sendkeys.defaults['{BS}'] = $.fn.sendkeys.defaults['{backspace}']. $.fn.sendkeys.defaults.simplechar is the workhorse insertion function. You can define your own special key functions as function(<string>), where the argument is the name of the special key and this is bound to the element.

Thus, $.fn.sendkeys.defaults['{alert}'] = function(s) {alert(this.value}}.

The plugin also pulls custom special keys from the jQuery cache with the key 'sendkeys', so


$.data(elem, 'sendkeys', {
	'{alert}' : function(s) {alert(this.value}}
});

will use that function on that element only.

Events

To help simulate an actual keypress, the plugin does a trigger('keypress') with the event keyCode, charCode and which all set to the ascii value of the letter sent. This is only triggered with simplechar; special characters do not trigger that event.

In addition, trigger('sendkeys') (a custom event) is executed, with event.which set to the original string that was sent.

12 Comments

  1. Ryan Boylett says:

    What about keys like CTRL, SHIFT and ALT?

  2. Danny says:

    @Ryan Boylett:
    This plugin just inserts text into input elements; it does not actually make the browser think that a given key has been pressed. I searched long and hard for a way to do that, but it looks like that is too much of a security risk. So it’s not the same as the Windows SendKeys. If you find a way to make that work, please let me know!
    –Danny

  3. Cristian Cortez says:

    Hey this is excellent, we can automate more things, like clicks, drag n drop and so on, this will be a testing framework…congratulations! this is good job! you rocks!

  4. Danny says:

    @Cristian Cortez:
    I hadn’t though of using this as a testing framework. Remember, it doesn’t actually simulate keypresses, it just inserts the letters into text boxes. I’d like to see what you do with this; please keep me updated!
    –Danny

  5. Jesse says:

    Sorry bother you with this, but I’m not very good with Ajax and jQuery.
    I’m doing this:
    $(‘#id’).sendkeys(‘1234’)

    but it is not working. Whrere did I go wrong?

    Thanks!

  6. Danny says:

    @Jesse:
    That’s the right way to do it. Can you post a page with your code to look at?
    –Danny

  7. Jesse says:

    @Danny
    When I use the .sendkeys function I get the following JavaScript error
    Uncaught exception: ReferenceError: Undefined variable: bililiteRange

    I uploaded here http://rockandscream.t35.com/test.php
    the html source is very messed up but I think it is readable.

    thanks again

  8. Danny says:

    @Jesse:
    At the top of this post is the note that it is obsolete; see the updated post that notes that it now depends on my text range code. So in addition to jquery.sendkeys.js you have to include bililiteRange.js.
    –Danny

  9. Jesse says:

    Yeah, I think missed the note.
    Anyway, it works perfect now.
    Great work! This plugin is just what I needed.

  10. vimal kumar says:

    It is very useful plugin.
    We need further sendkey functionalities :
    1) ctrl 2) F1 to F12 3)Alt 4) Shift

  11. Danny says:

    @Vimal Kumar:
    Unfortunately, you’re asking more of this plugin than it promises. It allows you to insert characters into a text box or editable div; it does not simulate a keypress in the browser. That is forbidden by the browser security. In other words, you can insert a control character with $('.output').sendkeys(String.fromCharCode(22)); but that will insert an actual ctrl-V, not do any pasting.
    –Danny

  12. Simulate JavaScript Key Events | ASK AND ANSWER says:

    […] You could even push this further and let it not only simulate the event but actually insert the character (if it is an input element), however there are many cross-browser gotcha’s when trying to do that. Better use a more elaborate plugin like SendKeys. […]

Leave a Reply


Warning: Undefined variable $user_ID in /home/public/blog/wp-content/themes/evanescence/comments.php on line 75