» Anatomy of a Module
Submitted by kplawver on Wed, 2006-04-26 13:44.Modules

Introduction

This document is a complement to Creating A Module, Module Best Practices and Setting Up A Local Development Environment. It will take you from start to finish building a brand new module. Hopefully, by the end of this document, you'll be able to go build your own modules without looking back.

The Module Skeleton

Every module should start from the skeleton. It gives you placeholders for all the important elements of a module, and makes sure you start with a solid foundation (which is why we called it "skeleton" to begin with).

If you haven't already looked at the source of the skeleton, here it is:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://iamalpha.com/.developer/profile/index.html">
	<title>Module Title</title>
	<link rel="stylesheet" type="text/css" id="manifest" href="http://imakealpha/.developer/css/manifest.css"/>
</head>
<body class="module" id="module-name">
	<h1>Module Title: Version <span class="version">1.0</span></h1>
	<h2>Edit Interface</h2>
	<div class="edit module-name">
	</div>
	
	<h2>View Interface</h2>
	<div class="view module-name">
		<h3 class="head"></h3>
		<div class="body"></div>
	</div>
	
	<h3>Description</h3>
	<p class="description">Description goes here</p>
	
	<h3>Detail</h3>
	<p class="detail">Detail goes here</p>
	
	<h3>Author Information</h3>
	<ul>
		<li><a href="http://yourdomain.aol.com" rel="author">Your Name</a> - <a href="http://yourdomain.aol.com/contact" rel="contact">contact</a></li>
	</ul>
</body>
</html> 

In the following sections, we'll explain what each section of the document is and what it should be used for.

The View

This is the view:

<div class="view module-name">
	<h3 class="head"></h3>
	<div class="body"></div>
</div>

The h3 is the title of the module that will be displayed to the user.

The div with a class of body will contain the contents of our module.

It's not required that you use h3 and div for the head and body of your module's view, but we recommend it. You could use any heading element (h1 - h6) for the head, and any block element (a list, paragraph, div, blockquote, etc) for the body, as long as they have the right class on them.

Module Description

This is the module description:

<p class="description"></p>

As you can see, it's empty. This isn't how a final module should look. There should be some text there that describes your module to someone who might want to put that module on a web page somewhere.

A good rule of thumb is that the module description shouldn't contain any acronyms, buzzwords or things that might confuse the "average user". Your mileage may vary as to what "average" means to you, but use your best judgement.

Also, your description should be about a paragraph. If you need more than one paragraph, put your paragraphs in a div with the class "description".

Module Detail

This is the module detail:

<p class="detail"></p>

A module's detail should contain more information than the description, and may therefore be much longer than a single paragraph. It should contain whatever information you think a fellow developer might need or want to know about how your module works.

Author Information

Here's what the author information looks like:

<ul>
	<li><a href="http://yourdomain.aol.com" rel="author">Your Name</a> - <a href="http://yourdomain.aol.com/contact" rel="contact">contact</a></li>
</ul>

What's the point of writing a module if you don't get any credit? This is so both users and systems that use your modules know where to look for you if they want to send you presents, hire you, or make jokes at your expense.

Building Our Module

Now that we're done describing the physical pieces of our module, we're going to build one, documenting each step along the way in a process that hopefully won't kill us by the time we reach the conclusion.

Design

The big question is "What do we want our module to do?"   Let's just pretend, for a moment, that we're a sports junkie, and would love to have a module that displayed the most recent sports headlines from AOL Sports?   Yes, I know, it's blatantly partisan of us, but this is an example.   You can substitute your own RSS feed if you want.

Since the feed we're using doesn't have full content, just headlines, that's going to make it easier, right?

Our design should be just as easy. We're going to have a module head, with a heading in it, probably "Latest Sports Headlines", and then an unordered list of headlines that link to the actual story. Couldn't be easier, right?

Define It

After we've got our design done (without opening Photoshop or drawing anything on napkins, mind you), it's time to think about how we're going to define our module in the manifest. Here's how we wrote it up:

Description:

The top five sports headlines from AOL Sports.

Detail:

This module grabs the AOL Sports RSS feed via Ajax parses it, and displays five headlines.

Author Information:

And that all should look like this in our manifest:

<h3>Description</h3>
<p class="description">The top five sports headlines from <a href="http://sports.aol.com" rel="proxy">AOL Sports</a>.</p>

<h3>Detail</h3>
<p class="detail">This module grabs the <a rel="proxy" href="http://xml.news.aol.com/aolnewsrss.xml?cid=1690&amp;amp;feedtype=manual">AOL Sports RSS feed</a> via AJAX, parses it, and displays five headlines.</p>

<h3>Author Information</h3>
<ul>
	<li><a href="http://lawver,net" rel="author">Kevin Lawver</a> - <a href="mailto:alphablogger@aim.com">contact</a></li>
</ul>

Mark It Up

Now that we've defined our module, it's time to actually build it.   We want it to look something like this when we're all done:

Top Sports Headlines

Since we're going to get the headlines from the RSS feed, the markup for our module is actually pretty simple:

<div class="view top-sports-headlines-example">
	<h3 class="head">Top Sports Headlines</h3>
	<div class="body">
		<ul class="top-sports-headlines-list">
			<li>Loading...</li>
		</ul>
	</div>
