This is the third and final installment of A Designer’s Guide to Prototyping Ajax. Be sure to also check out Ajax Wireframing Techniques and The Introduction if you haven’t already.

Introduction

Quick review: Last Monday A few weeks ago, we covered 3 different wireframing methods (keyframing, stacking and TOP) and how they can be used to create prototype-friendly XHTML/CSS wireframes. We touched on how descriptive interface class names like hide and show and techniques like CSS Boolean can help us conceptualize and understand the minimum markup changes that will be needed by our prototype to make them come alive. In the last part of this series, we’re going to finally get into some JavaScript fundamentals and the actual code that will help us make those specific markup changes dynamically.

HTML Form Builder

I know there are a good number of designers out there afraid of anything that smells of programming (basically, if it’s not plug and play, it’s not being used). I completely understand. Dealing with CSS rending across browsers is bad enough already. Because prototypes are all about making an interface “look” like it works, the dabbling we’re going to go over here is actually a process that’s amenable to designers (especially those with programming skills that started off as just rudimentary hacking skills). CSS is the domain that most of the new crop of web designers are most comfortable with and so the functions we’re going to go over are ones that manipulate, for the most part, the styles of our elements. Remember, we won’t be concerning ourselves with any content generation concepts like Ajax, innerHTML or node creation. There are two reasons for this:

  1. To keep it simple. We want our code to be as simple as possible when we hand off our work to developers (who’ll have a better idea of how they want to implement those features anyway since they should be database driven).

  2. To keep it organized. If built correctly, all the potential states and interactions of our interface should be built right into our XHTML/CSS wireframes and accessed by either hiding or showing the elements or adding and removing semantically appropriate class names. Since our structure and presentation layers are basically done and nicely separated, it would be a shame to move our markup into the behavior layer this early into the process.

Making Things Happen

Alright, so let’s say we have a JavaScript function that does something awesome. Something like this:

function doSomethingAwesome(){
    alert('Hello World!);
}

How do we call our awesome function in our XHTML document? Well, the easiest way would be to add an event to an element right in the markup. For example, if we wanted to call the function when we click on an element we’d add an onclick attribute to the element like so:

<div onclick="doSomethingAwesome();">Click Me for Awesome!</div>

It’s pretty straightforward and there are all kinds of events to play with depending on the element you’re working on. Peter-Paul Koch has a great overview of the different events on his web site. Now, there are some tricky exceptions. For example, if you wanted to call the function when you click on a link, you’d probably think to apply it like this:

<a href="" onclick="doSomethingAwesome();">Click Me for Awesome!</a>

Perfectly rational. Unfortunately, your browser will run the function and then try to go to the url specified in the href, which in this example will just refresh the page and therefore nullify the function that was just called. Not very useful. There are two ways to get around this behavior for links. You can either disable the default behavior of the anchor element or call the JavaScript function in the href. The latter is made possible thanks to JavaScript-enabled browsers support of the javascript: protocol, which is just like the http: and ftp: protocols except it lets you execute statements rather than loading a new document.

<a href="javascript:doSomethingAwesome();">Click Me for Awesome!</a>

If you’re a Flash developer, this method is useful when you want your movies to call JavaScript functions without needing something as complex as a JavaScript/Actionscript Gateway or the External Interface feature. If you don’t like that approach, you can always disable the default behavior of the link. All we need to do is add a ‘return false’ after we call our function.

<a href="" onclick="doSomethingAwesome();return false;">Click Me for Awesome!</a>

For those that need to know more about this method, Ryan has written more detailed discussions about disabling links in this feature and this notebook. Feel free to skip them if you’re not hardcore. I try to skip them because it’s Ryan and he’ll usually just fix whatever I might mess up.

Anyway, that does it for the easiest way to apply an event to an element. Like all things easy, this method is, unfortunately, bad for you and your code in the long run. This method of adding behavior to your HTML is considered an obtrusive approach (called this because the JavaScript is inserted into the flow of the markup) and just as we didn’t want our structural layer to find itself in the behavior layer, we really don’t want our behavior layer mixed in with our structural layer.

Event Listeners

The unobtrusive (and slightly more complex) method for attaching events to our document uses something called event listeners. Event listener functions allow us to attach a function to an event that fires on elements of our choosing. This is all made possible thanks to JavaScript’s ability to crawl the DOM. There are far more intelligent and opinionated discussions all over the Internet about how and what event listeners to use and so I won’t try to cover all the complexities in this feature. Instead I’ll toss you a roundup:

  • Document Object Model Events - W3C documentation on the subject. Best place to start is always from the source. The source knows all.

  • Catching Up with AddEvent - Ryan wrote a brief history lesson about addEvent for Treehouse that does an excellent job explain why there’s multiple versions of the code flying around now. Lucky for you, we edit the magazine so I’ve made the article available for use in this tutorial.

  • DOM Design Tricks II - Eisenberg does a great job going over the event-handling capabilities of the Document Object Model in this A List Apart article from back in the day.

  • Forget addEvent, use Yahoo’s Event Utility - Diaz gives a thorough review of why Yahoo might have the best answer for dealing with event handling in JavaScript.

Changing the Style of a Specific Element

One of the most important notions in DOM programming is that elements can be identified uniquely so that they can be found and manipulated. Targeting an element by its unique id is the fastest method for making changes on a singular element. In your markup, make sure your element has an id attribute like so:

<div id="vegetable">Broccoli</div>

To make it disappear, we’d could use the following JavaScript:

document.getElementById("vegetable").style.display = "none";

If you wanted to make a reusable function out of it, you might write the following:

function hideElement(obj){
    document.getElementById(obj).style.display = "none";
}

And then call the function like so to hide our dirty green stalk:

hideElement("vegetable");

Changing All the Elements in a Class

While the initial specifications for JavaScript is great about helping us target a specific element by its ID and even targeting all elements of a particular tag (getElementsByTagName), it is for some reason beyond me why it does not allow us to target all elements of a particular class. Fortunately, the solution is on the Internet. There’s lots of variation out there for implementing this function, but our favorite and the one we use instead of the built in one provided by prototype was created by Robert Nyman called the Ultimate getElementsByClassName. He’s done a great job explaining why it was written the way it was and various ways of implementing it. With this function we can now take the following markup:

<div class="veggies">Broccoli</div>
<div class="veggies">Carrots</div>
<div class="veggies">Cabbage</div>

And use the following code to make them all disappear.

var allVegetables = getElementsByClassName(document, "div", "veggies");for(i = 0, i < allVeggies.length, i++){
    hideElement(allVeggies[i]);
}

Class Name Manipulation

During our prototyping process, we try to use JavaScript style changes only on the display and visibility properties of an element. There are times when we make changes to position, height and width, but those generally tend to be edge cases. When it comes to making multiple style changes on an element to indicate a change in state, we prefer to manipulate class names instead.

For example, let’s say we wanted to make a change to an element that’s a bit more complicated than hide/show like indicating that an element or group of elements is in an error state. When I indicate an error in my application, I like to change the color of the text and background and probably show things in bold. Based on what we know so far, I could make all of those style changes with JavaScript like so:

function showError(obj){
    document.getElementById(obj).style.color = "red";
    document.getElementById(obj).style.backgroundColor = "pink";
    document.getElementById(obj).style.fontWeight = "bold";
}

It works, but it’s not great. The problem is we’re now pushing presentation information into our behavior layer. Later down the road, a designer might will probably change their mind and want their errors to look completely different. Going into the JavaScript to make those changes every single time is annoying and counter-intuitive. It would be much easier to specify these rules in our CSS like this:

.error{
    color:red;
    background-color:pink;
    font-weight:bold;
}

And then have JavaScript just attach and remove the semantically viable class to an element to keep both layers clean and separated. If your development is using a toolkit like Prototype, then you have easy access to the following two functions to do just that:

If you’re of the do-it-yourself variety, then you might want to use the following three functions to gain the same functionality.

String.prototype.trim = function() {
    return this.replace( /^\s+|\s+$/, "" );
}function addClassName (elem, className) {
    removeClassName (elem, className);
    elem.className = (elem.className + " " + className).trim();
}function removeClassName (elem, className) {
    elem.className = elem.className.replace(className, "").trim();
}

That first function is just a trimming function to remove leading and trailing spaces that might be created during the adding and removing process when dealing with multiple class names on an element. With these two functions in our arsenal, we can now use those useful class names we discussed in the 2nd part of this series to make our prototype come alive.

Conclusion

And that concludes the Designer’s Guide to Prototyping Ajax. Remember, these articles are meant to serve as a foundation and an initial set of guidelines to help you understand and develop practices that will work best for your work flow and team environment. We’ve found them to be great ways of relieving pressure off the developers, increasing designer responsibility and better code for the team to work off of in the long run. If you or your team has any other practices that you think would be beneficial for designers or prototyping in general, please do share because the way we see it, the love just follows you back for more.

HTML Form Builder
Kevin Hale

JavaScript Basics for Prototyping by Kevin Hale

This entry was posted 4 years ago and was filed under Features.
Comments are currently closed.

· 22 Comments! ·

  1. Olav · 4 years ago

    Thanks, this will make a permanent bookmark. Keep it up guys, you’re one of the few sites that regularly dishes out great content.

  2. Erik · 4 years ago

    Good article. I’m glad to see someone promoting the idea of changing classes on elements rather than going right in and munging the CSS attributes directly. Much cleaner this way.

    In the trim function, though, I would make the replace global, so that it cleans up both the front and back ends if there are extra spaces. Dunno how that might happen, but that would make the trim function more generic than for use just in the class toggling functions.

    return this.replace( /^\s+|\s+$/i, "" );

    And in the addClassName function, I would test to see if the class was there rather than removing it for fear of creating a flicker by removing it and then re-adding it:

    function addClassName (elem, className) { if (elem.className.indexOf(className) == -1) elem.className = (elem.className + " " + className).trim(); }

  3. Ian · 4 years ago

    I implemented a popup window function like this.

    I created a class called popup and several with dimensions (ie 400-300). Then upon each page load, I simply call a function that goes and grabs all popups and adds an onclick event (returning false). Instant popups!

    This type of event handling is really cool - and degrades perfectly :)

  4. mm · 4 years ago

    Jesus, could you use some more ambiguous terminology please? I know some of this confusion is unavoidable to an extent, but please, you can do better. Let’s look at your use of the word “prototype”, it’s used to mean:

    1) a design prototype 2) the Prototype library 3) a class prototype (JS inheritance)

    Not entirely your fault (since you can’t rename the library), but when you say things like “prototype-friendly”, which of these three are you referring to? It could, honestly, be any of the above. Honestly I’m not even sure if you know which one you mean half the time.

  5. Kevin Hale · 4 years ago

    MM, if you read the beginning and the other two articles you’d know that 99% of the time I’m referring to a design prototype since the context is “designer’s guide to prototyping ajax.” I’ve only mentioned the Prototype library once in this article and I refer to it with the capital ‘P’ and the word “toolkit”. Now, there is a trim function above that’s a class prototype, and I can see where there might be some confusion since I didn’t go into it, but I thought I was careful when I spoke of wireframes, CSS/XHTML wireframes, wireframing, prototypes, Prototype and prototyping (which can only really refer to design prototypes and not the other two definitions). Apologies if I didnt make that more clear.

  6. Dustin Diaz · 4 years ago

    Cool. Thanks for the link love on the Event util. These are definitely some good pragmatic approaches for prototyping and wireframing across the board. Good job on the entire series actually! Of course this wouldn’t officially be a comment from me if I didn’t mention something else sweet about YUI. Here’s some sweet advice you might like. With the YUI DOM Collection Utility, you can do this:

    YAHOO.util.Dom.addClass(YAHOO.util.Dom.getElementsByClassName('foo'), 'bar');

    Or even better, if you want to apply an entire batch to a method. Do this:

    YAHOO.util.Dom.batch(YAHOO.util.Dom.getElementsByClassName('foo'), doThatSuperCoolThing);

    Again, good writings these last few weeks! I’m lovin’ em.

  7. Ian MacColl · 4 years ago

    The links in the slug/leader to the previous articles (with anchors Ajax Wireframing Techniques and The Introduction) link to this article (but the recent news links look OK)

  8. Kevin Hale · 4 years ago

    Oops. Thanks for catching that Ian. I just forgot to add the links in there.

  9. Duncan Beevers · 4 years ago

    The removeClassName function is a bit clumsy. If a tag were to be classed “errortable error” and you simply wanted to remove the “error” class, well, you know, trouble.

  10. alxander · 4 years ago

    http://encytemedia.com/event-selectors/ builds on prototype, great for adding event-handlers to elements. Highly recommended.

  11. James · 4 years ago

    Hello, I’m trying to list all of the links on a page, including any iframes. The trick is those iframes may or may not have names. Can I use this library to do that?

    Thanks,

    James

  12. rifqi ahmed · 4 years ago

    Everyone needs a hug.

  13. php-ajax · 4 years ago

    prototype.js is a great tool http://www.itconsultinglive.com

  14. Hari · 4 years ago

    Need help in optmizing below code——

    do{
    orderKey =D1.OrderKeyList[forInd].value sgnew = eval(“D1.”+orderKey+”“) sgnewtxt = eval(“D1.”+”text”+orderKey+”“)
    alnesval=D1.OrderKeyList[forInd].text;
    alnesval=alnesval-1;
    doInd = alnesval do{
    var sgvalnew = sgnew[doInd].value;
    if(B[sgvalnew]==1){
    sgnewtxt.value=minQty;
    }//end if
    doInd — }while(doInd >=0)
    forInd— }while(forInd>=0)

  15. fred · 4 years ago

    Everyone needs a hug.

  16. Jeroen · 4 years ago

    I’ve read some posts about manipulating the TYPENAME.prototype and that it is “verboden!” (not allowed).

    For exampel: Object.prototype.hello = "hi";

    …actually will add this to every single time u loop any array anywhere. Sorry dont remember the post where i read it and i couldnt find it either.

    Just a little warning.

  17. sal · 4 years ago

    Thank you for your articles. they are beautiful (I’m a noob)

    !! Warning off topic !! Particle Tree is Beautiful your design is Simple, Colorful … so perfect, it makes me cry. You guys are my Heros. and ‘wufoo’ rules man. !!Back to normal!! Thank you.

  18. just.xTc · 4 years ago

    What an excellent site. Unsurpassed style, witty posts, and the design looks great. It makes my website look like monkey semen. Gj to whoever the admin(s) is (are).

  19. kl; · 4 years ago

    Everyone needs a hug.

  20. Parry · 4 years ago

    mlm lead

  21. 1 month and · 3 years ago

    Everyone needs a car.

  22. ogÅ‚oszenia · 3 years ago

    Everyone needs a hug mee to :D