Design

The Touchscreen Toolkit consists of a combination of JavaScripts and Cascading Style Sheets (CSS) that together make changes to the HTML Document so that it may be used with a touchscreen. The main purpose of the CSS is twofold:

The main purpose of the various JavaScripts is also twofold:

The heart of the toolkit lies within its JavaScripts, which follow an Object-Oriented Design. Below is a UML diagram showing the various classes in the toolkit and how they interact with one another (click to enlarge).

Currently, there are six main classes. The seventh, tsTouchscreenExt, in the diagram only serves to show how the toolkit can be extended, which is further explained in the Extended Use section. All class names are prefixed with "ts" to avoid name conflicts with other JavaScript functions or classes. Below is a description of each of the six classes, which is meant to accompany the UML diagram.

Class Description and How it Works
tsCompatibility

This class, whose methods are all static, provides a single interface to functionality that differs across browsers. For example, the function to attach event listeners to HTMLElements in most browsers is obj.addEventListener(). However, this syntax is not supported in Internet Exlporer, which uses the obj.attachEvent() function. So, when attaching event listeners to objects, the toolkit uses the tsCompatility.addEventListener() function, which decides whether to use addEventListener() or attachEvent(). As mentioned all methods and attributes in this class are static, which means that instantiation is not necessary, and that all functions must be referred to by tsCompatibility.<function()>.

As seen from the blue lines in the UML diagram, almost all classes directly or indirectly rely upon this class, so the functionality of the entire toolkit is dependant upon it functioning correctly. For a more detailed description of this class, see the class documentation.

tsMove

This class allows objects to be dragged around the screen by the user. For example, if you had an HTML Div Element referenced by the variable divElement, to make the user able to drag it across the screen, the following line of code would be necessary:

new tsMove(divElement, divElement);

As you can see from the class documentation, the first parameter is the HTMLElement to make draggable, and the second parameter is the HTMLElement that, when the mouse is pressed down upon, will begin the dragging, which are known as the target and the mover, respectively. Both parameters can either be the same HTMLElement, or the second can be a child of the first. As you may guess, the first parameter must also have absolute positioning.

How this works is as follows. The tsMove class's methods and attributes are mostly static to ensure only one object may be moved at a time, although it does have some instance variables. When a tsMove object is created, during construction event listeners are added to the target and to the mover. In short, when the mouse is pressed down on the mover, the tsMove class enters into the moving state (tsMove.enterMoveMode()). When the mouse is dragged, if the tsMove class is in the moving state, it compares the last saved mouse position coordinates with the current mouse position coordinates, and adjusts the target accordingly (tsMove.move()). When the mouse is released, the tsMove class exits from the moving state (tsMove.exitMoveMode()).

Saving a reference to a newly created tsMove object is not necessary because the most important features are the event listeners, which are never lost. For a more detailed description of this class, see the class documentation.

tsScroll

This class allows the binding of touchscreen-sized scrollbars to an HTMLElement or to the window object. For example, if you had a scrollable HTML Div Element referenced by the variable divElement, to allow the user to scroll the element with a touchscreen-sized scrolling apparatus, the following line of code would be necessary:

new tsScroll(divElement);

Upon creation of the tsScroll object, it will create the scrolling apparatus and set up all of the event listeners necessary to cause scrolling. The tsScroll class mainly works by creating event listeners, timeouts, and intervals. For example, all of these techniques are used in the scroll up button (and all scroll buttons). When a user presses down on a scroll up button, it not only scrolls up once, but sets a timeout for a fraction of a second, which waits that fraction of a second, and if the user is still pressing on the scroll up button, it creates an interval to continuously scroll the element up every so often until the button is released. If the button is released before the inital timeout expires, the interval is never created.

As with the tsMove class, saving a reference to a newly created tsScroll object is not necessary because the most important features are the event listeners, which are never lost. For a more detailed description of this class, see the class documentation.

tsKeyboard

This class allows the creation of keyboards for use with on-screen typing. It provides for many functions to allow the creation of customized keyboards, and the tookit itself uses this class to create the three main default keyboards (Alphabetized, Qwerty, and Numeber Pad).

The way that this class works is as follows. Upon construction, it creates an HTML Div Element with a few default buttons, such as Hide and Move (it makes it movable by using the tsMove class), and also allows the user to switch to using other keyboards by having a button per keyboard. By creating a new tsKeyboard object, the newly-created keyboard will automatically become on option on all other keyboards.

