How to Bluff Your Way in DOM Scripting

A presentation I gave with Aaron Gustafson at South By Southwest 2006.

Jeremy Keith: Thank you all very much for coming today to learn how to bluff your way in DOM Scripting.

The first thing you need to know when you want to bluff your way in DOM Scripting is what DOM stands for — Document Object Model — because we’ll be using that word a lot today.

Allow me to introduce myself. My name is Jeremy Keith. I’m from Ireland, travelled all the way here to talk to you guys. I wrote a book about DOM Scripting, and we’ll be giving away this book to you lucky people. If you have questions later on, we’re going to be opening be opening up the floor to questions. If you ask a good question, you get a book. There’ll be a choice of books as well.

So, the structure of today: Basically, what I talk about in my book is DOM Scripting and how to do it. Reading a book is going to take time, so we want to condense it down. And you don’t really want to “learn” how to do DOM Scripting; you just want to bluff it. So this is going to be the easy way to do DOM Scripting.

I was here last year with Andy Budd, and we did “How to Bluff Your Way in CSS”, because that was the cool technology of the time. CSS: Everyone needed to know how to bluff their way in CSS. And now the cool technology is DOM Scripting. So DOM Scripting is the new CSS, really, and you’ve got to learn how to bluff your way in the new technology.

To help me with my task in bluffing DOM Scripting, I have my friend Aaron Gustafson, and he is a coder, writer, and teacher. He’s a coder with Easy Designs, his design firm. He’s a writer in print; he just released the third edition of Web Design in a Nutshell, from O’Reilly. There’s two chapters in there from him: A chapter on JavaScript and a chapter on the DOM and AJAX.

He also writes online. He’s an editor at A List Apart. He’s got quite a few articles up there. And he’s a contributing writer to Digital Web. So, you’ve probably come across some of his writing before. And he is a teacher in the real world, so he is no stranger to public speaking. He’s been on the road, he’s been travelling all over the country, speaking with the likes of Molly Holzschlag and Andy Clarke — that web-design super-hero. This is nothing new to him. And he’s going to help me by explaining exactly what this DOM stuff is. So I’m going to hand it over to Aaron.

Aaron Gustafson: Thank you very much, Jeremy.

Let me find the little remote here…

Basically, in order to really be able to bluff your way through DOM Scripting, you have to know what DOM Scripting is and what it isn’t. Often, in the past, we’ve had people talking about DHTML and DHTML, as how you make your pages more usable and more interactive and spice them up a lot. Well, DHTML was created by the original bluffers, a bunch of marking wonks, basically, who had no idea what exactly the technologies were. Essentially, it was Javascript, CSS, and HTML.

The problem with DHTML is that a lot of people thought it was a language unto itself, that you had to know this DHTML thing and it was something completely separate from anything else, so there was that confusion. But it also had a lot of baggage that it carried with it, so you had a lot of browser-specific code. You had a lot of code forking, which if anyone knows about code forking, you basically end up forking yourself and your application. You also had a lot of people just doing stuff for screen only. As we’re finding out, it’s not just about the computer screen: It’s about mobile devices, it’s about print; etc…

There’s a lot that we can do to improve the usability, and the accessibility even, of our pages and our websites, using DOM Scripting. And then it also worked with non-standard markup. And now, hopefully, all of you have moved over to web standards. I know South by Southwest has a very large contingent of web standards supporters.

DOM Scripting is the best way to start approaching the addition of interactivity and the enhancement of your pages with JavaScript. Along the lines of the code forking: DHTML was a maintenance nightmare: If a new browser version came out, all of a sudden, you had to add browser detection for that, etc. It just spiralled out of control, it was way too much trouble.

A lot of us decided that it was too much trouble to be worth anything. So I decided, a long time ago, that I really hated JavaScript and wanted nothing to do with it. Then, all of a sudden, we started having web standards, and we started working with standardized document types, and started to be able to harness the power of the DOM. That was when I started getting interested in JavaScript again, and that’s what brought me here today.

So DOM Scripting is essentially the web-standards approach to manipulating documents: You have a document, and then you have a language that you’re using to manipulate it. In our case, we’re going to be talking about JavaScript, but DOM Scripting could really be applied to anything: You could be using PHP or Ruby to manipulate XML documents using the DOM.

The DOM is a standardized API for accessing your documents. It only requires a scripting language and valid markup. It’s also browser-independent: We’re not testing for browser manufacturers, we’re not testing for version numbers, anything like that. It embraces the concepts of both graceful degradation, which is becoming somewhat “passé” in terms of the web-standards world, in favour of progressive enhancement. What we’re doing is, we’re offering a more hi-fi experience to people who have the capacity to take that in and to use it. As I mentioned, it just makes sense… DOM Scripting is something that makes a lot more sense: It’s very easy to understand, and it’s something that’s very powerful and very easy to harness the power of.

Basically, it starts with a document. Here, we have just a simple, straightforward XHTML document: It’s got a head, a body. Inside the body, we’ve got a heading, level one (H1); we’ve got a paragraph, and an unordered list, with three list items within it.

Now, we have a lot of things that we can do with that, but first, we need to know how we can address that, how the DOM views the document.

Well, it’s kind of like a site map, or almost like a page map, or a tree; you could think of it that way. And this is going to be treetops view of how the DOM sees the document. In terms of the DOM, we talk about each of these little distinct pieces as nodes. So, at the top, we’ve got the HTML, which is the root element; it is the parent element of all the other elements that are on the page. And then we’ve got the head and the body. And then, within each of them, we have children; and those children are all siblings of one another. All of this stuff should make pretty good sense to you if you’re familiar a lot with CSS selectors; there’s a lot of similarity there. But we also have different node types apart from element nodes, which is what these are. If we dig deeper into the paragraph, we have a paragraph that has text in it; it says “This is a paragraph of text with a link”, and then a period. So, if we were to break that down into nodes, we’d have the text node “This is a paragraph of text with a” , and then we’d have an anchor element and that’s an anchor-element node , and then, within that, we’d have an attribute note. And that attribute node is the HREF, which contains the URL for the link.

