Obsurvey - when you need answers

Usability is In the Application (UIA)


(Work-in-progress since 2002, by Allan Ebdrup)

This article is intended for web developers. It is a description of some of the main features of UIA. UIA is my JavaScript framework for writing entire applications or rich internet applications (RIAs). I think it is most powerful for developing applications for use within an enterprise. But can be used for things like my obsurvey application too. It is very strong when dealing with structured data and documents, as you often do in an enterprise. Also, in an enterprise functionality is king, it is more important that the application is powerful and easy to use, and not so important that it is beautiful. UIA has no fancy effects or animations. It's far from a fancy flash animation, but you can make beautiful applications with UIA.

The main features of my framework are:

  • Classic inheritance and interfaces
  • Type checking
  • Obfuscation
  • Boxing the types
  • Mapped array
  • One to many
  • HTML components
  • Data binding
  • HTML array
  • Undo support
  • Drag and drop

Each feature is described in detail in the following sections.

Classic inheritance and interfaces

Like many other JavaScript frameworks I’ve implemented classical inheritance inspired by Douglas Crockfords original article. I’ve also added what I call interfaces; they have definitions of method signatures that you have to implement. My interface implementation also supports having code in the interface for default implementations of the methods in the interface, a kind of controlled multiple inheritance. Furthermore I’ve implemented the possibility to pass arguments when you implement an interface, you call a myImplements method passing the interface you want to implement and add the parameters you want to pass. An example of how I use my interfaces, is the way I’ve implemented drag and drop. See the section on drag and drop for more details. In drag and drop I use this for a kind of generically typed interface.

Type checking

I’ve implemented type checking on all constructor and method calls. Type checking is turned off in the production environment, the type checking is not included when I obfuscate the script for production. I’ve implemented type checking by use of hungarian notation, so if a parameter is called intCount, the type checking is inserted to check that intCount is indeed an integer. The type checking is performed on every method call. I also support allowing parameters to be undefined by suffixing with a u, uintCount, and I support allowing nulls by suffixing with n, nintCount. Type checking is also done on types, suppose you have a class called Employee, if you specify a parameter called objEmployee it will be type checked to be an Employee object or one of its subclasses.

Obfuscation

I’ve implemented an obfuscator in JavaScript using regular expressions, it can’t handle all JavaScript, but it can handle all my JavaScript. I use the .replace method and I obfuscate in one sweep. In FireFox I can obfuscate 430KB of JavaScript in 2 seconds, reducing it’s size to 150KB. I’ve Implemented an environment where I have an extra menu in the development environment, one of the items on this menu is obfuscate, I click that and I get a screen where all the JavaScript used in the application is fetched into one big script. So even though I have a fine grained include in my development environment, it all gets put together to one script in production. Then I click obfuscate, get a summary of the compression and click “deploy to test”. Now I have the obfuscated code running in my test environment, an exact copy of my production environment. When I have tested there, I click deploy and the new script is deployed to production.

Boxing the types

I have boxed versions of all the types in JavaScript, and I have extended the base types with a box method. This allows me to throw events whenever one of the boxed types is updated. I have a class called ModelEvent that is passed when events are thrown. For the basic types it is pretty straight forward, there is just an update. For arrays I support listening to all types of modifications to the array or just listen to certain kinds of events. I’ve also created an integer boxed type, which contains a number but checks that it’s an integer. By using a logarithmic search algorithm I found the number where adding one to the number is rounded off and has no effect on the integer part. I use this number as the maximum possible integer value.

Mapped array

The MappedArray class takes a function and a boxed array, the source array, in it’s constructor. The function is a mapping function. The idea is that the mapped array always contains the elements of the source array after they have been mapped by the mapping function. Using the events I get from the boxed source array I update the mapped array whenever changes are made to the source array. So for example when a new element is pushed on the source array, the mapping function gets called on the new element and whatever the mapping function returns is pushed on the mapped array. I’ve implemented all the manipulations you can make to an array, including slice, and added some of my own.

MappedArray inherits from the normal boxed array, so with polymorphism you can use a mapped array anywhere a normal boxed array can be used.

One to many

The OneToMany class takes a boxed array and a pointer in its constructor. The pointer is either one of the elements in the boxed array or null. When you change the value of the pointer it has to be an element in the boxed array or null, this is checked. When changes to the boxed array are made, the one to many automatically checks that the pointer is still valid. If the pointer is no longer valid, because the element in the pointer has been removed for the boxed array, the pointer is either set to null or an error is thrown, depending on how you have configured the one to many. It’s a bit like foreign keys in databases. The one to many has functions like moveNext, movePrevious etc. The one to many class also supports listening to changes to the pointer, like all the boxed types. I have found many uses for the one to many class, one of the being for dropdowns.

