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!

O'Reilly Velocity Conference
Save 20% with discount code AFF20

Recent Features

  • 6 Things You Didn&#8217;t Know About Firefox OS

    Firefox OS is all over the tech news and for good reason:  Mozilla's finally given web developers the platform that they need to create apps the way they've been creating them for years -- with CSS, HTML, and JavaScript.  Firefox OS has been rapidly improving,...

  • Page Visibility API

    One event that's always been lacking within the document is a signal for when the user is looking at a given tab, or another tab. When does the user switch off our site to look at something else? When do they come back?...

Incredible Demos

  • Telephone Link Protocol

    We've always been able to create links with protocols other than the usual HTTP, like mailto, skype, irc ,and more;  they're an excellent convenience to visitors.  With mobile phone browsers having become infinitely more usable, we can now extend that convenience to phone numbers: The tel...

  • Color Palette Generator Using jQuery

    As I continue to learn jQuery, I think it's important that I begin by porting over scripts I've created using MooTools. One of those scripts is my Color Palette Generator script, which debuted on Eric Wendelin's blog. For those of you that...

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

  • Access Mac Camera by Command Line

    With all of my recent command line tutorials, I've really gotten excited about the shell's simplicity and realized the true power of using the underlying technology of pretty UIs.  Since I work from home, I spend a lot of time on video calls, so when...

  • Open Files from Command Line on OS X

    I'm as much of a fan of application UIs as anyone else but I'm finding myself working more and more from the command line lately.  Much of that is becoming obsessed with media manipulation but I'm forcing myself to use less UIs so that I...

  • Get Stock Quotes From Command Line

    When I conned my way into my first professional programming gig, I didn't really think much about money -- just that I was getting my foot in the door.  But as my career has gone on, I've been more aware of money, investing, and retirement.  I've recently...

  • Geolocation API

    One interesting aspect of web development is geolocation; where is your user viewing your website from? You can base your language locale on that data or show certain products in your store based on the user's location. Let's examine how you can...

  • Create an Image Preview from a Video

    Visuals are everything when it comes to media.  When I'm trying to decide whether to watch a video on Netflix, it would be awesome to see a trailer of some kind, but alas that isn't available.  When I'm looking to download a video on my computer,...