Then, we have the text node within that anchor, which is the text “link”. And then we have another text node, which is a period. So this is a breakdown of how that works. And you have a lot of control over how you can manipulate your document: both reading from, and writing to, your document. And I’m going to pass it over to Jeremy to talk about the similarities between the DOM and working with CSS.

Jeremy Keith: Yeah, because, if you look at what this representation is: it’s just a way of looking at a page. And there are many ways of looking at the same page, depending on your mindset. If you’re a designer and you look at a web page, you see it in terms of colors and fonts and stuff; you see it in a certain way. Using CSS, you also view the page in a certain way; you start thinking about “What’s the header?”, “What’s the footer?”, “Where’s the sidebar?”

All that the DOM is is another way of looking at a page. But it’s not all that dissimilar to CSS. So don’t worry that DOM Scripting is going to be this whole new technology: you can use a lot of the skill you already have from CSS. I’m assuming you guys are pretty savvy with CSS; you could at least bluff your way in CSS. Could I get a show of hands of people who feel pretty comfortable with CSS. All right; all right, good. And you know your markup, right? Who’s good with markup here? O.K., I would hope so. So, you can recycle your CSS knowledge, because the DOM isn’t that different.

I’m going to step back and look at CSS. And one of these things about CSS is that it combines getters and setters. Those are the best terms I could think of. You need to get at some parts of the document, and then set the styles on those parts of the document. And the syntax for getting and setting in CSS is you have your getter you open up some curly braces , and then you have your setter or setters. An example would be, if you wanted to style all the paragraph elements in a document, you’d first have to get at all the paragraphs elements.

Well, you’d use the element selector: You would just write P, for paragraph element, open up your curly braces and then you set the styles you want to change. You might set the color to red. Another example would be using the ID selector. You need to get at an element with a certain ID, the ID selector in CSS begins with that hash, and then you have the name, the ID. So, hash, footer, and then you open up your curly braces, and you set the style you want to set, you might set the font size to be smaller. That’s basically the syntax of CSS: You have different kinds of selectors. Whenever you think “selector”, just think “getter”; that’s your getter. And, then, within the curly braces, of course, there’s a whole world of things you can set. But that’s what it boils down to: getting and setting, getting parts of the document; setting styles for that part.

The DOM is a bit different, in that it has separate getters and setters. First, you must get at the element or elements that you want to change; and, then, you set whatever it is that you want to set. So it takes a little bit longer than CSS; it’s a little bit more verbose; the syntax is a bit longer. What you’ll be using is methods. Whenever you need to get at something or set something, you’ll be using methods.

This term, “method.”: if anybody’s familiar with object-oriented programming, you’ll know what a method is. But who’s familiar with object-oriented programming? That’s complicated stuff. It’s easy to bluff; it’s really easy to bluff methods (and “properties” is the other one). And, if you can start talking about methods and properties, you sound like a real programmer. But it’s really easy, because a method is just a function, and a property is just a variable; it’s as simple as that.

The only difference between functions and methods, or between variables and properties, is that, in the case of methods and properties, they always belong to a specific object. In the case of the document-object model, that’s usually the document object. But you can spot the difference between a method and a function, because a method will always be preceded by something-dot. So, if you have “document.something” and then a set of parentheses, that’s a method. If it were just “something” and then parentheses, it would be a function. So that’s an easy way of spotting when something is a method or a property, rather than a function or a variable.

How do you spot the difference between methods and properties? If it’s got parentheses, it’s a method, as simple as that. If it doesn’t, it’s a property. And you could be doing mental substitution at that stage: Every time I say “methods”, you say “function”; every time I say “property”, it’s just a variable.

So here’s the syntax. You use a getter method on the document object. So it’s some method of the document object. And you usually assign it to a variable, so you can access it much more easily later. And then you can set something on that element. So, using the variable shorthand you’ve already got: use a setter method.

I’ll give you some examples. There are three main getters that we use in DOM Scripting. You have “getElementById” and that does pretty much what it says on the tin; it gets an element on the basis of the ID you pass to it. So “document.getElementById”. When you say anything dot, you know that it’s a method. So you pass it a string; you pass it the ID of the element you want to get to. That might be “header” or “footer” or whatever. Then you’ve got “getElementsByTagName”, “document.getElementsByTagName”, and you pass that the name of the tag;, so that’ll be P or H1, IMG, whatever. That will bring you back all the elements with that tag name.

Now, “getAttribute” is useful; With that, you can get at a specific attribute in an element. That one is a little different from the others, in that you don’t apply that to the whole document: you need to already have an element; you need to have already got an element, and then you can get the attribute of that element, again by just passing it a string, which is the name of the attribute, “title” or “alt” or “src” or whatever.

When you’re using the getters, you’ll usually want to save yourself some time, and you’ll use variables to store these values. So you might say, using the “var” keyword in Javascript: “var myElement = document.getElementById”… whatever; content, footer, whatever you’ve got in your document. You can do the same with “getElementsByTagName”; but, whereas “getElementbyId” will return a single element (which you can then set things on), “getElementsByTagName” returns a collection of elements. Now, this collection is not really an array; it plays one on TV: You can treat it pretty much like an array. You can loop through it; it’s got a length, and that’ll tell you how many elements are in it. So it’s very handy that it works much like an array.

So those are the main getters for getting at elements within the document. And, once you’ve got at an element, you can then get at the attributes within that element, using “getAttribute”.

Let’s say I’ve already assigned “myElement”, as a variable, to be “document.GetElementById”, followed by ID “content”. Well, now, I can simply say “myElement.getAttribute”… whatever; “title”, well, that will give me the value of the title, and I can assign that to a variable, like “myString”.

The best way to describe this is to compare the syntax of three different languages: and I’m going to compare my native language (English), CSS (not really a language, but it’s got a syntax), and the DOM. You’ll have three different vocabularies, three different ways of saying the same thing.