</div>

Make It Interesting With Ajax

Now, we have to do the hard part and go get our headlines!   To do that, we're going to need to use the JavaScript SDK, and set up our local development environment.

Back? Good! Now we get to write some JavaScript - yippee!!

First things first, we need to create a JavaScript function that grabs our headlines and displays them.    This is a little more complicated than it might be if you were building a regular Ajax function (or easier, I don't know, your mileage may vary), because you have to use our proxy because of XmlHttpRequest's security rules.   To start, we're going to make sure that we create unique functions that aren't going to be replaced by someone else, so we'll start with this shell, which I saved as "top-sports-headlines.js" in the same directory as my manifest:

function topSportsHeadlines() {
}
function topSportsHeadlinesWrite() {
}

Pretty exciting, huh? Before we get ahead of ourselves though, we need to add a few things to our module manifest so we get what we think we're going to get when we actually have something to do.   In the head of your manifest, add the following:

<script type="text/javascript" src="jssdk/lop.js"></script>
<script type="text/javascript" src="top-sports-headlines.js"></script>

The two jssdk files may be in a different location depending on where you installed them when you set up your local development environment, so those locations may need to change.

We also need to make sure our javascript runs, so inside your body tag, add the following:

onload="topSportsHeadlines();"

Now we need to actually write some javascript. We'll try to take this step-by-step:

  1. We need to tell the SDK that we're using the Ajax stuff, and set up our success and error functions.   They should look something like this:

    function topSportsHeadlines() {
    	var headlineURL = "http://xml.news.aol.com/aolnewsrss.xml?cid=1690&feedtype=manual";
    	var success=function(xml) {
    	}
    	var error=function(xml) {
    	} 
    	lop.Ajax.prototype.simpleGet(headlineURL,success,error,null);
    }

    This is the barest of bones for this function, and it won't actually show us anything if we try to run it. But, this will probably be the basis for almost any module you build with Ajax, so it's nice to see it this way.

  2. We need to start filling out our skeleton with some muscles. First, we need to find the lists we're going to populate with the headlines, and decide if we even need to go get them (say, if we don't find any lists to populate). In people-talk, here's what we're trying to do:

    1. Find all the lists in the document.
    2. Of those lists, we only want the ones that have a class name of top-sports-headlines-list.
    3. We want to save the matching lists for later.
    4. But, if we don't find any lists, we want to bail, because we'll have nowhere to put our headlines.

    And here's the code that does that (new stuff is in blue):

    function topSportsHeadlines() {
    	var headlineURL = "http://xml.news.aol.com/aolnewsrss.xml?cid=1690&feedtype=manual";
    	var container = document.getElementsByTagName("ul");
    	var lists = Array();
    	for ( var i=0; i<lists.length; i++ ) {
    		if ( lists.length > 0 ) {
    			var success=function(xml) {
    			}
    			var error=function(xml) {
    			}
    			lop.Ajax.prototype.simpleGet(headlineURL,success,error,null);
    		}
    	}
    }
  3. Now that we have our lists, it's time to define our error condition, and fill out our success callback with actual parsing magic. We also need to fill in the topSportsHeadlinesWrite() function. Again in people-talk, here's what we're trying to do:

    1. If there's an error, we want to display a reasonable message to the user.
    2. If successful, we need to get the list of headlines out of RSS and turn them into HTML list items.

    And here's the code to do that (new stuff is green this time):

    function topSportsHeadlines() {
    	var headlineURL = "http://xml.news.aol.com/aolnewsrss.xml?cid=1690&feedtype=manual";
    	var container = document.getElementsByTagName("ul");
    	var lists = Array();
    	for ( var i=0; i<lists.length; i++ ) {
    		if ( lists.length > 0 ) {
    			var success=function(xml) {
    				var dom=xml.responseXML;
    				var items =dom.getElementsByTagName("item");
    				for ( var i=0; i<items.length; i++ ) {
    					var item=items[i];
    					var title=item.getElementsByTagName("title")[0].childNodes[0].nodeValue;
    					var link=item.getElementsByTagName("link")[0].childNodes[0].nodeValue;
    					output+="<li><a href='" + link + "'>" + title + "</a></li>";
    				}
    				topSportsHeadlinesWrite(lists,output);
    			}
    			var error=function(xml) {
    				output = "<li class='error'>There was an error retrieving the headlines.  <a href='javascript:topSportsHeadlines()'>Please try again</a>.</li>";
    				topSportsHeadlinesWrite(lists,output);
    			}
    			lop.Ajax.prototype.simpleGet(headlineURL,success,error,null);
    		}
    	}
    }
    
    function topSportsHeadlinesWrite(lists,output) {
    	for ( var i=0; i<lists.length; i++ ) {
    		lists[i].innerHTML = output;
    	}
    }

    There, you've now got a script that does everything we set out to do in the definition phase!

In Conclusion

This module is actually available in the module gallery, and you can go play with it in the Playground or view the completed source. Hopefully, this tutorial helped clear up any confusion you had about creating modules, or filled in some blanks left by the other documents.

This was a relatively simple module, as far as AJAX modules go. We'll be posting tutorials on server-side and other kinds of modules in the near future. But right now, we need a nap.