- Introduction
- Designing Your Module
- Valid Semantic Markup
- CSS Guidelines
- Browser Support
- Performance
- JavaScript
- Search Engine Optimization
- Localization of Modules
- Updating Modules
- Security Issues
- Error Handling
- Clean Up After Your Module
Introduction
Thank you for deciding to create a module! We really appreciate it and think it will be a lot of fun. But, before you get too far into building, please review these best practices and guidelines. Hopefully they'll save you some trouble and lead to a better module.
Designing Your Module
The first part in building a module is deciding what it’s going to do, how it’s going to do it, and what it’s going to look like. These are very important decisions, and will determine whether your module is awesome or not.
Keep it Simple
Taking inspiration from other widget/module products like Apple’s Dashboard, we think that modules should do one thing and do it well and efficiently. Design shouldn’t be overly complex and shouldn’t require a steep learning curve.
Building a module that does one thing “right” is harder than it sounds. Concentrate on solving the simplest problem, and then spin off other modules to solve other problems and do other things.
Valid, Semantic Markup
Valid Is Good
Now that you’ve designed your module, you have to build it. Since modules are going to exist as HTML, it’s time to think about what markup you’re going to use. We require that all modules validate (with a few minor exceptions, which we’ll get into later). “Valid” markup means that your module code:
- Conforms to the version of the HTML standard it declares support for
- Is readable and well-formed
- Conforms to the XHTML 1.0 Transitional DOCTYPE. Basically, this means:
- All tags and attribute names must be lower case.
- All tags must be closed (<br> becomes <br/>).
- All attributes must be quoted.
There are, of course, other rules. Most Web development tools will allow you to build XHTML 1.0 documents and will even help you check for validity.
Make it easy on yourself and use our module skeleton to get started with modules. It provides a good valid base to start from. And once your module code is complete, validate it using the AOL ModuleT validator.
Mark It Up Like You Mean It
On top of validity, we prefer widgets that have semantic markup. What does that mean? It means that the markup implies meaning about the content of the module, not presentation, which will be taken care of in a style sheet. For example, if you have a list of names:
Kevin
Joe
Shawn
Paul
Ju
Kedar
Don't mark it up like this:
Kevin<br/>
Joe<br/>
Shawn<br/>
Paul<br/>
Ju<br/>
Kedar<br/>
Mark it up like a real list:
<ul>
<li>Kevin</li>
<li>Joe</li>
<li>Shawn</li>
<li>Paul</li>
<li>Ju</li>
<li>Kedar</li>
</ul>
For another example, to create a subheading on your page, don't mark it up like this:
<big>My Section Heading</big>
Mark it up using a specific subhead format:
<h3>My Section Heading</h3>
This may seem like extra work, but ultimately semantic markup means less markup and more options for styling when you get to writing the CSS for your module.
We also love the idea of microformats. In fact, the HTML document you create to submit your module is a microformat. We highly recommend you use existing microformats if they apply to your module, and try to follow the philosophy behind them if you’re doing something new.
Stay Classy
Because users may pull more than one instance of a module onto their pages, using ids is not a good idea. Use classes instead. Also keep in mind that there may be many modules on a page, and they were undoubtedly created by developers with different ideas of good class names. What does this mean to you? It means you need to go back and look at the semantics section and apply it to your class names.
Here are some examples of bad class values:
- right
- left
- dark
- red
Here are some good class names:
- first-name
- city
- odd-row (only needed until we can use nth-child selectors).
Classes should be just as semantic and descriptive as the markup you use. They should provide even more information about the data. Semantic markup is specific about a list item, where an <li> lets you know only that it’s a list item. If the class value is first-name, you now know that not only is this a list item, it’s someone’s first name.
We'll be presenting a list of reserved classes and ids in the near future. So, be on the lookout for that.
Keep It In The Format
We’ve created a microformat for creating modules that provides you, the developer, a single document where you can build, test, and deliver your modules. This microformat is documented in its profile. You can find more information on microformats in general on the microformats Web site.
Microformats provide many benefits, but for us, the main one was providing a single place for development, testing and delivery. We’ve found over the years that if you require separate files for meta data or descriptions that they never get written. With the microformat, you can do everything in one file, which should lead to better data about modules, and better modules because they’ll be easier to test.
To check that you're following our microformat, make sure you use our AOL ModuleT validator.
CSS Guidelines
For pages including modules, there will be two sets of CSS: module styles and page styles. Module styles should define properties needed for a module, and should be generic enough to be overridden easily by page styles. We’ll explain some of the best practices for doing that later on in this section. If you're in need of a little CSS refresher, we've also put together an overview of specificity and positioning that might help you make more sense of all of this.
Keep Your CSS To Yourself
Don't change the style of any generic HTML elements. You should declare styles that apply only to your module. To do this, begin all styles with your module name. For example, if your module's name is "Top Sports Headlines", the class on view and edit should be "top-sports-headlines". Here's an example:
<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>
In order to keep all your styles "contained" within your module, all of the styles you declare should begin with ".top-sports-headlines". That way, you'll only select your module and its descendants, not things outside of it. For example, if we wanted to style the list, and list items in the module above, we'd write something like this:
.top-sports-headlines ul {
list-style:none;
}
.top-sports-headlines li {
padding:0 0 .5em .5em;
}
Hopefully, this is clear. If not, please leave us a message on the message board and we'll explain it some other way.
Simple CSS Is Better CSS
Simple is good. Simple can also be rather difficult when you’re not sure where your module will be on a page or what will be around it. But, it’s also important for the CSS you write around modules to be simple to allow for the greatest flexibility in styling the page as a whole.
Avoid styling:
- float: You won’t know if your module will be pulled into a page inside a float, which could cause your clears to have unintended consequences. If you’re going to use float, make sure you position its parent relative. See the CSS overview for more information about this one.
- font-family: This is one of the things you definitely want to leave for the page style to set. Unless you have a really good reason, don’t change this.
- background and color: Changing the background color and text color could clash with the page style. And, if you change only one, it could make the text of your module unreadable.
Use Less-Specific Selectors
The power of CSS lies in its ability to define selectors that can apply to different kinds of elements, and elements in different states (selectors). For modules, your selectors should be as simple and with as low a specificity as possible. This means that they should apply to your module in the least specific way possible. For example, if your module has a class of kevins-module, your styles should all start with .kevins-module, but not with body div.kevins-module. Make sense? This will allow you to create a pleasing and usable default style for your module, but allow for page style sheets to get more specific and override your styles without a lot of extra work.
Need more examples? OK! Here’s our module markup. This is a simple static content module (without the rest of the manifest) that contains the preamble to the Constitution.
<div class="module constitution-preamble">
<div class="view constitution-preamble">
<div class="head">
<h3>The Preamble To The Constitution Of The United States of America</h3>
</div>
<div class="body">
<p><strong>We the People</strong> of the United States,
in Order to form a more perfect Union, establish Justice,
insure domestic Tranquility, provide for the common defense,
promote the general Welfare, and secure the
Blessings of Liberty to ourselves and our Posterity,
do ordain and establish this Constitution for
the United States of America.</p>
</div>
</div>
</div>
The easiest way to make “We The People” italics instead of bold (if you’re into that sort of thing) you be the following:
.constitution-preamble strong {
font-style:italic;
font-weight:normal;
}
That selector is simple, less specific than it could be, yet still will apply only within your module. If a page style wanted all strong elements to be purple and bold, they could easily override the style:
div.module strong {
color:#c90;
font-weight:bold;
}
Just adding one more HTML element to the selector makes the new one more specific and will override the module one. See how easy that was? Again, check out the CSS overview for more information.
We've created a table of recommended specificity for creating styles for modules and pages. For more information about specificity, see the CSS overview. The levels are also explained in the overview.
| level | maximum specificity | minimum specificity | all selectors should start with: |
|---|---|---|---|
| skeleton | 0,1,1,2 | 0,0,0,1 | n/a |
| module | 0,0,5,n | 0,0,1,1 | .module-name (the class assigned when you created the module) |
| page | 0,n,n,n | 0,1,0,0 | #page (need to look @ this one again) |
| user | 0,n,n,n | 0,2,0,0 | #page #content (since all user styles will be around modules and all modules will be inside of #content) |
Browser Support
For this phase of development, we’re supporting Firefox 1.0.7-1.5 and Internet Explorer 6.0+. You should aim for those too, and you should try to support Apple’s Safari. It will be supported by the time we get to Beta.
Performance
Here are a couple of tips on performance:
- Keep your JavaScript as localized as possible. Don’t create a file for every function. Limit yourself to one CSS and one JavaScript file per module. This will greatly benefit the end user in terms of download time and overall performance.
- Go light on the comments. If you have properly (neatly) formatted code, descriptive semantic markup, and logical function names, you won't need too much documentation. Keep your documentation in the description and detail sections of the module’s HTML. For JavaScript, if more than 20 percent of the file is comments, move some of them to the manifest or use a compressor before uploading the module.
And here are some performance standards to follow:
- All module feeds (server-side and fetched feeds):
- Latency of no more than 500 milliseconds
- Be ready to be popular. An extremely popular module could get millions of hits per day!
- All modules
- No more than 30 KB in the module and included JavaScript (other than Publisher-standard libraries and Dojo)
- Download JavaScript only when you need it
- Smaller is better!
JavaScript
We've written a whole page on using JavaScript in modules, which should help you get on your way.
Search Engine Optimization
A search engine that indexes a page containing your module will not run the JavaScript on that page. Instead, it will index the HTML as it is received from the server. If you want your dynamic data to be indexed, you have two choices:
- Use a server-side module. Because the data is included on the server, it is placed into the page before the search engine sees it. Therefore, it will be indexed.
- Have your module include searchable data in the page. The search engine sees whatever is saved in the page. Your module can save things to the page when it is in edit mode. So any time you are in edit mode, put something reasonable and searchable in the page.
Localization of Modules
Our expectation is that a given module will live in only one locale. If you want a module to exist in multiple locales, create a different version of the module for each locale.
Updating Modules
Once a module is on a page, it's there forever. There is no way to go back and update the HTML that is in the module.
If you want to allow yourself to make changes to your module, you have to design the module correctly. That means doing one of the following:
- Use a server-side module. You can make any changes you want on your server.
- Put code that might change into an included JavaScript file. Do not put it directly in the module. You can change an included JavaScript file.
But note: You can change a module in these ways, but it isn't a good idea. Changing a module means that you change the user's page in ways that he did not expect. That's okay if you're fixing a bug. But think carefully about making any changes that will change the user's page.
Security Issues
For feeds used by modules taken out of the AIM Pages Publisher Tool, you can always know what user was viewing the page that requested the feed. But you can't always know what page the user was viewing when he requested that feed. And it is possible for someone to write JavaScript that hijacks your feed and uses it in a different context than you intended.
Let's look at an example. Suppose MyCommentModule uses a feed that allows users to add comments to a page via Ajax Bob adds MyCommentModule to his page, and viewers of that page can add comments.
But Vlad decides that he wants to spam Bob's comments page. So Vlad puts up a page that contains hidden JavaScript that uses the MyCommentModule Ajax feed to add comments to Bob's page. If Jill views Vlad's page, a comment is added to Bob's page that has Jill as its author.
In some cases, like a comment module, the results of this aren't too bad. But in some cases, such as a module that changes a back-end data store that should be secure, this is a potential problem.
The important note here is that module and feed security is tricky. You need to give it a lot of thought.
Error Handling
Your module should do something reasonable even if its feeds have problems. There are two parts to this:
- Server-side modules must do something reasonable if the server feed does not arrive. This means putting something reasonable in the module's DIV. Normally, this is overwritten by the server include. But if the server fails to return, the page viewer sees what is in the module's DIV.
- Client-side modules must do something reasonable if their feeds have problems.
Clean Up After Your Module
A user may want to remove your module from his page. When that happens, the module receives a notification via the TBD event. Make sure you clean up any server-side resources associated with your module when you receive that event.
But don't move too quickly! You only want to clean up the server-side resources when the user saves the page without the module on it. When that happens, your module receives a TBD event. If you clean up things immediately, you run the risk of having the user delete the module but not saving the page. This means that the module is still on the page and needs its server-side resources.