with Imagination: by Dustin Diaz

./with Imagination

A JavaScript, CSS, XHTML web log focusing on usability and accessibility by Dustin Diaz

Collapsable effects with Script.aculo.us

Saturday, December 31st, 2005

Want to get that cool effect as demonstrated on this website from when a user clicks on the code block and it slides up and fades out? Well, assuming you’re interested anyway - I’ll show you just how I accomplished that by only using Prototype and Script.aculo.us. That’s right, I won’t be forcing you to grab from that common library. We’ll be using all the tools provided from these two libraries as needed such as the Event.observer, the Element object, even the getElementsByClassName prototype so you won’t need to use my own custom function for that matter.

The Object Game

As you might have guessed, this will of course be in my favorite syntax of object notation taking the form of an object literal to speed up the process.

So first off, let’s get a little sample of what we’re actually producing here. If you’re not reading this article through an RSS reader - go ahead and click on the head of the following code block:

Click Here for Demonstration

/* Sample CSS code */
h3.code,pre {
  color:#444;
  font:12px/1.1em 'courier new',courier,monospace;
  width:90%;
}
h3.code {
  background:#e3c78b;
  text-align:right;
  padding:2px 3px;
}
pre {
  padding:10px;
  overflow:hidden;
}

Great, so now that we know what we’re doing here, let’s see exactly what we need to do.

First things first

Like any other Prototype/Script.aculo.us tutorial - the first thing you’ll always see is that you need to do the following:

Reference your JavaScript

<head>
...
<script type='text/javascript' src='/js/prototype.js'></script>
<script type='text/javascript' src='/js/scriptaculous.js'></script>
...
</head>

With that done, now we can get right down to business. This is going to be short and sweet, so pay attention.

Building up the cd object

var cd = {
	codes : Array,
	init : function() {
		cd.codes = document.getElementsByClassName('code','contentBody');
		cd.attach();
	},
	attach : function() {
		var i;
		for ( i=0;i<cd.codes.length;i++ ) {
			Event.observe(cd.codes[i],'click',cd.collapse,false);
			Element.cleanWhitespace(cd.codes[i].parentNode);
		}
	},
	getEventSrc : function (e) {
		if (!e) e = window.event;
		if (e.originalTarget)
			return e.originalTarget;
		else if (e.srcElement)
		return e.srcElement;
	},
	collapse : function(e) {
		var el = cd.getEventSrc(e).nextSibling;
		if ( Element.hasClassName(el,'closed') ) {
			new Effect.Parallel(
				[
					new Effect.SlideDown(el,{sync:true}),
					new Effect.Appear(el,{sync:true})
				],
				{
					duration:1.0,
					fps:40
				}
			);
			Element.removeClassName(el,'closed');
		} else {
			new Effect.Parallel(
				[
					new Effect.SlideUp(el,{sync:true}),
					new Effect.Fade(el,{sync:true})
				],
				{
					duration:1.0,
					fps:40
				}
			);
			Element.addClassName(el,'closed')
		}
	}
};
Event.observe(window,'load',cd.init,false);

That’s it! Simple as that. Of course we wouldn’t learn anything if there was no explanation. So let’s look at it step by step.

  1. We can see that first this whole thing is named ‘cd’. Just a simple way to keep the object name nice and short for anytime we need to reference it.
  2. The bottom of this snippet of code reveals that we’re adding cd.init() to run upon the window ‘load’ event using the Event.observe method provided by Prototype.
  3. Now we declare codes as an array which eventually becomes a reference to all our header elements with a className of ‘code’.
  4. Next we fire the attach method of the cd object which assigns the collapse method to fire on the ‘click’ event for all of the element headers.
  5. Simutaneously while looping through the code headers we run the Element.cleanWhitespace method on it’s parent node so we can properly access our pre element a bit later on.
  6. Upon getting fired, the collapse method checks to see where it’s ‘click’ came from with the cd.getEventSrc method.
  7. Then we do a check to see if the element has a className of ‘closed’ - if it does, then we open up our code blocks using the Effect.SlideDown and Effect.Appear methods.
  8. If the code block does not have the className we checked for, then we close it up by running the Effect.SlideUp and Effect.Fade methods on the pre element and assign it a className of ‘closed’ appropriately.