In English, I might say “Get the element with the ID ‘content’.” My job is to translate that into whichever technology I’m using. If I were using CSS, I would use the ID selector: so, #content, and then { }, where I can set whatever I need to set. Well, the DOM equivalent to that is document.GetElementById(“content”).

So those three things are completely equivalent; they’re all saying exactly the same thing: they’re just using different languages; they’re using different vocabularies. When you want to bluff your way in DOM Scripting, you just need to know the vocabulary, you just need to know things like “getElementById”, “getElementsByTagName”, “getAttribute”. If you don’t know how to use them, just know how to say the words, and then you’ll impress people with your knowledge.

Here’s another language comparison. In English, I might say “Get all the paragraphs in a document.” I want to translate that into CSS. Easily done, using the element selector: “p”. That’s it, I’ve got all the paragraphs in the document. With the DOM, it’s a bit more verbose: It’s document.getElementsByTagName(“p”). Well, if you look at this, the DOM is the one that looks closer to English. CSS is nice and short; it’s curt and it’s brief. But the DOM is very readable. It’s a bit more verbose, but it makes a lot of sense to the human eye.

Here’s a much more complex comparison.: “Get all the paragraphs within the element with the ID ‘content’.” Now, I need to do more than one getter at a time. And, of course, that’s possible with CSS, because, if I go #content p { }, that gets all the paragraph elements, but only the paragraph elements that are within the element with the ID “content”. Right? Well, you can do this sort of chaining together of getters in the DOM as well. document.getElementById(“content”).getElementsByTagName(“p”). It’s starting to get a little long; it’s starting to get lengthy. It’s still very, very readable; you can look at that and see what’s going on. I’m getting all the paragraphs within the element with the ID “content”.

So, really, it’s just a matter of translation; and, once you know your CSS, once you know things like element selectors and ID selectors, then you just need to know the DOM equivalent. You need to know how to say the same thing, but using the DOM.

The setters… This is where it starts to get interesting: You can get all the elements you want, but you need to be able to do something with them. With the DOM, the most powerful thing you can do is that you can actually create nodes and then insert those created nodes into your document. You’re creating life, creating new markup. Even after the document has loaded into the browser, you can mess with it. And this is new territory. There are more setters than this: You can clone nodes, you can destroy nodes. There’s unlimited power.

Aaron Gustafson: And Bush can’t say anything about it.

Jeremy Keith: I’m going to look at creating, and then inserting, nodes into an existing document.

Of course, we’ve been able to do this for a while, right? Creating markup using Javascript, that’s nothing new. We were able to do that back in the nineties. Yeah, we could, but it was pretty ugly.

document.write(). You’ll be able to recognize that as the “write” method of the “document” object. It’s nasty, you just put a whole chunk of markup in between those parentheses, and that’ll get dumped into the page, and there’s no control. It’s just nasty, it’s nasty.

innerHTML is kind of the same. You pass it a big string of markup, it’ll just vomit that markup into some part of the page. It must be said that innerHTML is very well supported, which is surprising because it’s completely proprietary: It’s not in any standard. Completely proprietary, but very well supported across browsers. But it’s like using a sledge hammer to crack a walnut. Now, sometimes you do want a sledge hammer, sometimes, you really do just want to dump a whole bunch of stuff into the page. Usually, you want a bit more precision. And, where innerHTML is a sledge hammer, the DOM setters are like a scalpel, very finely tuned.

Setters for creating nodes: I’ve got createElement(), the createElement method of the document object: document.createElement… and then some string, and that’ll be the name of the element (P, H1, IMG, whatever).

Again, that does exactly what it says on the tin: it creates an element. CreateTextNode(): that creates a text node. Actually, the naming here is a little bit confusing, because it’s createElement, not createElementNode, but it’s createTextNode, not createText. But don’t worry about it: you don’t need to memorize this stuff; you just look it up.

The equivalent to getAttribute is setAttribute. So, once you’ve already got at some element, you can set the attribute of that element. You’re passing it two things: the name of the attribute that you want to set; and the value that you want to give it. So, I could say, someElement.setAttribute(“title”, “this is my title”).

So how do you use the setters here for creating nodes? Well, when you use document.createElement — and I might say document.createElement(“p”) — I must assign it to a variable.

When I showed you earlier, using the getters like getElementById and getElementByTagName, I used variables, but that was just to make my own life easier, just so I didn’t have to write out document.getElementById every time I wanted to refer to it. When you’re creating notes, you actually have to use a variable, because, when you create the element, you’ve created it but it isn’t in your document yet. So, later on, when you want to go back and say, “O.K. That element I created: Now, I want to put it in my document.” You have to have some sort of label, some way of talking to that element. And, if you haven’t assigned a variable to that, there’s no way you can get it: It’s created, it’s in Javascript limbo, but it never gets into your document. So you must use a variable in this case.

And the same with the text nodes: you create your text node, store that new node in a variable, like myTextNode.

And, when you’re setting an attribute, you must already have an element to set the attribute on. If I’ve already used the variable named myElementNode for some element I created, now I can set the attribute on that node even though it’s not in the document yet.

So here’s the thing: We’ve created markup: great. But that markup isn’t in our document. Our document is sitting there, these newly created elements are just floating about in Javascript limbo. We have to get them into the document, and we have setters for doing that.

There’s quite a few setters; I’m going to just talk about two. We’ve got appendChild. We looked at the document tree earlier, where you could see it as a tree of nodes. Well, you can think of that as a family tree. At any point, you can insert a child of some element. So I say whatever element, in a document I’ve already got at, appendChild, and then pass it the variable name that I chose for that newly created element.

I’ve just created a paragraph or something… Well, now, I can append that paragraph to some element in the document, and that will just put it as the last child in that element.

