Typewriter screenshot

Introduction

This tutorial is a showcase of the endless possibility JQuery can achieve. After finishing my previous tutorial on: “Step By Step: Automated JQuery Slideshow” I got another idea on my next experiment. This is very much like the on-screen keyboards we’ve seen around some of the more-secured websites, except that this is full of animation and effects. Afterall, it’s just my another experiment.

The Idea

Let’s first identify what the entire experiment is about. This mechanism should read the keystrokes pressed by users, and then typed the letters into a box. It should also allow users to break a new line, give a spacing, and clearing the field. These shall be the basic key functions for the on-screen keyboard to work.

Now, let’s take a look at what features we wished to implement.

The Features

  • Animate keys upon user’s keystrokes.
  • Allow customization: Setting mouse and keyboard typing.
  • Create a custom message to notify users.

For now, let’s keep it simple with only those features above. Our browsers can┬árecognize┬áthe keystrokes a user typed in with ASCII codes that is bind to each letters, numbers, symbols and modifiers on our keyboard. For this tutorial purpose, I shall be separating each portion into 3 sets: header, main, footer. Header for “message” feature, “main” for the box which will display what the users typed, and “footer” for the on-screen keyboard.

Here’s a few URL to help you get started with, and some of which I personally used to keep track of the keystrokes and specifications of each browsers.

ASCII Codes URL

For the second link, if you’re confused which column to use; the fourth column are the ASCII codes our browser used to detect the keystrokes. With all the necessary info and resources laid out, all that’s left is to develop the mechanism. Let’s get on to the HTML & CSS first.

HTML Layout

As the message should unobtrusively be displayed in a visible and obvious manner, placing it on the top would seem more logical. Create the container for the “message” feature.

1
2
3
4
<div id="container">
	<div id="header">
		<div id="msg"></div>
	</div><!-- end of #header -->

With the “message” container constructed within the header, it will not affect whatever elements below. Let’s create the container for the box that will contain what the users typed. An example would be like this:

1
2
3
4
	<div id="main">
		<div id="typed-container"><p id="typed"></p></div>
		<div id="letter-backspace" class="keys backspace">Del</div>
	</div><!-- end of #main -->

The code above has an extra container for a key called “Del”. This button shall function as a “clear message” which will be placed close to the box where the typed words are displayed. On to the last portion, setting up the layout of the keyboard. Here, it requires more structured layout. In my case, I’ve just created a nest of “div”s to contain each key. You may use alternative methods like “ul”, “dt”, etc. Below is an example of my structure.

1
2
3
4
5
6
	<div id="footer">
		<div id="keyboard">
			<div id="group-0">
				<div id="letter-1" class="keys float letters">1</div>
				<div class="flush"></div>
			</div>