The tsKeyboard class also provides for a number of static methods that allow the creation of buttons (character buttons, tab buttons, caps buttons, etc.).To add these buttons to the keyboard, you must append them to the tsKeyboard.keyboard HTMLElement, which is the aforementioned Div that contains all of the keyboards buttons. For a more detailed description of this class, see the class documentation.

tsUI

All methods and attributes in this class are static, and it handles the creation of all of the user interface elements with the exception of keyboards, which are handled by the tsKeyboard class. For example, it creates the navigation bar, which is displayed at the top of the HTML Document to let the user go back and forward between pages as well as show the keyboard.

Also notable is the fact that this class handles the notion of the currentInputTarget. The tsUI.currentInputTarget refers to the input who is able to receive input from the currently selected keyboard, and it is highlighted to show the user that it is receiving input. Clicking on an input will make it the currentInputTarget, and also clicking on a "Tab" button on a keyboard will switch between the various possible input targets. So, as you can see, the tsUI and tsKeyboard classes work closely together to allow for on-screen typing, but they must remain separate to allow for creating multiple keyboards.

tsTouchscreen

This is the main class for the entire toolkit. Instantiating an object of this class is how to load the entire toolkit. However, it should never be instantiated directly. Instead, the static tsTouchscreen.tsInit() function should be used to either instantiate a default tsTouchscreen object, or to instantiate an object that is a subclass of the tsTouchscreen object. Tunneling the loading of the toolkit through this function allows others to extend the toolkit without ever modifying the toolkit itself. Also, it ensures that the loading of the toolkit happens only after the page has been loaded, which is necessary for proper functioning of the toolkit. For more information, see the Extended Use section and the class documentation.

Important Concepts

IDs

It is important to note the use of ids. The non-static classes all have a static Array called instances, which stores all of the instances of that class, with each index being the id of an object and each value being a reference to the object. This is very important because very often, and especially in the tsMove and tsScroll classes, event listeners are bound to HTMLElements, which then have no way of getting back to the instance to which they belong. The way to fix this is to assign each instance of the class an id and store it in the instances Array. Then, when event listeners are bound to the HTMLElement, the HTMLElement is also given a parameter that stores the id of the object to which it belongs. Then, the HTMLElement's function to process the event can call the static getInstance method to retrieve the object to which it belongs.

For example, the tsScroll class creates a scrolling apparatus, one component of which is the scroll up button. This button is an HTMLElement, and an event listener is added to it with a function that scrolls up the object to which it is bound. Since this function is executed on a separate thread and is shared among all tsScroll objects, it has no way of knowing to which tsScroll object it belongs. So, an attribute called tsScrollId is added to the button, so that in the function that processes the event, it may call tsScroll.getInstance(), passing it its own tsScrollId, to retrieve the tsScroll object to which it belongs and scroll the object up.

Optimizations by Anonymous Functions

The toolkit also makes use, when available, of optimizations regarding function definitions using anonymous functions. Many functions, especially in the tsCompatibility class, have many possible execution paths, which follow one main if, else if, ..., else if, else statement. However, in some instances, such as in the tsCompatibility class, it is possible to decide when defining the function which path will be chosen.

For example, consider the two following definitions of the tsCompatibility.addEventListener() function:

tsCompatibility.addEventListener = function(obj, type, fcn, phase) {
    if(window.addEventListener != null) {
        obj.addEventListener(type, fcn, phase);
    } else if(window.attachEvent != null) {
        obj.attachEvent('on'+type, fcn);
    }
}
if(window.addEventListener != null) {
    tsCompatibility.addEventListener = function(obj, type, fcn, phase) {
        obj.addEventListener(type, fcn, phase);
    }
} else if(window.attachEvent != null) {
    tsCompatibility.addEventListener = function(obj, type, fcn, phase) {
        obj.attachEvent('on'+type, fcn);
    }
}

In the first example, if the user's browser recognizes only obj.attachEvent() (as all versions of Internet Explorer do), it would have to perform two comparisons before actually adding the event listener. At the very least, it would have to perform one comparison (the first one). When adding many event listeners, these extra comparisons can translate to slower performance.

However, in the second example, the function defintion changes based on those comparisons, since the fact that the browser supports the obj.addEventListener() function or obj.attachEvent function is not going to change at run time. So, this second example of how to define the function guarantees that the function will never have to make any comparisons when adding the event listener.