Another way of inserting newly created nodes into a document is by using insertBefore. And that gets pretty complicated. You’ve got the parent of both elements, insertBefore, the new node you just created, then the target node before, which you want inserted… It’s too complicated, don’t bother memorizing this stuff: This is why we have Google, this is why we look stuff up. I can’t remember what the syntax for this stuff is. That’s why O’Reilly write books: so we don’t have to memorize this kind of stuff.

Let me give you an example of creating markup in a usable way, hopefully.

I’m going to write a little script. Here’s my task: I want to make use of the cite attribute in blockquotes. Are you all familiar with blockquotes? You use blockquotes? Hopefully for marking up quoted text and not just for indenting text. Are you familiar with the cite attribute? O.K., quite a few of you.

A lot of people aren’t familiar with the cite attribute, which I’ve used here. I’ve used a blockquote, and I’ve got a cite attribute, which contains a URL. But there’s a good reason why a lot of people aren’t familiar with the cite attribute, and that’s because of the default browser behaviour.

The default browser behaviour is to do bugger all: it just ignores it. Semantically, it’s wonderful. Semantically, I can associate a blockquote with an originating URL. Great stuff, great semantics….

In practice, it’s absolutely useless.

So what I’m going to do is I’m going to change the default browser behaviour. I’m not happy with what the browser does by default. And this is exactly what you do in CSS. With CSS, you change the default browser styling; If you don’t apply a stylesheet to a document, it’s not that that document doesn’t have any styles, it just has the default browser styles — a subtle distinction, which Joe Clarke will always remind you of. And what you do with CSS is that you change the default browser styles to whatever that makes you happier. With Javascript, you can change the default browser behaviour.

So what I’ve got to do is I’ve got to sit down and think about exactly what it is that I want to do, step by step. In effect, what I’m going to do is I’m going to write a script but not a Javascript, not some programming language. I’m going to write a script in English; say what it is that I want to do.

I start putting my thoughts together. I want to find all the blockquotes in a document. I don’t want to do this on just any one blockquote: on any document that has blockquotes, I want to apply this. I’m going to find all those blockquotes, and I’m going to start looping through each and every one. And, for each and every one, I want to get the value of the cite attribute.

If that value exists — if the cite attribute is being used — then this is what I’m going to do: I’m going to create a new link element. I’m going to set the HREF value of that newly created link element and that’ll be the same value that I grabbed from the cite attribute, the blockquote.

I’m also going to create a text node; I’m going to put the word “source” in there, or it could be “link to original URL”, whatever, I’m just going to put the word “source” in there.

Now, I want to take that text node that I just created, and I’m going to put it into the link I just created. The link has the text node inside it and has the HREF as well, it’s all ready to go. My final step is to put it into the blockquote.

So I’ve written my script, it just happens to be in English. The only problem then is to translate it into Javascript, using DOM vocabulary.

You start looking at what you’ve written in English, and you think about what will be the right method to use for each step, and you translate.

Every time you see “find all the somethings in a document”, chances are that you need getElementsByTagName().

If I want to get the value of any attribute — in this case, the cite attribute — well, I’m going to use getAttribute().

To create a new link node, createElement().

To set the HREF attribute of that link node, setAttribute().

Create a text node; I’ll createTextNode().

And then I’m going to put the text into the link, using appendChild(), and put the link, with the text inside it, into the document, also using appendChild().

And there it is in Javascript; I’ve highlighted the various methods. So I’m assigning a variable there, “quotes”, to hold all the blockquotes in the document so that I don’t have to type out document.getElementByTagName(“blockquote”) every time; I can just write “quotes”. I start looping through it in a for loop. I get the value of the cite attribute: I’m also putting that into a variable; I’ll call it “source”. If that exists, then I do this: I create a link, and now I must use a variable, not just for convenience. I use a variable “link” here to store a newly created element. I set the HREF value of that newly created link node. I also create a text node. And I put the text node inside the link. And I put that link inside the blockquote.

In actual fact, I expanded the code: I went a bit further, because I couldn’t just put a link inside the blockquote, it had to be inside a block-level element in order to be valid markup. So I also created a paragraph and put the link inside the paragraph. But that was easy: I just createElement(“p”). I also wanted to set a class name, so I changed the class of the paragraph there to attribution, and that means that I can now style that paragraph, using CSS. And then I put the link inside the paragraph, and I put that paragraph inside the blockquote.

And, then, if you view the finished product, it’s exactly the same, but, now there’s a link that leads off to the source of the blockquote. If you can View Source, then it won’t look any different; the markup won’t appear in View Source.

In Firefox, you can use View Rendered Source; you can actually see the updated DOM. But, basically, all the changes I made were made after the document was already loaded into the browser. So, I’ve changed the default browser behaviour to do something useful.

So I’ve written my script, and I’ve got my markup. But the question is “How do I put the two together?”, because there’s a right way and a wrong way of getting Javascript into your document. Aaron’s going to tell us about the right way.

Aaron Gustafson: All right. Man, those chairs are comfy. I was tired beforehand, but, now, I just want to go to sleep.

All right, so, a lot of what you’ll hear about — and this is a key phrase that you should start working into your bluffing conversations in the hallway — is “unobtrusive Javascript”. You’ll hear this time and time again.

How many people here have used inline event handlers, like onmouseover? Well, we’ve all done it. How many have just had Dreamweaver do it? O.K. More of you than that.

O.K., so, unobtrusive Javascript.

In a nutshell, the way I think of it, it’s the golden rule, “Do on to others as you would have them do on to you.”

Conversationally, it’s “Don’t have Javascript? That’s fine, take a look at the content, it’s fully available to you.” “You have Javascript? Great, let me try and improve your experience.” “Oh, you don’t support the method I want to use? Ok, I’ll go away.”

You’re not getting in the way of the user being able to use your page to the best of their ability, you’re basically just enhancing it if you can, or, if you can’t, back off. It’s kind of the… Molly talks a lot about having to be a control freak and a Zen master: this is the Zen master part. You’re trying to improve somebody’s experience, but you have to be Zen about it, if they are not able to, on their mobile device or something like that, be able to run Javascript, then you just have to back off and make sure that the page is still usable to them.

