I like rich prototyping for web application interfaces. The richer the interface controls in an initial design, the easier it is to identify missing or desired interface features. And I'm mainly thinking out loud about steps in interface development that follow early abstraction steps (i.e. creating models for tasks and roles and use cases). Because, at some point, a page needs to be built so that site creators can evaluate the user experience being constructed.
At first, I just hard-coded an entirely new markup and scripting set for each prototype. But this became pretty costly in terms of time, at least for larger projects. After identifying the big roadblocks, which were usually client-side-scripting needs surrounding forms, I began using a library I created to simplify some of the common scripting tasks, such as form validation. Later, I was excited to see other developers tackling the same problem.
But what I needed was a library that could be extended in terms not just of validation, but of form and element access as well.
I'm prototyping here, not building universal access, so this design is only supported on later builds of Mozilla and IE 6.0. (It might work for earlier versions of IE and even Opera, but I haven't tested this on either.)
When using a system like Namaste, I've had better design feedback from my supervisors, clients, and colleagues because my prototypes feel less barebones than others that I previously drafted. (The developer: "Oh, later that's gonna check whether this is a valid UPC code before submitting...just use your imagination.")
To show what I mean, I've drafted two small forms I've created as examples for this sort of prototyping.
1. The Simple Combo form
In the Simple Combo example, I've created a simple form with a couple of drop-downs, a few radio buttons, a text field, and a textarea. Clicking the submit button activates form validation and outputs errors to a <div> I'm floating within the form. Pretty straightforward, but the payoff in all of the Namaste forms is that applying the validation is as easy as calling a single re-usable method. For example, the drop down accepts numbers only, so I call Namaste.setNumbersOnlyById("id_of_form_field") where id_of_form_field in this case is the ID attribute of the form element.
2. The Grid Form
In the Grid example, I've created a simple grid composed entirely of <textarea>s that is based on my Richer Table experiment. As in the Simple Combo example, clicking the submit button activates form validation and outputs errors to a <div> floating within the form. Here, though, I'm not using any of my pre-defined validation methods and have instead overwritten the validate() function with a high level, form-specific script. Not having to re-write form submission code here allows me to be really creative with the idea of how a form can look. (Just click in one of those cells and press Enter to see what I mean. Press Tab to escape.)
Under the Hood
While inheritance worked as a model, I found myself constantly calling the methods of a property as object. Why would I have an object as a property? Mainly, to encapsulate tasks that either were complex or seemed like they could become so later. But calling the property first and then the method seemed counter-intuitive so I tightened the syntax of Namaste calls by using a bunch of delegation at higher levels. I wonder if this qualifies as an anti-pattern or not. Hmm. I sure do like the tighter syntax; it's a lot easier to remember during implementation.
Though slightly awkward in the case of associative arrays, applying OOP design helped here. Now, as I draft application-or-business level logic for forms interaction, I can add scriptlets as either methods to base objects or as subclasses to Namaste that I extend through inheritance and prototyping. It cuts down on my initial coding time and I can re-use these classes for a variety of projects. Namaste objects even behave somewhat polymorphically, as other libraries don't care whether it's a calendar object or an email form object so long as it has, for example, a make() or a setDisabledById() method. With re-use of libraries I'm creating, my prototypes are getting richer and more interesting.
A reliance on OOP works well within Namaste, in part, because I'm creating DOM elements from scratch which opens the opportunity to establish certain elements as rich virtual objects. But there's a catch (always, developer) as there are differences in browser implementations of element creation. Here's two gotchas I encountered in IE:
1. Creating RADIO buttons.
For example, there's real trouble waiting in the wings for those attempting to generate radio buttons using the createElement() method in Internet Explorer. You can't set the name attribute after creating an INPUT with a type of "radio" and actually have the radio buttons behave as expected. They instead behave as a static-created radio button would if the name attribute was empty. (Meaning: the button can gain focus but will not actually check.) FAQTS details the solution which is to send the complete HTML for the starting INPUT tag and name attribute as an argument to createElement. This would look something like document.createElement("<input name='radio'>");
IE handles buttons with a type of "submit" and the onsubmit handler for their forms differently than Gecko. In order to have the onSubmit form handler called, an INPUT with a type of "submit" (or "image", I suspect) needs to be actually clicked. So I had to resort to creating one for each form in IE and setting the onclick of the BUTTON to call the click() method of the hidden <input type="submit"> element.
What? I totally have time for another project. I waste a lot of time, you know, blinking and stuff.