Good example of a jQuery demo with two rewrites

This post is more than 2 years old.

Whenever I see something interesting, UX wise, I consider writing it myself with jQuery, just to see if I can. Last night I did this, posted the code, and got some great rewrites from other folks in the jQuery community. I thought it would be fun to share both my version and theirs so folks can see how differently problems can be solved. I've said this many times in ColdFusion sessions. There's multiple ways to get things done. I guess it's no surprise the same applies to jQuery as well. The ... effect... widget... user experience I wanted to mimic is something I've seen on Slashdot. Slashdot's home page consists of a set of articles. I assume most of my readers have visited Slashdot but if you haven't, notice how the articles are either expanded or opened up. If you click on the title of an opened article, you are taken to the detail page with comments. If you click on the title of a closed article, first the summary opens up, and on a second click you are sent to the detail page.

Ok, so it's not rocket science. But I thought it was interesting and decided to whip up a quick demo:

<html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(document).ready(function() {

$(".collapsed").each(function(idx) {
	console.log("found one");
	//find all the children and hide them
	var kids = $(this).children();
	//hide everything
	$(kids).hide();
	//assumes top level item is our title
	$(kids[0]).show();
	//add click handler
	$(kids[0]).click(function(e) {
		console.log("click");
		//so - if our parent's children are hidden, show them
		//if they are visible, follow the link
		var parent = $(this).parent();
		var kids = parent.children();
		if($(kids[1]).is(":visible")) {
			var link = $("a",kids[0]).attr("href");
			window.location.href = link;
		} else {
			$(kids).show();
		}
	});
});

}) </script> <style> .collapsed { background-color: #f0f0f0; padding: 0px; } .collapsed h2 { border-style:solid; border-width:thin; cursor:pointer; background-color: #d0d0d0; padding: 6px; } .collapsed h2 a { text-decoration: none; color: black; } </style> </head>

<body>

<div class="collapsed"> <h2><a href="http://slashdot.org">Test Title</a></h2> <p> Summary content </p> </div>

<div class="collapsed"> <h2><a href="http://slashdot.org">Test Title2</a></h2> <p> Summary content2 </p> </div>

</body> </html>

If you look at the bottom, you can see two divs with a collapsed class. I've got an h2 on top representing a title and the summary as a paragraph beneath it. Now jump up to the code.

I begin by finding all my items with the collapsed class. I grab a pointer to all the kids via the children() operator. I then hide all of them and show the first one. This code basically assumes the first child is a title and all the rest are simply paragraphs.

Next I add a click handler to that top item. When clicked we do two things. We go up to get the parent and then grab the kids again. The second child is a paragraph. If hidden, it means we need to show all of them. If visible, we follow the link.

Test it out below...

So I tweeted demo last night and got replies from Doug Neiner and Jeremy Battle. First let's look at Doug's. This is my first time doing a jsfiddle.net embed, so forgive me if it doesn't work right:

This is pretty different. For the most part it makes sense to me, but this line threw me:

document.documentElement.className += " js";

It looks like it applies the "js" class name to everything in the document. I assume this wouldn't work if you had other DOM items you didn't want to use this behavior. Now let's look at Jeremy's:

This one's even smaller. It's much more direct then my version as well.

Anyway - I hope sharing three versions of the same code is interesting to folks. I really feel like I can do anything with jQuery now - but I really want to learn nicer ways of doing thing. "Nicer" is in the eye of the beholder of course, but I like both of these versions better than mine.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Dan G. Switzer, II posted on 4/25/2011 at 5:55 PM

@Raymond:

The purpose of the following line is to add a "js" class to the <html> tag:

document.documentElement.className += " js";

For their code sample, this style doesn't have any effect. However, what it allows you to do is provide your elements with a CSS style to show elements in a collapsed state by default.

So, if you add a style like:

html.js .collapsed {
display: none;
}

Then any browser w/JS enabled would see the headings collapsed. For browsers w/JS *disabled* the elements would show expanded.

Comment 2 by Raymond Camden posted on 4/25/2011 at 5:57 PM

Well hot damn. That is slick and DOES make sense. Thanks Dan.

Comment 3 by Dan G. Switzer, II posted on 4/25/2011 at 6:03 PM

What's nice is you can add that line anywhere after the <html> tag, so you can put it at the top of your document output stream to ensure the browser renders the design based upon the state of JS being available or not.

Comment 4 by JP posted on 4/25/2011 at 7:14 PM

Ray, a few weeks ago one of your readers posted an article (in a comment thread) about why you should never use the .live() method: http://jupiterjs.com/news/w...

Are you still thinking that it's okay to use the .live() method? When I read stuff like that, I get scared and lean towards the "better" way, which I believe is using .delegate().

Comment 5 by Raymond Camden posted on 4/25/2011 at 7:22 PM

JP - I tend to take a practical view of things. In cases where A is better than B but B still works, I don't get scared about forgetting to use B. I don't think that - for most of us - the difference in live vs delegate is going to make a large difference. We aren't - again - most of us - building GMail.

I'm probably going to be flamed righteously for that. ;) Please remember - I've been doing CF for 10+ years. I've been getting "heavy" into JS a lot shorter. Consider my code the code of a noob.