So, how do we accomplish unobtrusive Javascript? Well, with good planning is the place to start. You have to think about what exactly is your script’s purpose, what exactly is it trying to accomplish. How is the script interacting with the page, how is it being used? And finally, is your page usable without it?

How many of you have been on a site, that if you dud not have Javascript, would not run at all? Has anybody here ever used Excite.com? Has anyone ever viewed source on Excite.com? It is entirely Javascript. So actually, don’t get much of anything if you do… That’s crazy too, because it’s all nested tables, could you imagine trying to use all these DOM methods to do nested tables? We don’t want to do that. We don’t want to have navigation that is only available if you have Javascript. We want to make sure that everything is completely accessible to the user, and available to them no matter what device or method of getting to the content they have.

The next step is in the implementation phase. Now, you need to think about which methods you’re going to be using, and you need to test for support of those methods.

This is how we get around browser detection: We actually use what we call object detection or method detection, depending on what you’re using. In the case of Jeremy’s script, he was looking for, let’s say all the paragraphs within a node with an id of content. Well, if that node with an ID of content doesn’t exist, then the script is going to throw an error if it’s looking for that. We don’t want to throw Javascript errors on people’s browsers because that’s just not nice. So what we do is we test to make sure that that ID’d element actually exists within the document before we actually run our script. That’s object detection.

Similarly we want to check and see if document.getElementById() is even supported. If it’s not supported, then we go ahead and the script fails silently. Very simple way to make your script even more user friendly, let’s say.

The next thing that you can do, and here’s another great phrase that you can drop in: object literal. How many people have heard that term before? It’s a way of doing object oriented programming that allows you to keep your methods and properties etc. Kind of compartmentalized and separated from the rest of the scripting that might be going on at the site. So that’s a good phrase to drop in because it’s the new way to code. The old way to code objects is really becoming passé. So go with object literal.

Jeremy Keith: Object notation is another good phrase to throw in there.

Aaron Gustafson: Yes, object notation, also very good. These will all make you sound very very smart, and we all want to sound smart.

You also want to keep it generic, and what I mean by this is that you want to be able to use it in as many situations as possible. Who likes having to rewrite the same thing over and over again for different sites? In some cases you might be wanting to pull all of the paragraphs or all of the block quotes out of the content, or out of an element that ID’d with content, another might be ID’d main or something like that, so you want to be able to keep the script generic, so you can pass it the id of the element that you want to select stuff from, or that you want to dump stuff to. So this enables us to kind of keep a little separation between the actual pages that we’re using and the scripting, so that we can use it in multiple sites, use it in multiple situations, have different layouts etc.

Another thing we want to get away from is using inline event handlers. You can assign events and stuff like that which we’re not really going to get into, because it’s a little bit beyond the scope of the time that we have here. Using inline event handlers is generally considered bad, you can keep all of that out, external, to an external Javascript file, and then apply the event handlers to the specific elements once you’ve accessed them being at the DOM. So that’s another area we want to stick away from.

We’ll walk you through a simple example, well, relatively simple example of something that I did, which is dealing with selects.

How many people here have ever tried to style a select and failed miserably? How many people hate that? All right, yeah.

It’s a miserable thing, and no browser really allows to do it. So I thought, okay, how can we make a select that is actually stylable? Well, we have so many of these wonderful scripts out there and CSS approaches that allow us to create kind of faux selects using unordered lists, so why not use the DOM to allow us to replace a select or hide a select and replace it with an unordered list that we can then style however we want.

Starting with a clean functional document, as in this one, we have a form with a field set, and we’ve got a couple of text inputs, and then we’ve got out select etc. We’re going to take that and we’re going to solve the problem. And here, we have a fully styled select, and when we click on it, it’s actually changing the value that are stored in the form, so when the form is submitted, we’re actually getting that value in the other end. But we’re able to make it much more attractive. Not in this case, but you can make it much more attractive.

[audience laughter]

Aaron Gustafson: So, how do we do that? In a nutshell, we collect all the selects that are on the page, and then for each of those selects we build an unordered list that’s going to mirror it. So every option within the select is going to have a corresponding list item. Then of course we need to make sure that we know which one is highlighted in the select, which one is currently selected, so we need to take that and find a way of implementing that within the list. So, might be apply a class to a list item, or it might be making the text within the list item bold or something like that.

Then, we need to assign event handlers so that we can make it behave just like the drop-down does, the select does. So, expansion and collapsing of the select and then routing the selection, whichever list item you’re clicking on, back to the original select so that that is stored and can be sent with the form when it’s submitted. And then for accessibility, once we’ve focused on the select in question, we need to able to then track keypress events so that if somebody is heading up or down or page up or page down etc., that is also updating the selected option within the hidden select. And then we go to the process of actually hiding the select and showing the unordered list.

Once you start breaking it down and thinking about it in a logical way, it begins to make sense, it all sort of comes together. Then it’s all just about figuring out the code that you need to do that.

Couple other quick examples here. Email obfuscation is something that has been talked about a lot, and there are numerous methods of doing that because everyone hates email harvesters and getting lots of penis email.

[audience laughter]

Aaron Gustafson: So if you open the very very simple way of doing this, because a lot of them just seemed overly complex. So I decided that I was going to write my email address in natural language, so natural English for me, “aaron [at] easy [-] designs [.] net”. Very simple, very readable, people get the picture. So when people have Javascript enabled though, I want to be able to show them a mailto link. So in that particular case, and for those of you just… I’ll highlight it here so you can actually see it, right there for those in the nosebleed seats in the back there.

When you have Javascript enabled, I’ve made it into a mailto link. Essentially all I’ve done is I’ve gone through the document and I’ve collected any emphasis elements, and you might decide to class them, email or something like that, so that you have another hook so you can tell specifically that that’s what they are. In my case I think I’m actually checking for the existence of “at” in square brackets, because that will always exist in an email address. And then it’s collecting the text note from within that emphasis element, and using regular expressions, it basically retriggers the content and builds a mailto link, and then it swaps out that emphasis element for a mailto link.

