Showing posts with label unobtrusive. Show all posts
Showing posts with label unobtrusive. Show all posts

Tuesday, October 7, 2008

JavaScript Zebra Stripes: Alternate Background Colors on Tables and Lists

Love it or hate it, alternating background colors is a common design request for web designers. If you maintain a site of static HTML files, this "zebra striping" effect can become time consuming and tedious. Even if you use a content management system or a server side language, automation is your friend. This script is the automation you want.

There are tons of similar scripts on the Internet, and all do a great job. I've found they have some short comings. I don't always just want to alternate background colors on table rows. I often do not want cells in the table header and footer to have alternating colors either. Things get real messy when I want alternating colors on list items, and especially definition lists. This script package seeks to solve all these problems.

Browser Support

All standards compliant browsers are supported, as well as Internet Explorer version 5.0 and newer. If the browser supports the *.getElementsByTagName method, then the browser supports this script. This is also safe to use with any pre existing JavaScript library or framework. It packages all the related functions into an object called stripes. As long as you don't have a global variable or function named "stripes," this is safe to use, and since it utilizes only standard DOM API calls, no additional JavaScript libraries are required.

Using the stripes functions

Usually you'll want some sort of JavaScript event to kick things off. I recommend the onload event if you don't use a JavaScript framework like Mootools or jQuery. A simple function call in the onload attribute of the body tag will suffice:

<body onload="stripes.execute();">

For those who like unobtrusive JavaScript, you can add this to the window.onload function:

window.onload = function() {
stripes.execute();
};

The stripes.execute() function will parse the entire document object model. For very large HTML files, you might not want the function parsing the entire DOM tree. You can specify a root DOM element from which to start searching by passing an HTML tag Id or DOM node reference to the stripes.execute() function. If no argument is passed, or the Id passed does not exist in the HTML document, then the document element is used.

// Only search in <div id="content">

window.onload = function() {
stripes.execute( "content" );
};

/* --- OR --- */

window.onload = function() {
var contentNode = document.getElementById( "content" );
stripes.execute( contentNode );
};

How it works

The only thing this script package does is change class names on DOM node elements. For tables, a class name is assigned to the <tr> tag. For unordered and ordered lists, the class name is assigned to the <li> tag. Lastly, for definition lists the class name is assigned to the <dt> and <dd> tags. All you need to do is add style rules to your CSS.

The script comes preprogrammed with two class names. Even rows or list items are given the class "rowA". Odd rows or list items are given the class "rowB". You can easily change the class names in the JavaScript source code. Below is a snippet showing you where you can change these default class names:

window.stripes = {

stripeRowEven : "rowA",
stripeRowOdd : "rowB",
stripeParentClass : "stripes",


...

};

The stripeRowEven and stripeRowOdd properties contain the class names assigned to table rows, list items, and definition terms and descriptions. The third property, stripeParentClass, is the class name the script will search for when making the zebra stripes. As mentioned earlier, this script works for tables, unordered lists, ordered lists and definition lists:

HTML Structure Supported for TABLEs
<table cellpadding="5" cellspacing="0" border="1" class="stripes">
<thead>
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
<th>Heading 3</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Footer 1</th>
<th>Footer 2</th>
<th>Footer 3</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>Cell 1.1</td>
<td>Cell 1.2</td>
<td>Cell 1.3</td>
</tr>
<tr>
<td>Cell 2.1</td>
<td>Cell 2.2</td>
<td>Cell 2.3</td>
</tr>
</tbody>
</table>
HTML Structure for Lists
<ul class="stripes">
<li>List Item 1</li>
<li>List Item 2</li>
</ul>

<ol class="stripes">
<li>List Item 1</li>
<li>List Item 2</li>
</ol>

<dl class="stripes">

<dt>Definition Term 1</dt>
<dd>Description 1.1</dd>
<dd>Description 1.2</dd>

<dt>Definition Term 2</dt>
<dd>Description 2.1</dd>
<dd>Description 2.2</dd>
<dd>Description 2.3</dd>

