{"id":114,"date":"2008-08-20T23:17:44","date_gmt":"2008-08-21T05:17:44","guid":{"rendered":"http:\/\/bililite.nfshost.com\/blog\/?p=114"},"modified":"2011-11-02T12:10:31","modified_gmt":"2011-11-02T18:10:31","slug":"the-fnsendkeys-plugin","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2008\/08\/20\/the-fnsendkeys-plugin\/","title":{"rendered":"The <code>$.fn.sendkeys<\/code> Plugin"},"content":{"rendered":"<p><strong>This post is obsolete. Please see the <a href=\"\/blog\/2011\/01\/23\/improved-sendkeys\/\">updated post<\/a>.<\/strong><\/p>\r\n<p>The phone pad below is messed up in Internet Explorer. <a href=\"http:\/\/youngisrael-stl.org\/images\/webdesign.png\">I know<\/a>. I don't care anymore. The plugin, however, works.<\/p>\r\n<script src=\"\/inc\/jquery.sendkeys.js\" type=\"text\/javascript\"><\/script>\r\n<script src=\"\/inc\/bililiteRange.js\" type=\"text\/javascript\"><\/script>\r\n<script type=\"text\/javascript\">\r\n$(function(){\r\n             $('.output, .test').css({\r\n                fontSize: '100%',\r\n                width: '12em',\r\n                padding: '0.5em'\r\n             });\r\n\t$('.phonepad ').css({\r\n\t\twidth: '13.5em',\r\n\t\tborder: '1px solid gray',\r\n\t\tpadding: '0px'\r\n\t});\r\n\t$('.phonepad input').css({\r\n\t\twidth: '3em',\r\n\t\theight: '2em',\r\n\t\tmargin: '.5em'\r\n\t});\r\n\t$('div.test').css({\r\n\t\tborder: '1px solid gray'\r\n\t});\r\n});\r\n<\/script>\r\n<pre><code class=\"language-javascript demo\">\r\n\t$('div.test input:button').click(function(){\r\n\t\t$('.output').sendkeys($('div.test input:text').val());\r\n\t});\r\n\t$('.phonepad input').click(function(){\r\n\t\t$('.output').sendkeys(this.name || this.value);\r\n\t});\r\n\t$('.output:first').bind('keypress', function(evt){\r\n\t\t$('#keypress').text($('#keypress').text()+' '+evt.which);\r\n\t}).bind('sendkeys', function(evt){\r\n\t\t$('#sendkeys').text($('#sendkeys').text()+' '+evt.which);\r\n\t});\r\n<\/code><\/pre>\r\n<pre><code class=\"language-html demo\">\r\n&lt;div&gt;\r\n&lt;textarea class=&quot;output&quot;&gt;&lt;\/textarea&gt;\r\n&lt;br\/&gt;\r\n&lt;input type=&quot;text&quot; class=&quot;output&quot; \/&gt;\r\n&lt;div class=&quot;phonepad&quot;&gt;&lt;input type=&quot;button&quot; name=&quot;{leftarrow}&quot; value=&quot;&amp;larr;&quot;\/&gt;&lt;input type=&quot;button&quot; name=&quot;{rightarrow}&quot; value=&quot;&amp;rarr;&quot;\/&gt;&lt;input type=&quot;button&quot; name=&quot;{backspace}&quot; value=&quot;BS&quot;\/&gt;&lt;input type=&quot;button&quot; value=&quot;7&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;8&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;9&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;4&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;5&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;6&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;1&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;2&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;3&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;*&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;0&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;#&quot; \/&gt;&lt;\/div&gt;\r\n&lt;div class=&quot;test&quot;&gt;&lt;input type=&quot;text&quot; \/&gt;&lt;input type=&quot;button&quot; value=&quot;test&quot;\/&gt;&lt;\/div&gt;\r\n&lt;div id=\"keypress\"&gt;keypress event.which:&lt;\/div&gt;\r\n&lt;div id=\"sendkeys\"&gt;sendkeys event.which:&lt;\/div&gt;\r\n&lt;\/div&gt;\r\n<\/code><\/pre>\r\n<h4 style=\"clear:both\">The <code>$.fn.sendkeys<\/code> Plugin<\/h4>\r\n<p>I wanted to make a general-purpose onscreen keypad, and wasted a huge amount of time trying to find a way to\r\nsimulate a keypress. \r\n<code class=\"language-javascript\">$(element).trigger(\"keypress\",...)<\/code> won't work. Neither will keyup or keydown.\r\nFor security reasons, I guess, you can't tell an element to pretend a key was pressed. The browser is too\r\nworried that you will access menus or something.<\/p>\r\n<p>So I wrote my own plugin and named it after Microsoft's <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/8c6yea83(VS.85).aspx\">sendkeys<\/a> \r\nwhich does similar things. For any element <code>elem<\/code> that\r\nis a <code class=\"language-html\">&lt;textarea&gt;<\/code> or <code class=\"language-html\">&lt;input type=&quot;text&quot;&gt;<\/code>, \r\n<code class=\"language-javascript\">$(elem).sendkeys(string)<\/code> inserts <code>string<\/code> at the insertion point or selection. \r\nIt's the insertion point sensitivity\r\nthat makes it more sophisticated than <code>elem.value += string<\/code>.<\/p>\r\n<h4>Downloads<\/h4>\r\n<p>Download <a href=\"\/inc\/jquery.sendkeys.js\">$.fn.sendkeys<\/a>.<\/p>\r\n<!--more-->\r\n<p>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\r\nthe example above).<\/p>\r\n<p>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\r\nthem. I have to store the insertion point in $.data(elem, 'sendkeys.selection'), which works, but on first use it always appends to the string\r\nrather than inserting.<\/p>\r\n<p>In the example above, the \"test\" button will insert whatever is in the text field into the output on top.<\/p>\r\n<p>It might work on other elements, but there are no guarantees.<\/p>\r\n<h4>Special keys<\/h4>\r\n<p>Some special keys are defined, namely <code>{backspace}<\/code> to delete backwards, <code>{del}<\/code> to delete forwards, \r\nand <code>{rightarrow}<\/code> and <code>{leftarrow}<\/code> to move the insertion point. <code>{selectall}<\/code> selects the entire field.\r\n<code>{{}<\/code> inserts a <code>{<\/code> by itself.\r\nSo \r\n<code class=\"language-javascript\">$(elem).sendkeys('1234')<\/code> inserts <code>1234<\/code>,\r\n<code class=\"language-javascript\">$(elem).sendkeys('123{backspace}4')<\/code> inserts <code>124<\/code>, and\r\n<code class=\"language-javascript\">$(elem).sendkeys('1234{leftarrow}{leftarrow}{leftarrow}{del}')<\/code> inserts <code>134<\/code>.\r\n<\/p>\r\n<p>I used Microsoft's key-escaping notation rather than backslashes because putting backslashes in strings means escaping <em>them<\/em>, and I\r\nalways get lost in the forest of slashes. Unlike the Microsoft function, this does not use metacharacters (+^%~).<\/p>\r\n<h4>Options<\/h4>\r\n<p>There are no options to the plugin call itself, but the <code>$.fn.sendkeys.defaults<\/code> object contains the functions to deal with special keys.\r\nIt defaults to:<\/p>\r\n<pre><code class=\"language-javascript\">\r\n$.fn.sendkeys.defaults = {\r\n\t'{backspace}': backspace,\r\n\t'{rightarrow}': rightarrow,\r\n\t'{leftarrow}': leftarrow,\r\n\t'{del}': del,\r\n\t'{{}': function() {simplechar.call(this, '{')},\r\n\t'simplechar': simplechar \/\/ the default function\r\n};\r\n<\/code><\/pre>\r\n<p>where the <code>backspace<\/code>, <code>rightarrow<\/code>, <code>leftarrow<\/code> and <code>del<\/code> functions are browser-specific.\r\nYou can create synonyms easily, like <code class=\"language-javascript\">$.fn.sendkeys.defaults['{BS}'] = $.fn.sendkeys.defaults['{backspace}']<\/code>.\r\n<code class=\"language-javascript\">$.fn.sendkeys.defaults.simplechar<\/code> is the workhorse insertion function. You can define your own special key functions\r\nas <code class=\"language-javascript\">function(&lt;string&gt;)<\/code>, where the argument is the name of the special key and\r\n<code class=\"language-javascript\">this<\/code> is bound to the element.<p>\r\n<p>Thus, <code class=\"language-javascript\">$.fn.sendkeys.defaults['{alert}'] = function(s) {alert(this.value}}<\/code>.<\/p>\r\n<p>The plugin also pulls custom special keys from the jQuery cache with the key 'sendkeys', so<\/p>\r\n<pre><code class=\"language-javascript\">\r\n$.data(elem, 'sendkeys', {\r\n\t'{alert}' : function(s) {alert(this.value}}\r\n});\r\n<\/code><\/pre>\r\n<p>will use that function on that element only.<\/p>\r\n<h4>Events<\/h4>\r\n<p>To help simulate an actual keypress, the plugin does a <code class=\"language-javascript\">trigger('keypress')<\/code> with the <code>event<\/code>\r\n<code>keyCode<\/code>, <code>charCode<\/code> and <code>which<\/code> all set to the ascii value of the letter sent. This is only triggered with <code>simplechar<\/code>; special characters do not trigger that event.<\/p>\r\n<p>In addition, <code>trigger('sendkeys')<\/code> (a custom event) is executed, with <code>event.which<\/code> set to the original string that was sent.<\/p>","protected":false},"excerpt":{"rendered":"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); }); &lt;div&gt; &lt;textarea class=&quot;output&quot;&gt;&lt;\/textarea&gt; &lt;br\/&gt; &lt;input type=&quot;text&quot; [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/114"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=114"}],"version-history":[{"count":34,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/114\/revisions"}],"predecessor-version":[{"id":2076,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/114\/revisions\/2076"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}