Very simple, very straightforward, I think it’s like eight lines of code. But shows the power of DOM Scripting.

Another example: Some of you may have seen it in A List Apart, this is where I originally debuted this particular strategy. How many of you here remember Eric Meyer’s (I consider) seminal piece on print style sheets and putting the link in parentheses after the link? I thought isn’t that great, that’s like the best thing.

Well, I ran into a problem, because my wife, who’s sitting in the audience, was proofreading one of my articles; and I tend to go a little link crazy and I’m linking everything, and it’s just making the text really illegible, because there’s all of these parentheses with URLs, some of them fairly long. She couldn’t read any of it.

So she started yelling at me and I was like “aaaaggh O.K., I’ll figure out something”.

I decided that I was going to make a script that went through and collected all of those links, and in addition to those, throw in citations, throw in getting HREFs off of any element, because in XHTML 2.0 will eventually be able to do that — should be really cool.

It’s basically, collect all that information and then build a link list at the end as footnotes. Very simple concept.

So here I have just a sample of one article that I’ve written here, which shows there are quite a few links in here. Now if we view if afterwards, you see that each of those links is followed by a superscript, and that number in that superscript corresponds to a number in the footnote links.

What I’ve done is I’ve built on-the-fly footnotes for my document, and that can be collected from sources of anything on the page, and it allows me to choose where I want to pull that content from, and where I want to dump it to, so in my case usually it’s from an ID’d div or div with an id of content, and dumping it to a div with an id of extras or something like that. But this is a way of actually using the DOM to improve something apart from the screen, which is something we really haven’t explored all that much. And I’m sure there’s a lot more that we can do in this area. It’s actually improving the printed page, so there’s a lot more you can do when you’re working with the DOM then we’ve even begun to discover.

I’m going to pass it over to Jeremy to talk about stripy tables.

Jeremy Keith: Yeah. This is something, it’s a common task when it comes to styling pages. Let’s say you’ve got a table, a data table of course, not a layout table. Of course.

[audience laughter]

Aaron Gustafson: Although it might be fun to stripe somebody’s layout table.

Jeremy Keith: That will be fun, write a Greasemonkey script.

[audience laughter]

Aaron Gustafson: It’s a Greasemonkey, yeah.

Jeremy Keith: Go and stripe all the layout tables on the web.

Okay, let’s say I’ve got a table of events in this case. And it looks okay, I’ve been able to style things like the headers and stuff, but it’d be really nice to have that striped table effect where every second row has a different color. Now we can do that, in theory we can do that in CSS, there’s an Nth-child I think, and you can even have odd and even, but that’s, I don’t know if it’s CSS 2.1 or CSS 3, but it’s just not supported enough yet to really use it in the real world. But that’s O.K. Because we can use the DOM to plug that hole until CSS support gets better.

We could also do it by hand, I could go in here and I could style every second row, I could put a style declaration on it, or because we don’t want to use inline style declarations, I could go in and I could put a class name on every second row. Well that will get pretty tedious, you know? It will be tedious enough with just this table here, could you imagine a really long table? And then imagine if you have to go in and insert a new row between rows two and three: there’s a new event, and now everything that was odd, is even, and everything that was even, is odd. That would get painful. It actually makes sense in this case to do it after the page has loaded into the browser.

And a nice thing about the Document Object Model is that it doesn’t mind tedium. Well, JavaScript basically is a programming language, and tedium is what they do.

So here’s what I want to do, I want to stripe the tables in my document. So again I’m going to break it down in English:

  • Find all the tables in a document,
  • loop through every table,
  • find all the rows in the current table,
  • loop through every second row, and
  • set the background color of that row.

That’s my script, I’ve written my script, it just happens to be in English, now I just need to use the DOM. And in this case I’m really only using one DOM method and that’s getElementsByTagName. That’s all I need to get the tables and then also get at the rows within those tables by chaining together the same method.

So here’s an example of how the code might look. I’m going to assign document.getElementsByTagName(‘table’) to a variable “tables”, so I don’t have to write it out every single time. I’m going to loop through every instance of that table. Now I’m going to assign the variable “rows” to all the rows, table rows, the TR elements in the current table. Now I’m going to loop through every second one, you can see there the code is slightly different from the first loop, that I’m looking through every second row. And then I set the style. So whatever the current row is, set the style, set the background color to, in this is it’s the hex number for a shade of grey.

Well that’s okay, that’s okay, but really, I don’t want to be setting my styles in my Javascript. We should keep Javascript separate from style sheets, just as we should keep style sheets separate from our markup. Separation is generally pretty good. So I’m rewriting my script in English. Instead of saying “set the background color on the row”, I’m going to say “give the row a class name”, I’m going to give it a class of “odd”. And now in my style sheet I can say — using the class selector — I say, every element with the class odd, well give it the background color of grey. So now all the style declarations are safely off in the style sheet. If somebody wants to change the color, they don’t have to hunt through Javascript, they just do it in the style sheet where it belongs. So I’ll rewrite my script, and instead of setting the actual style, I just set a class name. In actual fact you’d probably want to be a bit more bullet-proof than this. I’d want to see if there was already an existing class, and then add this class name to it with a space separated, but this is just a quick and dirty way of doing it.

I would also want to apply the principles that Aaron was talking about, we want to really make it bullet-proof, we are going to make sure that the browser is going to understand what you’re asking it to do. In this case that’s easily done. All I need to test is “do you understand what I mean by ‘getElementsByTagName’?” And only if the browser understands that, will it execute everything within the curly braces there. If that first if-statement evaluates to false, if it doesn’t know what that means, then it will never execute the script.