HTML component

Almost everything rendered on the screen I UIA is a HTML component, they inherit form the HTMLComponent class. Each HTML component has a HTML tag that it is rendered as, and it supports having a header and footer. So when you addHTMLChild to the HTML component it is added after the header and before the footer. A HTML component is almost always a square on the screen, although it can contain absolutely positioned children. HTML components are really just a proxy to the bare DOM calls. I’ve implemented my own event handling system and the support swapping and other neat stuff but that’s it.

Data binding

With the boxed types and the HTML component in place it’s time to build some HTML components that support data binding. For example I have a class called HTMLInteger. It takes a boxed integer in its constructor. It renders as a input type text HTML element. Whenever the box is updated I update the boxed integer automatically, in short data binding. Because I know the type is an integer I only let keystrokes that are numbers or minus filter through. I’ve also let the up and down arrows add and minus one from the number. I’ve created HTML components for all the boxed types I have, witch is a superset of all the types in JavaScript.

HTML array

A HTML array is used for data binding an array. It is basically just a mapped array where the mapping produces HTML components. The source array is an array in the display model that is mapped to a target array of HTML components. HTML array is a HTML component and inherits from HTMLComponent, so you can add it to your HTML.

All changes to the source array are automatically mapped to HTML components. The HTML array then maps these changes to operations on the DOM of the HTML page. This means that newly created HTML components are inserted in the correct place in the DOM, deleted HTML components are removed from the DOM and swapped elements are also swapped in the DOM.

The abstraction a HTML array provides is that you just need to have a boxed array in your display model and a mapping function. When you have changes, you just update your boxed array in your display model, events are thrown automatically from the boxed array, the mapping function is automatically called if needed and the HTML array automatically makes the appropriate changes to the HTML. All the manipulations you can do to a boxed array are supported by the HTML array.

Drag and drop

To have your HTML component be draggable you simply implement the HTMLDraggableForDropController. HTMLDraggableForDropController has the default implementation for dragging for drop, and has the abstract methods getDragForDropArea and getDragForDropData.

The getDragForDropArea must be implemented to return the HTML component that defines the area where you can click the mouse, hold the button down and start dragging.

The getDragForDropData method must be implemented to return the data beeing dragged, the data that will be passed to the HTML component that eventually accepts the drop.

To accept a drop you implement the HTMLDropController. HTMLDropController has the default implementation for accepting a drop, and has the abstract methods getDropArea and dropDataHandler.

The getDropArea must be implemented to return the HTML component that defines the area where you can drop the data.

The dropDataHandler must be implemented to accept the data beeing dropped.

When implementing HTMLDropController you specify what types can be dropped by passing the classes in the myImplements method. The implementation makes sure your dropDataHandler is never called with data of types you don’t accept. The implementation supports polymorphism, so when you accept a class you automatically accept all it’s subclasses.

Undo support

I’ve build in undo functions for the most important boxed types. The boxed types all inherit from a base class called UndoType. This means that in order to get Undo support for modifications to your boxed types, all you have to do is set an UndoStack on the type. If you do this the boxed type automatically registers all modifications to it and you can undo/redo them by calling the methods undo() and redo() on the UndoStack.

Because of the databinding capabilities of UIA, the only place you have to worry about undo’s is in your display model. If you let your display model inherit from UndoStack and register all your properties you want undo for using the inherited method addUndoChild(), you don’t need to do anything else to get full undo support. In practice this means that I could add undo support to obsurvey using just 16 lines of code in the display model, and the where all either to inherit from UndoType or addUndoChild(). This was possible because all the data in the entire display model for obsurvey is expressed as arrays of things and strings, and I used my boxed arrays and strings.

Please ask questions or leave comments

Other articles by me

I've written an article about undo functionality in web applications entitled Where did undo go?.

Obsurvey uses my Structured Active Rich Document (SARD) principles, that you can see in action when editing a survey's questions.


Obsurvey is created by Copenhagen code. It's a free service with no adds at all.
Here you can create you own online surveys, collect responses from people you yourself invite and analyze the results

Obsurvey ©2007-2013 Copenhagen Code. [Donate | Forum | Privacy policy]