Creating a Virtual jQuery Keyboard

For those of us who travel often, we often end up accessing our emails and other confidential web accounts on public computers. In such circumstances, we are completely at the mercy of keyloggers and other malicious software that track our keystrokes and record our passwords.

Yet, very few websites provide their users with the option of using a virtual keyboard to key in (at the bare minimum) their passwords. Yes, a few banks do it, but considering how much personal information we store in various web applications these days, the safety of these accounts are of no less significance to us. This tutorial will explain how we can implement a simple virtual keyboard with some (well, okay, lots of!) help from jQuery.

Before I begin, let me show you how it will all look in the end.

Basic HTML and CSS Setup

Ok, let’s get started. We start off with a plain, old login form with username and password fields and a login button. We add a link which will show/hide the virtual keyboard when clicked.

Note: For the purpose of demonstration, I have actually used a normal text field instead of a password type text field!

<h3>Login form</h3> <form action="" method="post" id="loginform"> <label for="username">Username:</label> <input type="text" name="username" id="username" /> <label for="pwd">Password:</label> <input type="text" name="pwd" id="pwd"/> <a href="#" id="showkeyboard" title="Type in your password using a virtual keyboard.">Keyboard</a> <br /> <input type="submit" name="Submit" id="submit_butt" value="Submit" /> </form> 1 2 3 4 5 6 7 8 9 10 < h3 > Login form < / h3 > < form action = "" method = "post" id = "loginform" > < label for = "username" > Username : < / label > < input type = "text" name = "username" id = "username" / > < label for = "pwd" > Password : < / label > < input type = "text" name = "pwd" id = "pwd" / > < a href = "#" id = "showkeyboard" title = "Type in your password using a virtual keyboard." > Keyboard < / a > < br / > < input type = "submit" name = "Submit" id = "submit_butt" value = "Submit" / > < / form >

Next, it’s time to put in the XHTML for the keyboard in place. I just wanted to take a very simple approach, and thus ruled out generating the keys dynamically. I have just the four main rows of the standard keyboard (each enclosed in a DIV), along with their shift equivalents. So that means, a total of 8 rows, of which at any time (depending on whether the shift key is pressed or not), four of the rows would be visible, and the other four hidden.