And that’s fine, because the table is still there, the content is still there. O.K., it won’t look quite as pretty, it won’t have the striped effect, but the content is there, that’s really important that everybody can access it. You can visit the site using Lynx, you can visit the site using Mosaic, you’ll still get at all the content, you get at the data. But if you visit using a standards compliant browser that understands the DOM, a browser that does understand “getElementsByTagName”, in this case, then you’ll get an enhanced experience.

So the final result is like this, you get the stripy table effect. And like I said, in the future we’re going to probably be able to ditch these little helper scripts that help us to style things, because CSS is going to have better support for doing stuff like this. So there was some quick examples of scripts, and….

Aaron Gustafson: Do the resizing one?

Jeremy Keith: Oh yeah! I think Aaron’s got a pretty neat example in the wild. This is a website he was doing, you want to talk through this one?

Aaron Gustafson: Oh yes, or actually this one I’m saving for later.

Jeremy Keith: Oh okay.

Aaron Gustafson: Save this one, ignore that. Just find the other one I want here. There we go.

Okay, some of you have probably seen this effect before, if you have, I certainly didn’t invent it, I can’t say that I did. There’s been a lot of talk about zoom layouts and that sort of stuff, and creating a layout that works for a small screen and then having a different layout that works for a wider screen. So in this case this was a site that I did for the State of Connecticut’s Department of Transportation. I created a site that is small on 800 by 600, and then once you get a little bit larger here, so it’ll actually… Did you turn off Javascript? Oh, there we go! It jumps to a wider version of the site. I think it’s once it goes over a 1000 pixels or something like that.

This has been on numerous sites, Rammstein was the first one I think that I knew of that did it.

Jeremy Keith: Is Cameron Adams in the room?

Aaron Gustafson: Cameron Adams… No… There he is!

Jeremy Keith: Oh he’s there! Do you want to… Would you like to say a few… I believe you would be the inventor of this technique really.

Cameron: Aaaww…

Jeremy Keith: Yeah come on. This is the man in blue, right here, he’s travelled all the way from Australia to be here.

[audience applause]

Jeremy Keith: And he’s pretty much pioneered this technique, which is…

Aaron: Yea!

Jeremy:… It’s being adopted more and more as a way of striking the balance between the whole fixed vs. liquid thing, which is a debate for another day.

[laughter]

Jeremy Keith: And more and more people are using it all the time. Dave Shea is starting to use this for sites that he’s doing, it’s just a really nice way of compromising.

Aaron Gustafson: Do you want to talk about Jay Skript and the Domsters here?

Jeremy Keith: Well you show that example where you’ve got the…

Aaron Gustafson: Well that one’s for the frameworks portion, save that for later.

Can I jump in for one quick second? One thing to point out, very key, if you really want to bluff your way into DOM Scripting, show off your stuff. That’s a really good way, show off little scripts and tell people how easy it was to do. That is exceptionally key.

Jeremy Keith: Don’t actually show them the code.

Aaron Gustafson: Nah.

[audience laughter]

Aaron Gustafson: Show them the examples but don’t actually show them the code.

Jeremy Keith: So at this point I do have some examples I can show, we can start looking at more cool examples without even looking at the code, but I’d like to open it up for questions. If you have a question, we have a microphone right here, so you’ve got two choices, you can either walk up to the microphone or you can shout it out really loudly from where you’re sitting.

Aaron Gustafson: There’s actually a microphone in the back as well, so I think we should be able to…

Jeremy Keith: There’s a sea of hands. Well we’ve got a gentleman over here…

Performance, O.K., so the question is, in the example of striping the tables, on a really large table, would there be performance hit? And the man to ask about this is Peter-Paul Koch.

That’s the guy who, you know, these would be theoretical questions for anybody else, he actually goes and he investigates it. Let’s say 900 tables on a page, he will write a test case with 900 tables on the page.

Aaron Gustafson: But he’ll generate the entire test case with the DOM.

Jeremy Keith: Yeah, probably, at the same time. So I would refer you to www.quirksmode.org.

Aaron Gustafson: I think just another thing to talk about when you’re testing certain things, a lot of people when they’re doing it… I think the way you’ve done it, it’s really great, with the for loop where you’re actually incrementing by two each time. But sometimes people test for odd or even or for a particular number or something like that.

One way that you can actually improve everything is by going with something like the bitwise operator which actually goes to the binary version of the number and you can tell immediately, you don’t even have to do a modulus of the number in order to determinate if it’s odd or even.

Jeremy Keith: You geek! What are you talking about!?…

[laughter, applause]

Jeremy Keith: Professor over here! No actually, there’s always a better way to do things.

Aaron Gustafson: I’m bluffing.

Jeremy Keith: There really is always… There’s more than one way to skin a site, shall we say. There’s always more than one way of doing things, and actually I first came up with the table striping script, I was so used to looping through every element in array whenever I wanted to do something, I wasn’t looping through every second element, I was just going: Take every row, O.K. If the variable I’ve set was called odd, change it to even, and apply that class, and if it’s called odd, change to even, change back. It was ridiculously complicated. And somebody just wrote me an email and said “why don’t you just increase by two?” It’s like “Doh!”

[audience laughter]

Jeremy Keith: In fact, is Dustin Diaz in the room at the moment?

Dustin: Woohoo!

Jeremy Keith: Thank you for that tip Dustin!

[audience laughter]

Jeremy Keith: It’s a shame you told me after I put it in the book, but thank you nonetheless.

[audience laughter]

Jeremy Keith: I see a hand back here, let’s get this gentleman…

Yeah, the question is about the practicalities of generating markup using the DOM. I compared innerHTML as being a sledgehammer to the DOM scalpel. The fact is that when you get very complicated DOM stuff going on, and we’re talking very complicated, this was a lot of markup generation. Okay, so you were generating a lot. And again, this is something that Peter-Paul Koch has done tests on, and there is definitive proof that frankly, innerHTML is faster. There’s just is no getting around it. As much as it grates that I have to say it, the standards based way of generating nodes with the DOM just takes too long.