</dl>

You'll notice that with the <dl> tags you can specify more than one <dt>, and more than one <dd> per definition term. After the script runs, the tables and lists will be given this HTML structure:

Tables, after scripts.execute()
<table cellpadding="5" cellspacing="0" border="1" class="stripes">
<thead>
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
<th>Heading 3</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Footer 1</th>
<th>Footer 2</th>
<th>Footer 3</th>
</tr>
</tfoot>
<tbody>
<tr class="rowA">
<td>Cell 1.1</td>
<td>Cell 1.2</td>
<td>Cell 1.3</td>
</tr>
<tr class="rowB">
<td>Cell 2.1</td>
<td>Cell 2.2</td>
<td>Cell 2.3</td>
</tr>
</tbody>
</table>
Lists after stripes.execute()
<ul class="stripes">
<li class="rowA">List Item 1</li>
<li class="rowB">List Item 2</li>
<li class="rowA">List Item 3</li>
</ul>

<ol class="stripes">
<li class="rowA">List Item 1</li>
<li class="rowB">List Item 2</li>
</ol>

<dl class="stripes">

<dt class="rowA">Definition Term 1</dt>
<dd class="rowA">Description 1.1</dd>
<dd class="rowA">Description 1.2</dd>

<dt class="rowB">Definition Term 2</dt>
<dd class="rowB">Description 2.1</dd>
<dd class="rowB">Description 2.2</dd>
<dd class="rowB">Description 2.3</dd>

</dl>

Styling the zebra stripes with CSS

With a small amount of CSS, you can style your zebra stripes.

.rowA {
background-color: #f0f0f0;
}

.rowB {
background-color: #d0d0d0;
}

You can change how tables and lists are displayed by using different CSS selectors:

tr.rowA {
background-color: #f0f0f0;
}

tr.rowB {
background-color: #d0d0d0;
}

li.rowA {
background-color: #fccccc;
}

li.rowB {
background-color: #dccccc;
}

dt.rowA {
background-color: #000;
color: #fff;
}

dd.rowA {
background-color: #505050;
color: #fff;
}

dt.rowB {
background-color: #ccc;
color: #000;
}

dd.rowB {
background-color: #d0d0d0;
color: #000;
}

Download the stripes JavaScript source code

  1. Click on the box below to highlight the code.
  2. Copy it.
  3. Paste it into a blank text file.
  4. Save it as package.stripes.js
  5. Include it in your HTML documents using a <script src=""> tag.

Who can use this script

The short answer? Anyone. It's released under the LGPL license and is free for commercial and non commercial use. Let's face it, this isn't ground breaking stuff here, so copy it. Distribute it. Use it. But always include some form of recognition and never claim it as your own. If you feel so inclined, link back to this page. If you have comments, suggestions or problems, post them below.

Friday, September 28, 2007

TextEditor: Free Unobtrusive JavaScript Code Editor Supporting Web Standards

Easily create a JavaScript enhanced code editor with any TEXTAREA that includes auto-indent, tab stops, auto-complete, XHTML compatibility and more. Did I mention it's free?

I've worked with several older web-based content management systems, that store template code in a database. That means writing HTML in a TEXTAREA. Yuck! Many of them have been updated to include a WYSIWYG editor, be it Java or JavaScript-based. As good as they are, I still yearn for code. Pure, unadulterated, geeky, I'm-in-total-control ... code.

Even with a fancy WYSIWYG editor at my disposal, I turn it off. A plain old TEXTAREA will suffice, but I miss the coding assistance of a real text editor like HTML Kit. I want complete control of my code, and I want a smart code editor all on a Web page. So I built one.