<div id="keyboard"> <div id="row0"> <input name="accent" type="button" value="`" /> <input name="1" type="button" value="1" /> <input name="2" type="button" value="2" /> <input name="3" type="button" value="3" /> <input name="4" type="button" value="4" /> <input name="5" type="button" value="5" /> <input name="6" type="button" value="6" /> <input name="7" type="button" value="7" /> <input name="8" type="button" value="8" /> <input name="9" type="button" value="9" /> <input name="0" type="button" value="0" /> <input name=" - " type="button" value=" - " /> <input name="=" type="button" value="=" /> <input name="backspace" type="button" value="Backspace" /> </div> <div id="row0_shift"> <input name="tilde" type="button" value="~" /> <input name="exc" type="button" value="!" /> <input name="at" type="button" value="@" /> <input name="hash" type="button" value="#" /> <input name="dollar" type="button" value="$" /> <input name="percent" type="button" value="%" /> <input name="caret" type="button" value="^" /> <input name="ampersand" type="button" value="&" /> <input name="asterik" type="button" value="*" /> <input name="openbracket" type="button" value="(" /> <input name="closebracket" type="button" value=")" /> <input name="underscore" type="button" value="_" /> <input name="plus" type="button" value="+" /> <input name="backspace" type="button" value="Backspace" /> </div> <div id="row1"> <input name="q" type="button" value="q" /> <input name="w" type="button" value="w" /> <input name="e" type="button" value="e" /> <input name="r" type="button" value="r" /> <input name="t" type="button" value="t" /> <input name="y" type="button" value="y" /> <input name="u" type="button" value="u" /> <input name="i" type="button" value="i" /> <input name="o" type="button" value="o" /> <input name="p" type="button" value="p" /> <input name="[" type="button" value="[" /> <input name="]" type="button" value="]" /> <input name="\" type="button" value="\" /> </div> <div id="row1_shift"> <input name="Q" type="button" value="Q" /> <input name="W" type="button" value="W" /> <input name="E" type="button" value="E" /> <input name="R" type="button" value="R" /> <input name="T" type="button" value="T" /> <input name="Y" type="button" value="Y" /> <input name="U" type="button" value="U" /> <input name="I" type="button" value="I" /> <input name="O" type="button" value="O" /> <input name="P" type="button" value="P" /> <input name="{" type="button" value="{" /> <input name="}" type="button" value="}" /> <input name="|" type="button" value="|" /> </div> <div id="row2"> <input name="a" type="button" value="a" /> <input name="s" type="button" value="s" /> <input name="d" type="button" value="d" /> <input name="f" type="button" value="f" /> <input name="g" type="button" value="g" /> <input name="h" type="button" value="h" /> <input name="j" type="button" value="j" /> <input name="k" type="button" value="k" /> <input name="l" type="button" value="l" /> <input name=";" type="button" value=";" /> <input name="’" type="button" value="’" /> </div> <div id="row2_shift"> <input name="a" type="button" value="A" /> <input name="s" type="button" value="S" /> <input name="d" type="button" value="D" /> <input name="f" type="button" value="F" /> <input name="g" type="button" value="G" /> <input name="h" type="button" value="H" /> <input name="j" type="button" value="J" /> <input name="k" type="button" value="K" /> <input name="l" type="button" value="L" /> <input name=";" type="button" value=":" /> <input name="’" type="button" value=’"’ /> </div> <div id="row3"> <input name="Shift" type="button" value="Shift" id="shift" /> <input name="z" type="button" value="z" /> <input name="x" type="button" value="x" /> <input name="c" type="button" value="c" /> <input name="v" type="button" value="v" /> <input name="b" type="button" value="b" /> <input name="n" type="button" value="n" /> <input name="m" type="button" value="m" /> <input name="," type="button" value="," /> <input name="." type="button" value="." /> <input name="/" type="button" value="/" /> </div> <div id="row3_shift"> <input name="Shift" type="button" value="Shift" id="shifton" /> <input name="Z" type="button" value="Z" /> <input name="X" type="button" value="X" /> <input name="C" type="button" value="C" /> <input name="V" type="button" value="V" /> <input name="B" type="button" value="B" /> <input name="N" type="button" value="N" /> <input name="M" type="button" value="M" /> <input name="lt" type="button" value="<" /> <input name="gt" type="button" value=">" /> <input name="?" type="button" value="?" /> </div> <div id="spacebar"> <input name="spacebar" type="button" value=" " /> </div> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 < div id = "keyboard" > < div id = "row0" > < input name = "accent" type = "button" value = "`" / > < input name = "1" type = "button" value = "1" / > < input name = "2" type = "button" value = "2" / > < input name = "3" type = "button" value = "3" / > < input name = "4" type = "button" value = "4" / > < input name = "5" type = "button" value = "5" / > < input name = "6" type = "button" value = "6" / > < input name = "7" type = "button" value = "7" / > < input name = "8" type = "button" value = "8" / > < input name = "9" type = "button" value = "9" / > < input name = "0" type = "button" value = "0" / > < input name = " - " type = "button" value = " - " / > < input name = "=" type = "button" value = "=" / > < input name = "backspace" type = "button" value = "Backspace" / > < / div > < div id = "row0_shift" > < input name = "tilde" type = "button" value = "~" / > < input name = "exc" type = "button" value = "!" / > < input name = "at" type = "button" value = "@" / > < input name = "hash" type = "button" value = "#" / > < input name = "dollar" type = "button" value = "$" / > < input name = "percent" type = "button" value = "%" / > < input name = "caret" type = "button" value = "^" / > < input name = "ampersand" type = "button" value = "&" / > < input name = "asterik" type = "button" value = "*" / > < input name = "openbracket" type = "button" value = "(" / > < input name = "closebracket" type = "button" value = ")" / > < input name = "underscore" type = "button" value = "_" / > < input name = "plus" type = "button" value = "+" / > < input name = "backspace" type = "button" value = "Backspace" / > < / div > < div id = "row1" > < input name = "q" type = "button" value = "q" / > < input name = "w" type = "button" value = "w" / > < input name = "e" type = "button" value = "e" / > < input name = "r" type = "button" value = "r" / > < input name = "t" type = "button" value = "t" / > < input name = "y" type = "button" value = "y" / > < input name = "u" type = "button" value = "u" / > < input name = "i" type = "button" value = "i" / > < input name = "o" type = "button" value = "o" / > < input name = "p" type = "button" value = "p" / > < input name = "[" type = "button" value = "[" / > < input name = "]" type = "button" value = "]" / > < input name = "\" type=" button " value=" \ " / > < / div > < div id = "row1_shift" > < input name = "Q" type = "button" value = "Q" / > < input name = "W" type = "button" value = "W" / > < input name = "E" type = "button" value = "E" / > < input name = "R" type = "button" value = "R" / > < input name = "T" type = "button" value = "T" / > < input name = "Y" type = "button" value = "Y" / > < input name = "U" type = "button" value = "U" / > < input name = "I" type = "button" value = "I" / > < input name = "O" type = "button" value = "O" / > < input name = "P" type = "button" value = "P" / > < input name = "{" type = "button" value = "{" / > < input name = "}" type = "button" value = "}" / > < input name = "|" type = "button" value = "|" / > < / div > < div id = "row2" > < input name = "a" type = "button" value = "a" / > < input name = "s" type = "button" value = "s" / > < input name = "d" type = "button" value = "d" / > < input name = "f" type = "button" value = "f" / > < input name = "g" type = "button" value = "g" / > < input name = "h" type = "button" value = "h" / > < input name = "j" type = "button" value = "j" / > < input name = "k" type = "button" value = "k" / > < input name = "l" type = "button" value = "l" / > < input name = ";" type = "button" value = ";" / > < input name = "’" type = "button" value = "’" / > < / div > < div id = "row2_shift" > < input name = "a" type = "button" value = "A" / > < input name = "s" type = "button" value = "S" / > < input name = "d" type = "button" value = "D" / > < input name = "f" type = "button" value = "F" / > < input name = "g" type = "button" value = "G" / > < input name = "h" type = "button" value = "H" / > < input name = "j" type = "button" value = "J" / > < input name = "k" type = "button" value = "K" / > < input name = "l" type = "button" value = "L" / > < input name = ";" type = "button" value = ":" / > < input name = "’" type = "button" value =’ "’ /> </div> <div id=" row3 "> <input name=" Shift " type=" button " value=" Shift " id=" shift " /> <input name=" z " type=" button " value=" z " /> <input name=" x " type=" button " value=" x " /> <input name=" c " type=" button " value=" c " /> <input name=" v " type=" button " value=" v " /> <input name=" b " type=" button " value=" b " /> <input name=" n " type=" button " value=" n " /> <input name=" m " type=" button " value=" m " /> <input name=" , " type=" button " value=" , " /> <input name=" . " type=" button " value=" . " /> <input name=" / " type=" button " value=" / " /> </div> <div id=" row3_shift "> <input name=" Shift " type=" button " value=" Shift " id=" shifton " /> <input name=" Z " type=" button " value=" Z " /> <input name=" X " type=" button " value=" X " /> <input name=" C " type=" button " value=" C " /> <input name=" V " type=" button " value=" V " /> <input name=" B " type=" button " value=" B " /> <input name=" N " type=" button " value=" N " /> <input name=" M " type=" button " value=" M " /> <input name=" lt " type=" button " value=" < " /> <input name=" gt " type=" button " value=" > " /> <input name=" ? " type=" button " value=" ? " /> </div> <div id=" spacebar "> <input name=" spacebar " type=" button " value=" " / > < / div > < / div >