Aaron Gustafson: Though if you have the ability to use cloneNode in order to replicate content, that is actually a little bit faster way than creating an element each time, is to create one kind of exemplary element and then replicate it using cloneNode, and you’ll save some in performance doing that, and the unmassive DOM…

Jeremy Keith: This is something that comes up in AJAX all the time. Actually when you’re parsing XML and creating markup, you know, big markup, to change the page, that could be a performance issue. Sometimes it’s better to just take the markup, let’s create in on the server side, and dump it in the document using innerHTML. So yeah, when you get into very complex stuff, innerHTML does actually trounce the DOM methods.

Aaron Gustafson: Question a couple of rows back…

Jeremy Keith: It’s Simon Willison, ladies and gentlemen! Right, so Simon is just making the point that, again, there’s always more than one way of doing things. Let’s say the example of the block quotes. I created a link element, I set the HREF attribute to that link element, I may have created a paragraph, to put the link in. I did all that, and then when I had that chunk of markup, I appended that to the document. Now I could’ve appended each part to the document: append a paragraph, then append a link in there, then set the HREF attribute of that link. They’re equivalent, they’re completely equivalent, but the difference is in performance. There is a performance difference, it’s better to do it all first and then dump it into the document in one go. Do we have time for…

Aaron Gustafson: Yeah we have time for maybe two more questions.

Jeremy Keith: Okay. This gentleman down the front…

So the question is, with the greater adoption now of standards and using the DOM, using DOM Scripting, the question arises, how are these performance issues that have been raised, how will they be addressed by the browsers, for instance IE, what about the next version of IE, will it address it? As far as I know, the next version of IE has pretty much decided to stay away from Javascript, because it’s O.K., there are things in every browser we’d like to fix, every browser has its own little Javascript quirks and it would be nice to fix them, but let’s face it, the real problem with Internet Explorer right now is the CSS support, and that’s what they’ve concentrated on, and I think that’s fair enough.

The DOM support is there. Yeah there are performance issues, but I would say that those performance issues that you’re talking about, they’re edge cases. They’re pretty extreme examples. In fact I would say, if you’re generating that much markup in the DOM, what are you doing? I mean, the DOM is good for enhancing existing pages, but if you’re generating massive documents using the DOM, how do people without Javascript get at that stuff? So, it’s better using DOM for small little things.

Okay, Aaron’s got just a few closing remarks, I think I’m going to have to stop taking the questions right now. So I’ll just let Aaron close up, a few remarks about covering frameworks and best practice and such.

Aaron Gustafson: Okay. We can answer your questions in private afterwards.

Jeremy Keith: Oh yeah, you can find us at the parties, and we’ll talk Javascript all night.

[audience laughter]

Aaron Gustafson: Especially if you ply us with alcohol.

So there’s been a lot of talk about frameworks and stuff like that, using Prototype and using Scriptaculous and all those sorts of things. So will frameworks help you bluff?

My feeling: no.. and a little bit yes. You don’t want to look like the fool, that’s the worst mistake you can do when you’re bluffing. Because if you start using Prototype or something like that and you’re using it for everything and then all of a sudden something goes wrong and you don’t know what Prototype is doing for you, you’re basically left high and dry and you’re going to look like a fool in front of somebody. You don’t want to do that.

You can use Prototype and other sorts of frameworks to create effect. They’ve got a lot of really neat things. People know the flash and stuff like that. This particular page I did for Konica-Minolta has a combination of the flash that people are probably familiar with from base camp, and Shaun Inman — he’s here somewhere, he’s back there, Shaun Inman, very amazing DOM scripter and not a bluffer — he has a beautiful scroll-to script, and this is an incorporation of that, it’s the scroll-to and flash, it’s a way of creating targeted elements that are actually more usable, so you’re not just jumping down the page and then leaving some period of trying to figure it out. Especially in a listing like this, where they’re trying to figure out exactly what property the printer or something like that that they’re looking at, that they just jumped down to, it gives them an immediate way to look at it and it’s just fun to do. Who doesn’t like to sit there and just watch the page scroll down?

Ooh… Gives me shivers. Anyway, so, that’s a fun one. And it can also be combined, in that site actually there’s some combinations of that with some AJAX, so the page will reload then it’ll scroll and then it’ll flash, so all kinds of pretty stuff you can do.

But anyway, when working with frameworks, I feel the best way to start out is to start out slowly and work incrementally, and know what it is that you’re using the framework to do. So in the case of Prototype you have a wonderful function which is the dollar sign function, and what that allows you to do is, it’s kind of shorthand of “document.getElementById”, and anyone who has done a really long DOM script, has probably just hated the fact that they had to keep typing that, or they just keep it on a snippet, or cut and paste or something like that. So that’s an easy way that you can do it. And it’s even more powerful and that you could supply it multiple ids and it will bring back all of those elements collected into an element collection which you can then loop through like an array.

So there are lots of ways that you can start using frameworks and slowly work them into your scripts and not get in over your head. So that’s all we’re really going to say about frameworks right now.

I’m going to hand it over to Jeremy for the wrap-up.

Jeremy Keith: Yeah I think that’s basically it. I’m sorry we didn’t get to take too many questions there, but like I said, we’re around. I’m actually going to be outside signing copies of the book, so form an orderly queue, we don’t want anybody killed in the stampede for the books. If you had your hand up to ask a question, come up and take a book.

I just want to close with some basic remarks, and that is that you can sort of bluff your way in DOM Scripting, by dropping those terms, and you can bluff your way in CSS, once you visit the right sites and know all the cool techniques.

But you can’t bluff your way in markup, and it’s important to remember that both CSS and DOM Scripting are enhancements to the document, and it’s the document itself that’s a solid basis for whatever you put on top of it, be it presentation, be it behaviour. A well structured semantic well formed document is the most important thing.

So don’t worry if you can’t bluff your way in DOM Scripting, and don’t worry if you can’t bluff your way in CSS, know your markup. Everything follows on from the markup. And I would like to thank you all very very much.

[applause]

Also on AMP

Have you published a response to this? :