I’ve also included an exterior container called “group” to better organize and contain these keys. It’s pretty straight-forward here, all you need to do is lay all the keys you’re going to implement in a well-structured layout. Here’s the entire structure for my keyboard.

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
	<div id="footer">
			<div id="keyboard">
				<div id="group-0">
					<div id="letter-1" class="keys float letters">1</div>
					<div id="letter-2" class="keys float letters">2</div>
					<div id="letter-3" class="keys float letters">3</div>
					<div id="letter-4" class="keys float letters">4</div>
					<div id="letter-5" class="keys float letters">5</div>
					<div id="letter-6" class="keys float letters">6</div>
					<div id="letter-7" class="keys float letters">7</div>
					<div id="letter-8" class="keys float letters">8</div>
					<div id="letter-9" class="keys float letters">9</div>
					<div id="letter-0" class="keys float letters">0</div>
					<div class="flush"></div>
				</div>
				<div id="group-1">
 
					<div id="letter-a" class="keys float letters">a</div>
					<div id="letter-b" class="keys float letters">b</div>
					<div id="letter-c" class="keys float letters">c</div>
					<div id="letter-d" class="keys float letters">d</div>
					<div id="letter-e" class="keys float letters">e</div>
					<div id="letter-f" class="keys float letters">f</div>
					<div id="letter-g" class="keys float letters">g</div>
					<div id="letter-h" class="keys float letters">h</div>
					<div id="letter-i" class="keys float letters">i</div>
					<div id="letter-j" class="keys float letters">j</div>
 
					<div class="flush"></div>
				</div>
				<div id="group-2">
					<div id="letter-k" class="keys float letters">k</div>
					<div id="letter-l" class="keys float letters">l</div>
					<div id="letter-m" class="keys float letters">m</div>
					<div id="letter-n" class="keys float letters">n</div>
					<div id="letter-o" class="keys float letters">o</div>
					<div id="letter-p" class="keys float letters">p</div>
					<div id="letter-q" class="keys float letters">q</div>
					<div id="letter-r" class="keys float letters">r</div>
					<div id="letter-s" class="keys float letters">s</div>
					<div id="letter-enter" class="keys float enter">Enter</div>
					<div class="flush"></div>
				</div>
				<div id="group-3">
					<div id="letter-t" class="keys float letters">t</div>
					<div id="letter-u" class="keys float letters">u</div>
					<div id="letter-v" class="keys float letters">v</div>
					<div id="letter-w" class="keys float letters">w</div>
					<div id="letter-x" class="keys float letters">x</div>
					<div id="letter-y" class="keys float letters">y</div>
					<div id="letter-z" class="keys float letters">z</div>
					<div id="letter-space" class="keys float space">Space</div>
					<div class="flush"></div>
				</div>
				<div id="group-4">
					<div id="letter-comma" class="keys float letters">,</div>
					<div id="letter-fullstop" class="keys float letters">.</div>
					<div id="letter-questionMark" class="keys float letters">?</div>
					<div id="letter-quotes" class="keys float letters">'</div>
					<div id="letter-apostrophe" class="keys float letters">"</div>
					<div id="letter-exclamation" class="keys float letters">!</div>
					<div id="letter-at" class="keys float letters">@</div>
					<div id="letter-dollar" class="keys float letters">$</div>
					<div id="letter-dollar" class="keys float letters">%</div>
					<div id="letter-dollar" class="keys float letters">&</div>
					<div class="flush"></div>
				</div>
			</div><!-- end of #keyboard -->
	</div><!-- end of #footer -->
</div><!-- end of #container -->

(The yellow colored text is due to the usage of “&” as text in the last div key)

CSS Styling

With our HTML page nicely setup, we need to style and position all the elements so that it sits perfectly on our containers and designated place. As usual, I would always use a CSS total reset to ensure I’m having full control of all elements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*===============================================
CSS TOTAL RESET
===============================================*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-weight: inherit;
	font-style: inherit;
	font-size: 100%;
	font-family: inherit;
	vertical-align: baseline;
}
:focus {
	outline: 0;
}

To start styling up the entire page, we begin with the “global elements” which are commonly used.

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
/*===============================================
GLOBAL ELEMENTS
===============================================*/
a {
	color: lightblue;
	text-decoration: none;
}
 
a:hover {
	text-decoration: underline;
}
 
.flush {
	clear: both;
}
 
.float {
	float: left;
}
 
body, html {
	background: #111;
}
 
#container {
	padding: 20px;
}
 
#container #main {
	position: relative;
	margin: 20px auto 20px;
	width: 900px;
}

If you recalled from the above keyboard structure, all keys have a class called “float”. That is to ensure all the keys sit close with each other. By setting a width to the “main” container, we can use “margin:auto;” to position it in the center of the page. Following so far? Good.

Our header should sit on top of the page, positioned in the center with a given height so that the containers below will not be affected when the message appears and disappears.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*===============================================
HEADER ELEMENTS
===============================================*/
#container #header #msg {
	position: relative;
	margin: auto;
	padding: 5px 20px;
	width: 660px;
	height: 20px;
	border: 1px solid #A60000;
	background: maroon;
	color: #fff;
	text-align: center;
	text-shadow: 0 1px 2px #000;
 
	-o-border-radius: 10px;
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	border-radius: 10px;
 
	opacity: 0;
	filter: alpha(opacity=0);
}

As shown above, a width and height is given so that we may better position the message in the center. But if you have a much longer message, you may wish to change the width to “min-width: 660px;” and height to “min-height: 20px;”, so that the message may expand when needed.

CSS3 is used here, mainly “text-shadow” and “border-radius”. The “opacity” will hide the message when the page loads, and by using JQuery, we can animate it to appear when needed. I shall touch on that later on. The use of “filter: alpha(opacity=0);” is mostly for older Internet Explorer that does not support “opacity”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*===============================================
MAIN ELEMENTS
===============================================*/
#container #main #typed-container {
	position: relative;
	margin: 50px auto -20px;
	padding: 10px;
	width: 800px;
	height: auto;
	min-height: 60px;
	border: 1px solid #000;
	border-bottom: none;
	background: #050505;
	font-family: Georgia, Helvetica, Verdana;
	font-size: 25px;
	color: #fefefe;
	text-align: justify;
	white-space: pre-wrap;
}