I have taken care to represent characters which have special meaning in HTML, like “The CSS

I have kept the CSS styling very minimal. Of course, if you want your keyboard to look like a dragon, you can go ahead and all that jazz! We set the display property of div enclosing the keyboard to be “none” initially, as we don’t want it to show up till the user activates it by clicking on the “Keyboard” link. In addition, we also hide the “shift” keys, i.e. the keys which get activated only when the shift button is down. I have named these rows with a div id ending “_shift”. We will bring them back into view when the user presses the shift key (we will see later).

The rest of the CSS involves basic formatting to make the keys look like as they are on a standard QWERTY keyboard.

#keyboard { position: absolute; display: none; border: 1px solid #ccc; width: 560px; padding: 10px; cursor: move; } #spacebar input { width: 180px; margin: 0 auto; margin-left: 150px; } #shift, #shifton { width: 70px; text-align: left; } #row0_shift, #row1_shift, #row2_shift, #row3_shift { display: none; } #row0, #row0_shift { padding-left: 20px; } #row1, #row1_shift { padding-left: 60px; } #row2, #row2_shift { padding-left: 70px; } #shifton { border-left: 3px solid #000; border-top: 3px solid #000; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #keyboard { position : absolute ; display : none ; border : 1px solid #ccc; width : 560px ; padding : 10px ; cursor : move ; } #spacebar input { width : 180px ; margin : 0 auto ; margin - left : 150px ; } #shift, #shifton { width : 70px ; text - align : left ; } #row0_shift, #row1_shift, #row2_shift, #row3_shift { display : none ; } #row0, #row0_shift { padding - left : 20px ; } #row1, #row1_shift { padding - left : 60px ; } #row2, #row2_shift { padding - left : 70px ; } #shifton { border - left : 3px solid #000; border - top : 3px solid #000; }

jQuery

Let’s now get to the most important part – the JavaScript that controls the behavior of the keyboard. We will be using two jQuery extensions – one to make the keyboard draggable, and the other to aid in the selection and manipulation of the password field. I have made some additions to the original fieldSelection JQuery plugin by Alex Brem to suit our additional needs. vkeyboard.js contains our custom code.