All done. Pretty cool eh?

Todays question and book information

JavaScript complete reference

The winner of today’s contest will receive a copy of JavaScript: The Complete Reference by Thomas Powell and Fritz Schneider.

Put together an “Ode to my underwear” in exactly four lines. (Yours, not mine)

Please remember to put your answers encapsulated within a <blockquote> element, and the regular discussion as normal.

22 Responses to “Collapsable effects with Script.aculo.us”

  1. Nate Cavanaugh

    http://moofx.mad4milk.net

    IMHO, I think the small size of the MooFX library makes it ideal for doing effects like this (if all you’re going for is effects). However, I think having the libraries is awesome if you need the extended power.

    Anyways, on to my entry :)

    Underwear, o’ underwear
    the comfy boxer brief,
    snug support and freedom when I need it,
    what an upgrade from Adam’s leaf.

  2. Dennis

    This is a really cool effect Dustin. Thanks for the tutorial! I dont know much about Java but I am interested in learning. Do you have some direction for me to enhance my skills?

  3. Jim A.

    Underwear, My Underwear
    I love my tighty-whities
    Because I need support.
    You see–life can be tough
    When you aren’t short!

  4. Dustin Diaz

    Haha. I can just tell these entries are going to be great!

    @Nate: The Moo.fx library is very cool indeed as I’ve toyed around with that one for a bit too. But I’d still keep the prototype library around for this.

    @Dennis: I’m not much of a Java guy, but if you are in fact inquiring about “JavaScript” - then I’d recommend any of the books about JavaScript all found in my Books section

  5. Dante

    Argh, I tried scriptaculous a while back and gave up in disgust. It’s just too bulky and it would not work, plus I had to add extra markup. moo.fx isn’t much better, though I do enjoy their moo.ajax framework.

    Oh, Dark Side of the Moon Boxers
    The coolest thing to wear
    Don’t care if it has a rainbow on it
    Who’s going to be looking down there?

  6. Rob

    underwear, oh how marvelous are you! From holes for legs to holes from wear, at which the other half will always dispair.In many colors and many shapes, a good male will always run out, even though they are the christmas present of choice of the “relatives”

  7. Raanan Avidor

    The way JavaScript has advanced in the last year is amazing. From the retarded sibling to a truly helpful tool.

    I love my undies, I truely, truely do.
    They hold the trueusers of my love for you.
    But my undies come second to the desire that I feel,
    for your lingerie, my lovely meal.

  8. Dante

    Raanan, JavaScript has always been a powerful tool. It just took dynamic HTTP Requests to prove it to everyone.

  9. BlogContestSite.com

    Hi Dustin,
    When does the contest end?
    Jane

  10. Jim A.

    @Dante: You are indeed correct. JS was more like the abused older brother whose siblings finally grew up and understood him. JS has been abused by web “masters” for years. Combine that with the lack of CSS in the early years, and the non-standard versions of HTML; and you had a powerful tool that looked weak and useless.

    With real developers actually getting hold of JS now and using it in a way that actually enhances pages where available, and doesn’t break them when it’s not; and CSS and HTML “growing up”; we are finaly seeing the true gracefulness and power that is JS.

  11. Nick

    From Adam’s bloom to Fruit of the Loom
    The Indian Chief’s to boxer briefs
    The male mode of undergarment comfort reigns evermore
    Quoth Ghandi’s loincloth evermore, evermore.

  12. Ryan Gahl

    Not entering the contest… just wanted to let you know that all the code in your code blocks on your site runs off the right side (when deeply nested) and gets clipped, therefore I cannot read much of the code on this page. IE 6. 1600×1200 res.

  13. Dustin Diaz

    Ryan,
    You’re seeing the result of ‘overflow:hidden’ which was done on purpose. Otherwise the code would be flying off the page which really makes things look yucky.

    If you want to really check out the code, you can copy and paste the lines you want, and surely enough, it will all be happily waiting for you on your clip board :)

  14. AC

    Hi,

    Great example! I’m trying to get it working on my dev server. I copied your source code and ofcourse I have the Prototype and Script.aculo.us libraries installed. Now when I attempt to run the example, I get the following:

    Error: Enumerable is not defined
    Source File: http://fc4dev/sandbox/scriptaculous-js-1.5.1/src/effects.js
    Line: 182

    Any idea how to fix that? What am I doing wrong?

    Thanks,

    AC

  15. AC

    Haha….I should have waited another couple of minutes. I had a mismatch between the Prototype and Script.aculo.us libraries. Either way, great site Dustin. I’ll be sure to come back regularly.

  16. bigClown

    OK, so it’s a bit late - and it’s not four lines. But it was written when I was eight, and it’s one of the three poems I can actually remember.

    Blowing in the breezes
    is a pair of underwear.
    They are drying there.

    My humble haiku, for you.

  17. Jim Amos

    Hmm, I’m sure this is great, but right now it’s not working at all. Does it use an outdated version of prototype?

  18. links for 2006-09-21 at willkoca

    […] Collapsable effects with Script.aculo.us (tags: javascript scriptaculous animation effects prototype) […]

  19. teddY

    Hi Dustin,

    Sorry for bumping this old post. But firstly, thanks for sharing this awesome code. It helped me to clear up lots of unwanted spaces taken up by codes.

    I’ve experimented with the code you’ve provided, and I found out that it only works for the “pre” “code” elements, and not others, for example, “div” or “span”. Why is this so? Is there any workaround, because I wish to implement this script for my sidebar to make it collapsable, which is made up of “div” tags only… since I do not want to include my sidebar contents in the “pre” and “code” tags.

    Thank you!

  20. Michael

    Hi Dustin - thanks a ton for posting this tutorial. I’m completely ignorant about js. Is there a way to modify the .js so the window is collapsed by default, and “opens” when clicked?

    Again, thanks so much.

  21. kunter ilalan - web developer, izmir

    sorry, Dustin was here and there but looked real busy to me, so I’m replying to your questions:

    Re:Michael;
    Yes, there are ways, as Dusting has explained clearly at the end, you can classify your TAGs as ‘closed’ so browser chooses your way at the 1st IF crossroadds.

    ...

    You can also trigger the method at the body onload

    
    window.onload = function() { new Effect.SlideDown(document.getElementById('YOUR_ID')) }
    

    Re:teddY;
    ah ted, the getElementsByClassName is for this sort of work.. see the ‘code’ there? replace it with someother (not necessarily but) block-level elements.

    Re:jim;
    Boy, you do have some problems - hey dustin, this site requires some attention :-) anyways - I’ll keep looking for more examples
    -k.

    ======= anyways

  22. the alchemist

    The explanation for implementation is unclear and unusable for me. The source code for this page varies greatly from your example as well. Can you explain what some of the unexplained items like “contentBody” refer to? How about a simple, working downloadable sample?

Leave a Reply

Phone Number:

If you're about to post code in your comment, please wrap your code with the tag-combo <pre><code>. Also please escape your html entities - otherwise they will be stripped out. I recommend using postable.

Get "JavaScript Design Patterns"

"As a web developer, you'll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power waiting to be unlocked--JavaScript is capable of full object-oriented capabilities, and by applying OOP principles, best practices, and design patterns to your code, you can make it more powerful, more efficient, and easier to work with alone or as part of a team."

Buy JS Design Patterns from Amazon.com Buy JS Design Patterns from Apress

Flickr

Submit a Prototype

All content copyright © 2003 - 2007 under the Creative Commons License. Wanna know something? Just ask.

About | Archives | Blog Search

[x] close

Loading...

Submit a prototype

By checking this prototype I agree that I am not submitting false credentials, pornography, or a hate crime website. I also understand that by submitting my entry I may or may not be accepted, and if accepted, my entry may be taken down at any given time if I violate these terms.