Notice the use of “min-height: 60px;” here? This is to allow the container to adjust to the new-line break option the users’ are allowed to perform with the “enter” key. 60px will allow the container to maintain at least a visible height above the keyboard even without texts.

1
2
3
4
5
6
#container #main #typed {
	width: 720px;
	height: auto;
	min-height: 60px;
	background: #010101;
}

This is where the text that is typed by the user will appear. The width is smaller than its container so that there’s ample space for the “Del” button to be placed on the right side. With all the above constructed, let’s move on to the more tedious part of this tutorial. Let’s position the footer container first.

1
2
3
4
5
6
7
/*===============================================
FOOTER ELEMENTS
===============================================*/
#container #footer {
	position: relative;
	margin: 0 20px 50px 20px;
}

It’s a simple positioning so that it falls into the right place of our desired layout. Now, we need to construct the keyboard container, which shall be containing the keys.

1
2
3
4
5
6
7
8
9
10
11
#container #footer #keyboard {
	margin: auto;
	width: 850px;
	height: 300px;
	border: 1px solid #121212;
	background: #050505;
 
	-o-box-shadow: 0 2px 10px #000;
	-moz-box-shadow: 0 2px 10px #000;
	-webkit-box-shadow: 0 2px 10px #000;
}

With a given height and width, we use “margin:auto;” to center it within the “keyboard” container, along with its own visual settings. Next, we will make the keys look pretty and stylish with CSS3.
keyboard-styled
A preview of the keyboard after being styled.

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
#container .keys {
	padding-top: 5px;
	margin-top: 20px;
	margin-left: 30px;
	font-family: Helvetica, Verdana;
	color: #7f5b1e;
	text-align: center;
	text-shadow: 0 1px 2px #000;
	cursor: pointer;
 
	border: 1px solid #333;
	-o-border-radius: 5px;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
 
	background: #121212;
	background-image: -webkit-gradient(
	    linear,
	    left bottom,
	    left top,
	    color-stop(0.47, rgb(0,0,0)),
	    color-stop(0.74, rgb(17,17,17))
	);
	background-image: -moz-linear-gradient(
	    center bottom,
	    rgb(0,0,0) 47%,
	    rgb(17,17,17) 74%
	);
}

Constructing the keyboard can be made easier if we separate the different purposes of a styling into different classes. In other words, a class “.float” will cause the element to float the direction stated. In this way, changes or editing the layout will not be tedious to do. In this case, I separated the keys styling from any other styling such as floats, or specific styles for letters and symbols.

1
2
3
4
#container .keys:hover {
	color: #fefefe;
	text-shadow: 0 0px 20px #fff;
}

I’ve given additional visual effects by using the pseudo “hover” and a large blur radius for text-shadow. So whenever the user’s mouse hovers over any keys, it will give the text-shadow and color animation. The next set of codes is actually meant for mobile users, where hover does not come into effect. The keys will then show a slight change in its border color to inform the users of what they pressed.

1
2
3
#container .keys:active {
	border: 1px solid lightblue;
}

Now we got the visual effects done, we need to form the keyboard in a neat order, and shaped like keyboard keys. Here’s the size for each key.

1
2
3
4
#container #footer #keyboard .letters {
	width: 50px;
	height: 25px;
}

Not too big, not too small, just the right size of an actual key. Now, we do know that certain keys have a different size compared to the standards, such as “space”, “enter”, “shift”, etc. Let’s style up the keyboard to make it looked more convincing, shall we?

1
2
3
4
#container #footer #keyboard .space {
	width: 210px;
	height: 25px;
}

This CSS style extends the width of a “space” key, just like you would see in a normal keyboard layout. Remembered that we decided to have a “Del” button on the right side of the typing area? We should position and style it now.

1
2
3
4
5
#container #main #letter-backspace {
	position: absolute;
	bottom: 20px;
	right: 60px;
}

This positions it to sit neatly beside the typing area. The size of the “Del” is actually the same as any other keys in this case. So, why would I be re-creating another class for it? The reason is, it allows easier modifications in the future should you wish to change its position and size. Of course, if you think its redundant to do so, you may skip this step.

1
2
3
4
#container #main .backspace {
	width: 50px;
	height: 25px;
}