Features of the JavaScript TextEditor:
  • Unobtrusive JavaScript. No need to clutter up your HTML with event handlers.
  • Object-oriented JavaScript. Helps keep the global JavaScript namespace clean and tidy, and simplifies interacting with the editor using JavaScript.
  • Create as many code editors as you want. Want more than one code editor on a page? No problem. Have as many as you want.
  • Create HTML tags in upper or lower case. The HTML 4.01 doctype declares HTML tags in upper case even though they aren't case sensitive. You can have it either way.
  • Set tab stops. When you press the TAB key, it inserts enough spaces to get to the next tab stop. Nice for indenting code.
  • Block Indent. Select several lines of code and hit the TAB key to indent all the lines, or hold the Shift key and hit TAB to unindent each line by one tab stop.
  • Auto-Indent. When you press the ENTER or RETURN keys, the cursor and code is indented automatically to where you were on the previous line.
  • Auto-Complete. Greatly speed up your coding by typing an HTML tag name, highlighting it, then holding the Ctrl and Shift keys down and pressing the "<" key. BAM! Automatic opening and closing tags are created, plus commonly used attributes, and applicable child tags.
  • XHTML compatible. The auto complete feature is XHTML aware.
  • Tabify and Detabify. Did someone actually use real TAB characters to indent the code!? *gasp* Functions are included to convert those pesky tabs to tab stops, and then back again. You'll have to provide the button and the onclick, but the function is available.
  • Escape and Unescape HTML. Does just what it says: Converts "&", "<" and ">" characters to HTML entities, and you can change them back again. Of course you'll need to supply your own button and onclick, but the function is there.
  • Convert newlines to <br> and <p>. Select a bunch of text, and a function can convert all newline characters to page break and paragraph tags. You'll need to create the button and onclick.

The JavaScript TextEditor is completely customizable. When creating it, you can pass several options on a case-by-case basis so every editor can be different.

Browser support for version 0.1

It's an early version and works only in Opera and Firefox on Windows. I tested Safari 3.03 on Windows and found a bug . The Control, Shift and Alt keys do not generate keydown, keypress or keyup events on TEXTAREA's, so the auto complete feature doesn't work, but tab stops and auto indent do. I've reported the bug to Apple.

Mac OS support is upcoming. I need to turn off my PC and fire up my Mac. TextEditor might work on Mac OS right now, but I'll have to double check the keyCodes generated by the event object so the Control, Shift and Tab keys are captured properly.

Internet Explorer users? Well. Your browser sucks and doesn't support the standard methods used to manipulate text in the TEXTAREA, but fear not, Internet Explorer support is pending too. But enough yackin', let's see the code:

Source code for the JavaScript TextEditor

Just click on the box below to select it, then copy.

Implementing the TextEditor

Save the JavaScript code above as TextEditor.js and include it in the HEAD of any page you want JavaScript enhanced TEXTAREA's.

<script type="text/javascript"
src="TextEditor.js"></script>

Next, you will need a TEXTAREA:

<textarea name="body" cols="65" rows="20"
id="body_source"></textarea>

Lastly, you'll need a bit of JavaScript in the HEAD of your HTML document to get things rolling:

<script type="text/javascript">
window.onload = function() {
window.CodeEditor = new TextEditor("body_source");
};
</script>

You can then access that instance of the TextEditor with the global JavaScript variable CodeEditor.

alert(CodeEditor.version);
Future development of TextEditor

In stock for the first full release, version 1.0, is support for Mac OS and Linux. Next up for version 2.0 is support for Internet Explorer 5.5 and newer. I will also be writing an add-on class to create a user interface for TextEditor, which will create a semi-WYSIWYG interface. Think the point and click BB Code editors you see in popular forum software, meets Dreamweaver — and all in your Web browser. Since the basic functionality of the code editor is separate from the user interface, you can have just the code editor, or a full-blown point and click code editor. Upcoming features are:

  • Mac OS and Linux browser support
  • Internet Explorer support
  • Point and click user interface to assist coding
  • Full documentation
  • Downloadable JavaScript files: Uncompressed with documentation, uncompressed without documentation, packed, obfuscated, and both packed and obfuscated.
  • Live preview. Will not require AJAX.
Who can use TextEditor

This script is released under the LGPL license and is free for commercial and non-commercial use. This is still in development so check back again for updates. Any updates to this script will be posted on this blog post.