<script type="text/javascript" src="jquery-1.2.6.min.js"></script> <script type="text/javascript" src="jquery-ui-personalized-1.5.2.min.js"></script> <script type="text/javascript" src="jquery-fieldselection.js"></script> <script type="text/javascript" src="vkeyboard.js"></script> 1 2 3 4 <script type = "text/javascript" src = "jquery-1.2.6.min.js" > </script> <script type = "text/javascript" src = "jquery-ui-personalized-1.5.2.min.js" > </script> <script type = "text/javascript" src = "jquery-fieldselection.js" > </script> <script type = "text/javascript" src = "vkeyboard.js" > </script>

In vkeyboard.js, we place all our code within jQuery’s ready function to ensure that the code runs only after the document is fully loaded.

$(document).ready(function(){ // all our code goes here }); 1 2 3 $ ( document ) . ready ( function ( ) { // all our code goes here } ) ;

Let me just walk you through the underlying logic behind the code. We first add an “onclick” event handler which causes the keyboard to toggle (i.e. show up if hidden, hide if already shown) when the user clicks on the “Keyboard” link.

$("#showkeyboard").click(function(e) { var height = $(’#keyboard’).height(); var width = $(’#keyboard’).width(); leftVal=e.pageX-40+"px"; topVal=e.pageY+20+"px"; $(’#keyboard’).css({left:leftVal,top:topVal}).toggle(); }); 1 2 3 4 5 6 7 $ ( "#showkeyboard" ) . click ( function ( e ) { var height = $ ( ’ #keyboard’).height(); var width = $ ( ’ #keyboard’).width(); leftVal = e . pageX - 40 + "px" ; topVal = e . pageY + 20 + "px" ; $ ( ’ #keyboard’).css({left:leftVal,top:topVal}).toggle(); } ) ;

Next up, we make the keyboard draggable, so that the user can drag it and keep in anywhere on the screen such that it does not obstruct the text underneath. We do this by calling the draggable(), courtesy of the jQuery UI + draggable plugin.

$("#keyboard").draggable(); 1 $ ( "#keyboard" ) . draggable ( ) ;

We need to next define a function that toggles between the default rows on the keyboard and the rows which get activated when the “Shift” key is pressed.

function onShift(e) { var i; if(e==1) { for(i=0;i<4;i++) { var rowid = "#row" + i; $(rowid).hide(); $(rowid+"_shift").show(); } } else { for(i=0;i<4;i++) { var rowid = "#row" + i; $(rowid).show(); $(rowid+"_shift").hide(); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function onShift ( e ) { var i ; if ( e == 1 ) { for ( i = 0 ; i < 4 ; i ++ ) { var rowid = "#row" + i ; $ ( rowid ) . hide ( ) ; $ ( rowid + "_shift" ) . show ( ) ; } } else { for ( i = 0 ; i < 4 ; i ++ ) { var rowid = "#row" + i ; $ ( rowid ) . show ( ) ; $ ( rowid + "_shift" ) . hide ( ) ; } } }

Lastly, we define a function that’s called whenever any of the keys on the keyboard are pressed.

This function checks if the key pressed is Backspace. If it is, then it calls the replaceSelection function from the fieldSelection plugin with an empty string as a parameter, to indicate that a backspace operation (replacing preceding character to the current cursor location by an empty string – i.e. deleting the preceding character) must be performed.

If the “Shift” key had been pressed, then the function sets the “shifton” variable to be true to indicate that the shift key has been pressed and calls onShift(1). However if the shift key has already been pressed, the function deactivates the shift rows by calling onShift(0).

If some other key had been pressed, then we simply insert the character in between the current cursor position. The replaceSelection()handles the case when some characters have already been selected by the user. In that case, the selected characters would be replaced by the character that is represented by the key pressed.

$("#keyboard input").bind("click", function(e) { if( $(this).val() == ‘Backspace’ ) { $(’#pwd’).replaceSelection("", true); } else if( $(this).val() == "Shift" ) { if(shifton == false) { onShift(1); shifton = true; } else { onShift(0); shifton = false; } } else { $(’#pwd’).replaceSelection($(this).val(), true); if(shifton == true) { onShift(0); shifton = false; } } }) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $ ( "#keyboard input" ) . bind ( "click" , function ( e ) { if ( $ ( this ) . val ( ) == ‘ Backspace ’ ) { $ ( ’ #pwd’).replaceSelection("", true); } else if ( $ ( this ) . val ( ) == "Shift" ) { if ( shifton == false ) { onShift ( 1 ) ; shifton = true ; } else { onShift ( 0 ) ; shifton = false ; } } else { $ ( ’ #pwd’).replaceSelection($(this).val(), true); if ( shifton == true ) { onShift ( 0 ) ; shifton = false ; } } } )

And… we are done! Check out the demo and download full source code here.

As you can see, most of the actual hard work is handled by the jQuery plugins. If you are interested in reading up more on the challenges involved with field selection and replacement using Javascript, you should check out this article on Quirksmode.