AJAX - a run-through for the rest of us
Dualism in Design
The classic clash: one very small version of yourself sits on your right shoulder, whispering design ideas; another very small version on the other shoulder, whispering technical constraints.
A few thousand years ago in Egypt, someone said, "I want my tomb to be a stupidly big square-based pyramid. Made of stone. In the desert. Yes, I know there's no stone in the desert."
Today, I want a clean site design, constructed in XHTML Strict, pure CSS, perhaps a bit of gracefully failing Javascript manipulating the HTML DOM for fanciness.
In the future, I want to be able to have my site do whatever I think of. Dragging page elements around the screen? Using what information feeds I want, and have them appear in a standard format? Dragging difficult words to a dictionary area? Email notifications popping up on my home page when I receive a new email? The ancient Egyptians threw slaves at their problem. I can write websites which satisfy my technical aesthetics. So why not the future stuff now, too?
Put your hands down
You have probably already spotted a solution. AJAX is here, and it is pretty. It lets us drag stuff (to predefined locations, usually) and pull in whatever feeds the page writer decides on. We can even look up postcodes in the UK; why not use AJAX to satisfy your needs?
Well, there is no why not. Except that most examples of this stuff are being done by technical people. An emphasis of construction over presentation. Worse still, an emphasis of technical proof of concepts over designed solutions to problems which AJAX can solve.
So, here is my effort. Perhaps to get the ball rolling a bit. I leave the incredible presentation to others, as I am not so gifted in that area. But I can see some possibilities, and I will briefly describe this one. I mentioned earlier the ability to drag difficult words into a dictionary area, to reveal a definition. It's a reasonably elegant solution to the problem of deciding which words to include in a glossary: let the user choose. Let's do it in AJAX. Easily.
The Design
Let's set down what we want from this. Some brainstormed ideas:
- Dictionary's function is obvious to the user.
- Degrades well with a non-Javascript browser.
- Does not require changes to the source text.
- Easily extended with new words and definitions.
- Manageable: a way of removing on-page definitions which are no longer needed.
Random
One arbitrary design decision: I will use PHP. Another: I will make a basic page which will include the source text. A third: I will make it reasonably pretty.
The PHP
I want this to parse the source text, and add markup to it. This markup will be used in conjunction with AJAX later. So in our main page, let's start it with this (at the very top, even before the DOCTYPE declaration):
Two variables here, for easy changing later.
$raw_text_file_path_from_index is exactly that: the path to the
content we are going to provide definitions for.
$wordbin_dir_path_from_index is the path to the place where the
words and definitions are kept. dbd/preparser.php is where we
dump the rest of the code. dbd is short for Definition Bin Demonstration.
Let's look at that:
This requires brief explanation. To keep things simple (and good), each
defined word will be in a directory called wordbin/; it will be
in an eponymous file, with the definition as the only text. E.g. a file called
CSS with its contents as This is the definition for
CSS. I hope more thought will go into the definition than that. Anyway.
The PHP starts by reading each file name within the wordbin/
directory into the $wordlist array. It then reads the source text
(to have definitions added to) into a variable called $rawtext.
Finally it does a clever bit of regular expression stuff, where it surrounds
each definable word (e.g. CSS) with this markup:
That's that.
The AJAX
That last bit looked decidedly Javascripty. The more discerning may even
know where it comes from. It is time to mention script.aculo.us. Get their incredible framework. I
will pop it in a directory called dbd/js. I will also put these
lines into the head of my document:
Built into this is the Draggable element. The PHP registers an element to
be draggable. And that's the start. CSS it up a bit so that elements with
class="dragme" look a bit different, so people know to drag them,
and you should be dragging any words which have definition files (and appear
in your source text) round your page.
Now to create the thing to drag them into. I made a div with
id="bin" and styled it a bit to give it a fixed width, and a
min-height (* html { height: whatever; } for IE). At
the end of the HTML document (it must appear after this div) I include some of
my own Javascript:
Inside this file I register #bin to have stuff dropped onto it:
This adds #bin as a Droppable: you can drop things on it. It
is set to only accept elements of class "dragme" which is what we
want. When an element is dropped on it, a few things happen. Some error
checking: if the definition for that word is already present, we remove the
existing definition and replace it. This serves solely to bring the definition
to the top of the list.
Secondly, an AJAX (finally!) request is fired off, to the other bit of PHP,
at dbd/textadder.php. It's asynchronous - the website does not
block until it receives a response - and is POSTed the parameter
"word=CSS", to continue our example of "CSS" as the
word being defined. If it works, the function handlerFunc (which
we have not yet defined) is called. Let's get the remaining PHP out of the way
before we get onto that. This is dbd/textadder.php:
This grabs the wordname (we will stick with "CSS"), looks it
up in wordlist/CSS, and inserts it into some code, which is
returned looking like this:
This gives us some nice text which can be referred to in CSS via its class and id. It is also registered as Draggable. Why do we want to drag a definition? Well, my final design requirement was to be able to remove definitions from the dictionary. More on this later.
Back to the main source code, and we need to have another function in
dbd/js/custom-dbd.js:
This adds the returned text from textadder.php to the top of
the element bin. Great.
Almost there. Now, we will make another element with
id="remove". This will be what definitions can be dragged onto to
be removed. Style as appropriate, and I added this into my
dbd/js/custom-dbd.js:
This only accepts elements dragged from the definition bin, and does some cute animation with the remove element when it's dropped onto. It also (obviously) removes the definition div from the definition bin.
A couple of final functions, regarding the cute animation. Put them in
dbd/js/custom-dbd.js. Don't worry too much about them, although
you will have to tweak them if you use the effects. They counter what happens
when an element is dropped onto the remove element during an animation:
That's it. Take a look. The icons were ten minutes (you can tell) in Inkscape. Want to add a word definition? Just add one file and refresh the page in your browser. Simple. Want it to degrade a bit better? Make Javascript create the Definition Bin, so non-JS users never get confused. This is just a framework for bigger things. Web 2.0 hype aside, I think we can go further with the web in making web pages feel more like applications, and do what the user wants. We can make things that satisfy the designer and the engineer in us. This was just a simple example from a young guy with relatively little experience; no doubt you can create something far more useful and lasting. I'd love to see it happen.
Article last modified: Thursday 09 March 2006