The same applies for the “Enter” button. I did the same thing to have its own classes, so you may change its width as an alteration option. The only thing you need to note is, changing of widths of any buttons will cause the layout to shift. The container that contains all these keys has a given width, so exceeding that would cause some of that row’s keys to move down.
keyboard-keys-styled
The preview after all the keys are positioned and styled.

The JQuery

You are expected to have some basic knowledge of JQuery to work on this, which I’ve mentioned earlier on top, as I won’t be going through the tiny details or basics. I will only discuss and share the concept to make the keyboard work, otherwise you may simply download a copy to explore the coding.

1
2
3
4
5
6
7
(function($) {
 
	$.fn.virKeyboard = function(settings) {
		var defaults = {
			mouse: true,
			intro: true
		};

This sets the entire script as a plugin, where you simply call for just the “virKeyboard();” and attached it to a container you would like to apply on. There isn’t a real need for settings here, but if you would like to use it, the code above shows you how to.

1
2
		//EXTEND THE SETTINGS TO DEFAULTS
		var settings = $.extend(defaults, settings);

This extends the setting, so that users may declare their own customizations that will alter the plugin.

1
2
3
4
5
6
7
8
9
		//INFORM USER TO START TYPING
		//FADE AWAY AFTER A SHORT DELAY
		$('#msg').html("You may start typing and see the effects!").animate({
			opacity: 1
		}, 'fast', function() {
			$(this).delay(1500).animate({
				opacity: 0
			}, 'fast');
		});

But before everything starts, to enhance the entire plugin we are going to add a simple notification, which uses the “message” container we built earlier in the “header” container. The above code sets the inner text of the “message” container and then animates it to appear. With a short delay, the notification will then disappear again.

1
2
3
4
5
6
7
		//FUNCTION THAT TRIGGERS OFF ON EACH KEYPRESS
		$(document).keypress(function(e) {
			switch(e.which) {
				//KEYSTROKES ASCII FOR THE ALPHABETS
				case 97:
					keystroke('a');
					break;

Here is the core of the entire keyboard plugin. Basically, we look out for key presses that users make, and then execute a certain set of code depending on what that key is. To do it, we use “$(document).keypress(…)” to check for key presses, and “switch(e.which)” to check for what keys are pressed. As I’ve provided the link to get the ASCII codes above, please refer to it for a complete list of keystrokes.

In this case, the demo above shows you how to set for each key. Yes, you have to set a response for each key in order for the keyboard plugin to work. Notice the function inside the loop? I shall be touching on that now.

1
2
3
4
5
6
		//FUNCTION TO HANDLE THE KEYSTROKES
		//INPUTS THE KEY INTO THE TYPING AREA.
		function keystroke(key) {
			var p = $("#typed"); //VARIABLE FOR THE "TYPED" CONTAINER.
			var text = p.html(); //VARIABLE FOR THE TEXTS INSIDE THE "TYPED" CONTAINER.
			var keystroke = $("#letter-"+key); //SETTING THE ID FOR THAT SPECIFIC KEYSTROKE.

This is the “keystroke()” function that processes and inserts the key of what the users typed. The code above first declare all the required variables we shall be using often in the later part of the code.

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
			//THE IF-ELSE LOOP BELOW CHECKS FOR SYMBOLS
			//OR MODIFICATION KEYS ON THE KEYBOARDS.
			//ALPHA-NUMERICS ARE NOT REQUIRED AS THE KEYS
			//ARE THE LETTERS/NUMBERS ITSELF.
			if(key == "Space") {
				key = "&nbsp;";
			}
			if(key == "Enter") {
				key = "<br/>";
			}
			//SETTING THE KEY VALUE FOR ALL
			//THE SYMBOLS.
			if(key == "comma") {
				key = ",";
			}
			if(key == "fullstop") {
				key = ".";
			}
			if(key == "questionMark") {
				key = "?";
			}
			if(key == "quotes") {
				key = "'";
			}
			if(key == "apostrophe") {
				key = "&#34;";
			}
			if(key == "exclamation") {
				key = "!";
			}
			if(key == "at") {
				key = "@";
			}
			if(key == "dollar") {
				key = "$";
			}

It’s pretty straight-forward as it only checks for the keystrokes, and then replace the key’s value to the correct symbols. What’s left is the “Del” key. It’s easy, but you need to also notify the users that their text is cleared.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
			//IF USER PRESSES THE "DEL".
			if(key == "backspace") {
				key = ""; //THE KEY VALUE IS CLEARED.
				text = ""; //THE TEXT IN THE "TYPED" CONTAINER WILL BE CLEARED.
				//THE "MESSAGE" CONTAINER WILL THEN BE INSERTED
				//WITH THE FOLLOWING TEXTS.
				$('#msg').html('Your message has been cleared!');
				//THE "MESSAGE" CONTAINER WILL THEN
				//ANIMATE TO APPEAR AND NOTIFY USER.
				$('#msg').stop(true,false).animate({
					opacity: 1
				}, 'fast', function(){ //AFTER A SHORT DELAY, IT WILL DISAPPEAR.
					$(this).delay(1500).animate({
						opacity: 0
					}, 'fast');
				});
			}

Again, straight-forward. Clear key’s value, clear text, and then notify.

Now, you might be asking: “Why do you have to do that when the ASCII code are bind to the keys?! If they are detected, it will input the exact character, right?” Yes, it will. But don’t forget that your plugin is not to simply typed out what the users has keyed. You need to show it on your virtual keyboard. That is, the animation to tell or notify the users that that key is pressed.

And to do that you need to use the key’s ID, which is done so by using “var keystroke= $(“#letter-”+key);”. Do you get the idea of how the keyboard’s mechanism work? Good! We’re now going to put the keys of what the users typed, into the “typed” container, like this:

1
			p.html(text+key); //SETS THE INNER TEXT TO BE THE KEYS USER TYPED.

Yes, as simple as this. What it does is basically, combining whatever that has already been typed into the container, with the newly typed keys, and then placed back into the “typed” container. The last part, is actually just to animate the keys in the virtual keyboard to notify which keys are pressed.

1
2
3
4
5
6
7
8
9
			//ANIMATES THE VIRTUAL KEYBOARD TO DENOTE WHICH KEYS ARE PRESSED
			keystroke.stop(true,false).css({"border":"1px solid lightblue"}).animate({
				marginTop: 15
			}, 300, function() { //AFTER A SHORT DELAY, FINISH THE ANIMATION
				$(this).delay(300).css({"border":"1px solid #333"}).animate({
					marginTop: 20
				}, 'fast');
			});
		}

The “keystroke” in the code above, is exactly what I’ve just explained about the confusion of the replacements of symbols. Without a valid keystroke, which is the keys’ ID, your keys cannot animate.

Mouse Settings

This is only needed if you decided to implement the “mouse” feature stated above. If you recalled, we have a “mouse” settings implemented and default to be “true”. If you remove the settings, then you may just skip this section.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
		//FUNCTION TO HANDLE THE KEY EVENTS
		//THAT WILL TRIGGER OFF ON EACH CLICKS
		if(settings.mouse) {
			//BACKSPACE REQUIRES SPECIAL ATTENTION
			//TO SET THE KEYSTROKE AS BACKSPACE
			$('#letter-backspace').click(function(e) {
				keystroke('backspace');
				e.preventDefault();
			});
			//BINDS THE CLICK EVENT TO EACH KEYS IN THE
			//KEYBOARD, AND ACTIVATE THE KEYSTROKE FUNCTION
			$('#keyboard .keys').bind('click', function(e) {
				var key = $(this).html();
				keystroke(key);
				e.preventDefault();
			});
 
		} //END IF FOR MOUSE TRIGGERS

If you do notice, the “keystroke” issue I’ve mentioned earlier for the symbols do not apply here. Why? Basically, it’s because the animation for mouse-clicks are triggered with CSS pseudo styles “:hover” and “:active”. There’s absolutely no need to replicate the animation used above for keys that are typed.

Unsolved

There are a few features that I’m still unable to implement. Modifications such as “Shift”, “Capslock”, “ctrl-c”, “ctrl-v”, etc. Well, I did manage to have some leads and progress on “Shift” and “Capslock”, but was only midway through and found myself stuck. And yes, there’s a one bug in which I figured the problem, but didn’t know how to solve. Notice the “Please Note:” at the bottom? Yeah, that’s the unsolved bug. Texts continue to typed in and doesn’t break a new line even when it exceeds the width of the container. Do you know how to solve it? Share it with us!

Conclusion

Of course, you may be wondering the purpose and use of such plugins or script. I’ve been asked by a friend as well. There’s no particular reason though, except that its an experiment to explore different fields, ways and methods, possibilities and ideas, that may come along as you work with JQuery, HTML/CSS, Ajax, etc, everyday.

Nonetheless, I hope this tutorial teaches a thing or two, or inspire newer magnificent creations through it. Thank you for reading it, and remember to follow me on Twitter @GrayJunior!