O'Reilly

MooTools Zebra Table Plugin

By on  

I released my first MooTools class over a year ago. It was a really minimalistic approach to zebra tables and a great first class to write. I took some time to update and improve the class.

The XHTML

<table class="list-table" cellpadding="0" cellspacing="0">
	<tr>
		<th><b>Award</b></th>
		<th><b>Actor</b></th>
		<th><b>Film</b></th>
	</tr>
	<tr>
		<td>Actor In A Leading Role</td>
		<td>Daniel Day-Lewis</td>
		<td>There Will Be Blood</td>
	</tr>
	<tr>
		<td>Actress In A Leading Role</td>
		<td>Marion Cotillard</td>
		<td>La Vie en Rose</td>
	</tr>
	<tr>
		<td>Actor In A Supporting Role</td>
		<td>Javier Bardem</td>
		<td>No Country For Old Men</td>
	</tr>
	<tr>
		<td>Actress In A Supporting Role</td>
		<td>Tilda Swinton</td>
		<td>Michael Clayton</td>
	</tr>
	<tr>
		<td>Directing</td>
		<td>Joel Coen and Ethan Coen</td>
		<td>No Country For Old Men</td>
	</tr>
</table>

You may have as many tables as you want.

The CSS

.highlight			{ background:#d5fcdc; }
.even					{ background:#fff; }
.mo					{ background:#e3f1fb; }
.odd					{ background:#eee; }
.list-table th		{ padding:5px; background:#ddd; border-bottom:1px solid #999; text-align:left; font-weight:bold; }
.list-table td		{ padding:5px 20px 5px 5px; border-bottom:1px solid #ddd; }

The above are the classes are configurable using the plugin's options.

The MooTools JavaScript

var ZebraTable = new Class({
	//implements
	Implements: [Options,Events],
	
	//options
	options: {
		elements: 'table.list-table',
		cssEven: 'even',
		cssOdd: 'odd',
		cssHighlight: 'highlight',
		cssMouseEnter: 'mo'
	},
	
	//initialization
	initialize: function(options) {
		//set options
		this.setOptions(options);
		//zebra-ize!
		$$(this.options.elements).each(function(table) {
			this.zebraize(table);
		},this);
	},
	
	//a method that does whatever you want
	zebraize: function(table) {
		//for every row in this table...
		table.getElements('tr').each(function(tr,i) {
			//check to see if the row has th's
			//if so, leave it alone
			//if not, move on
			if(tr.getFirst().get('tag') != 'th') {
				//set the class for this based on odd/even
				var options = this.options, klass = i % 2 ? options.cssEven : options.cssOdd;
				//start the events!
				tr.addClass(klass).addEvents({
					//mouseenter
					mouseenter: function () {
						if(!tr.hasClass(options.cssHighlight)) tr.addClass(options.cssMouseEnter).removeClass(klass);
					},
					//mouseleave
					mouseleave: function () {
						if(!tr.hasClass(options.cssHighlight)) tr.removeClass(options.cssMouseEnter).addClass(klass);
					},
					//click 
					click: function() {
						//if it is currently not highlighted
						if(!tr.hasClass(options.cssHighlight))
							tr.removeClass(options.cssMouseEnter).addClass(options.cssHighlight);
						else
							tr.addClass(options.cssMouseEnter).removeClass(options.cssHighlight);
					}
				});
			}
		},this);
	}
});
	
/* do it! */
window.addEvent('domready', function() { 
var zebraTables = new ZebraTable();
});

The improvements to this class include:

  1. General MooTools style consistency
  2. CSS class flexibility
  3. Checks to make sure the table heading rows (rows with "th") are untouched
  4. You may use the zebraize method after class initialization
  5. Table highlighting has been separated

The class is still very basic. This plugin does not contain sorting functionality nor was it designed to.

Need basic table highlighting? Download it!

Track.js Error Reporting

Recent Features

  • Serving Fonts from CDN

    For maximum performance, we all know we must put our assets on CDN (another domain).  Along with those assets are custom web fonts.  Unfortunately custom web fonts via CDN (or any cross-domain font request) don't work in Firefox or Internet Explorer (correctly so, by spec) though...

  • Creating Scrolling Parallax Effects with CSS

    Introduction For quite a long time now websites with the so called "parallax" effect have been really popular. In case you have not heard of this effect, it basically includes different layers of images that are moving in different directions or with different speed. This leads to a...

Incredible Demos

  • Create a NoScript Compatible Select Form Element with an onChange Event

    I wouldn't say that I'm addicted to checking Google Analytics but I do check my statistics often. I guess hoping for a huge burst of traffic from some unknown source. Anyway, I have multiple sites set up within my account. The way to...

  • MooTools Font-Size Scroller with Cookie Save

    Providing users as many preferences as possible always puts a smile on the user's face. One of those important preferences is font size. I can see fine but the next guy may have difficulty with the font size I choose. That's why...

Discussion

  1. Seeing how you can accomplish this with some CSS, PHP + Modulo operator and loop I’m not sure how much sense it makes to rely upon JS to do this task for you.

    Unless you’re not exporting items from a database. But if that’s the case, then your tables will most likely be short anyways making it easy to just add the class names yourself to alternating rows.

    Cool, and works well but I still ask myself if JS is really the tool to rely on for the job…..

    // Tim

  2. Jacob

    click function can be made simpler…

    click: function() {
        tr.toggleClass(options.cssMouseEnter).toggleClass(options.cssHighlight);
    }
    
  3. @Jacob: I believe I had that at first but the cssHighlight was causing issues once the item had been clicked off.

  4. Jacob

    @Tim you can’t do this with CSS if it is to work the same in IE 6 & 7 tho can you?

  5. @Jacob: You couldn’t with the hover — IE6 wouldn’t like that. In my opinion, adding special classes/colors in PHP is really ugly, although a tad safer than JS.

  6. nice tutorial! additional information for me! thanks.

  7. Alexander

    Great plugin!, already implemented it.

    However, i would like to know how do i do if i want the previous selected row to go back with the previous tag once i click or select another row.

    Regards,
    Alex!

  8. Cool, and works well but I still ask myself if JS is really the tool to rely on for the job…..

    I think it’s ok in this case, it’s only for aesthetic, so leaving this job to the client side, even though it’s not a huge task for the server, sounds like a good idea.

  9. Ahmed

    Omg, you have no idea how much pain in the ass this will save me

  10. Nice work! But, I have a question. Is this posible to make something like this for definitions lists?

  11. @Hiway: Yep, you’ll just need to modify the class to look for the proper XHTML tags.

  12. @David Walsh: Thanks, David! That’s OK. But, in your JS code you are working basically only with <tr>-element, and almost the whole formating applying to this element. In that time, when in the list of definitions we don’t have general element for <dt> & <dd> exept <dl>, but one list of definitions can have many <dt> & <dd>, and exactly for these ones we need to apply a “Zebra” formating.

  13. @david: Why aren’t you just using CSS3 nth-child selectors (http://tinyurl.com/czhlp2)? MooTools support CSS3, and zebra striping is quite easy with CSS3-selectors.

    I’ve made a rough example with mootools here: http://ljd.dk/loot/mootables.html. I’ve only tested in FF3, IE8 and IE8 compatability view, but so far it seems to works just like yours with less code.

    Maybe I’m misunderstanding something, but imho it wouldbe easier to use CSS3 selectors. Thanks for a great blog!

  14. This is way easier with jQuery if you want to follow the JavaScript route.

    eg: $("myTable tr:odd).css("background-color", "#000"); would colour the odd rows.

  15. @Phil: Writing that in Moo would be just as short — my class does much more than simple color every odd row differently.

  16. Nice!

    I would use <thead> for the headers and <tbody> for the data rows, and that way save the <th> check.

  17. Matt

    Hmm it would be very cool if the zebratable are dynamically. A function for addRow or something like this :)

    I tried to make but without success :/

  18. I’ve been modifying this plugin somewhat for a project I am working on, and I’ve encountered some problems with it.

    The project I am working on involves hierarchical data in a table, arranged as a series of ‘entry’ rows and ‘folder’ rows. Clicking on a folder row hides or shows the corresponding hierarchy of entries or subfolders. This was easy enough, but I wanted to use this class to recolour the table rows dynamically (as hiding a bunch of rows may throw off the zebra effect).

    Modifying the code so that it checked for tr.style.display != 'none' was trivial, as was adding the extra voodoo to make the zebra effect work independently of row number, but then I found the code did not work reliably after more than one call.

    The problem was actually something I should have noticed from the start: zerbarize() does tr.addClass(klass).addEvents( ... ); *but it doesn’t remove the style classes or events before doing so*, so each call to zebraisze() is just adding classes and event handlers rather than replacing the existing ones!

    In the end, I used the following code:

    var options = this.options, klass = pos % 2 ? options.cssEven : options.cssOdd;
    
    // We might not know which class we have (if any), so check for either
    if(tr.hasClass(options.cssEven)) {
        tr.removeClass(options.cssEven);
    } else if(tr.hasClass(options.cssOdd)) {
        tr.removeClass(options.cssOdd);
    }
    
    // This is rather harsh, but provided the only events get added in zebraize() 
    // it should be safe enough...
    tr.removeEvents();
    
    //start the events!
    tr.addClass(klass).addEvents(..... etc....
    

    I can link you to a pastebin of the complete modified version if you’re interested.

  19. Heikki Naski

    “Seeing how you can accomplish this with some CSS, PHP + Modulo operator and loop I’m not sure how much sense it makes to rely upon JS to do this task for you.”

    Outputting the stripes server-side, you’d need to add that bit of logic to every table you output. It’s not much code, about 5 rows, but it’s duplication nonetheless and requires testing each table separately. Using JS to modify all tables of say, given class or id, you’d have the logic in just one place, with the benefits of centralized control.

    Of course, if you happen to have a method of generating the tables through a single routine in the server-side code, you’d then only have to code the striping once, but a lot of us don’t probably have that luxury always, especially with legacy apps.

    Using PHP would obviously work without JS, so it all depends on can you trust the user to have JS on.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • OSCON Portland:  Conference  Discount!

    O'Reilly puts on the best web industry conferences in the world.  These conferences include Fluent Conference, Velocity Conference, and the upcoming OSCON in Portland, Oregon from July 20-24.  Open Source Convention (OSCON) is a conference that focuses specifically on open source developers and the tools and possibilities...

  • Follow Redirects with cURL

    I love playing around with cURL. There's something about loading websites via command line that makes me feel like some type of smug hacker, just like tweeting from command line does. I recently cURL'd the Google homepage and saw the following: I found it weird that Google...

  • Developers Have WordPress, Amateurs Have Squarespace, Professional Designers Have the NEW Webydo!

    Web design platforms have traditionally come in one of two varieties. There are the solutions like WordPress and Drupal that are incredibly powerful, but an understanding of web development and coding is required to be able to use those platforms effectively. On the other side of the...

  • Chris Coyierâs Favorite CodePen Demos II

    Hey everyone! Before we get started, I just want to say it’s damn hard to pick this few favorites on CodePen. Not because, as a co-founder of CodePen, I feel like a dad picking which kid he likes best (RUDE). But because there is just so...

  • GSAP + SVG For Power Users: Motion Along A Path

    Now that the GreenSock API is picking up steam, there are many tutorials and Getting Started guides out there to provide good introductions to the library, not to mention GreenSock’s own Forum and Documentation. This article isn’t intended for beginners, but rather a...