Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at Scotch On The Rock (SOTR) 2010 (Brussels) with: Ray Camden and Alison Huselid

jQuery Demo: Build A ColdFusion Guru

By Ben Nadel on

jQuery is just awesome. I have been playing around with it and every thing it does it just wicked cool. Over the weekend, I built this little demo to play around with adding event handlers after the DOM has loaded. This should keep my HTML mark up very clean and "informational" while at the same time allowing me to do some really cool Javascript stuff.

This demo (or rather experiment) was modelled after those children books that let you choose different head / torso / legs for a given character. Mine of course does not line everything up (I am not about to spend weeks looking for the right photos) but you get the idea. I hope no one gets offended by the graphics or heads chosen. I did not do anything on purpose - I just used whatever good pictures I could find and it's all in good fun:


 
 
 

 
Build a ColdFusion Guru  
 
 
 

Try it out for yourself here.

The above has some pretty decent functionality. But, take a look at the HTML here:

  • <h1>
  • Build-a-Guru
  • </h1>
  •  
  • <div id="build-frame">
  •  
  • <div id="head-frame">
  •  
  • <a class="previous">Previous</a>
  • <a class="next">Next</a>
  •  
  • <div class="option-frame">
  • <ul>
  • <li>Head 1</li>
  • <li>Head 2</li>
  • <li>Head 3</li>
  • </ul>
  • </div>
  •  
  • </div>
  •  
  • <div id="torso-frame">
  •  
  • <a class="previous">Previous</a>
  • <a class="next">Next</a>
  •  
  • <div class="option-frame">
  • <ul>
  • <li>Torso 1</li>
  • <li>Torso 2</li>
  • <li>Torso 3</li>
  • <li>Torso 4</li>
  • </ul>
  • </div>
  •  
  • </div>
  •  
  • <div id="leg-frame">
  •  
  • <a class="previous">Previous</a>
  • <a class="next">Next</a>
  •  
  • <div class="option-frame">
  • <ul>
  • <li>Leg 1</li>
  • <li>Leg 2</li>
  • <li>Leg 3</li>
  • <li>Leg 4</li>
  • </ul>
  • </div>
  •  
  • </div>
  •  
  • </div>

How simple is that? The CSS and lack of Javascript make it very easy to see how the document is put together. The markup has become very informational and light-weight. Now, once the document is ready, I am using the jQuery notation $( fn{} ) in order to set the Javascript. Here is that Javascript:

  • // Once, the DOM (Document Object Model) is ready to
  • // be interacted with, let's go through an initialize
  • // the main players in this build-a-guru application.
  • $(
  • function(){
  • // Get the segment width. This will be used for
  • // calculating and animating later on. While each of the
  • // segments have different heights (depending on the
  • // frame in which they are used) all segments will line
  • // up horizontally (same widths).
  • var intSegmentWidth = $( "div.option-frame:nth(0)" ).width();
  •  
  •  
  • // Let's initialize the variaous slide areas.
  • $( "//ul" ).each(
  • function( intListIndex ){
  • var jUL = $( this );
  • var jLI = jUL.children( "li" );
  • var jFrame = $( this.parentNode.parentNode );
  • var strFrameType = jFrame.attr( "id" ).replace( new RegExp( "^([^\\-]+).*$", "gi" ), "$1" );
  •  
  •  
  • // Set the width of the parent list. This should
  • // be equal to the cumulative width of all of the
  • // child list items.
  • jUL.css( "width", (jLI.length * intSegmentWidth) );
  •  
  • // Set up the background images for each slide.
  • jLI.each(
  • function( intSlideIndex ){
  • $( this ).css(
  • "background-image",
  • "url( './" + strFrameType + "_" + intSlideIndex + ".jpg' )"
  • );
  • }
  • );
  •  
  •  
  • // Start each list at a random place. To get this,
  • // we will select a ranom slide offset and then
  • // just multiply that by the width of the segments.
  • jUL.animate(
  • {
  • left: -(Math.floor( Math.random() * jLI.length ) * intSegmentWidth)
  • },
  • "fast"
  • );
  • }
  • );
  •  
  •  
  • // Let's initialize all the "Previous" action links.
  • // Each of these links needs to be able to move the slide
  • // to the right if it can.
  • $( "a.previous" ).bind(
  • "click",
  • function( objEvent ){
  • var jUL = $( this ).find( "../div/ul" );
  • var intLeft = parseInt( jUL.css( "left" ) );
  •  
  • // Check to see if we can move right.
  • if (intLeft < 0){
  •  
  • // Move the list right.
  • jUL.animate(
  • {
  • left: Math.min( (intLeft + intSegmentWidth), 0 )
  • },
  • "normal"
  • );
  •  
  • }
  • }
  • );
  •  
  •  
  • // Let's initialize all the "Next" action links.
  • // Each of these links needs to be able to move the slide
  • // to the left if it can.
  • $( "a.next" ).bind(
  • "click",
  • function( objEvent ){
  • var jUL = $( this ).find( "../div/ul" );
  • var intLeft = parseInt( jUL.css( "left" ) );
  •  
  • // Check to see if we can move it left.
  • if (intLeft > -(jUL.width() - intSegmentWidth)){
  •  
  • // Move the list left.
  • jUL.animate(
  • {
  • left: Math.max( (intLeft - intSegmentWidth), -(jUL.width() - intSegmentWidth) )
  • },
  • "normal"
  • );
  •  
  • }
  • }
  • );
  •  
  • }
  • );

As you can see above, the Javascript basically does three main things:

  1. Set the background of each list item to be the appropriate image and then randomly animates to one of the slides.
  2. Binds a click event to all the "previous" links.
  3. Binds a click event to all the "next" links.

jQuery makes hooking all this stuff up super easy! I can't thank the "each()" method enough. The jQuery selectors combined with the each() method makes "bulk" updating a piece of cake.

Now, if you look at the code above, you will see that I get pointers to many jQuery objects. I think jQuery people tend to chain tons of stuff together and call $() on the fly. This is good, but I feel that it makes the code less readable. Plus, why turn the same DOM object into a jQuery object more than once? I like the idea of getting the jQuery object, storing it, and then referencing it multiple times.

Anyway, I just had some fun with this. If you haven't looked into jQuery, you should; it's totally awesome.

Tweet This Fascinating post by @BenNadel - jQuery Demo: Build A ColdFusion Guru Thanks my man — you rock the party that rocks the body!



Reader Comments

Code - very cool. I'm using jQuery more and more and it's really seems to be taking off with the ColdFusion community.

Demo - Ben called. He wants his pants back.

Reply to this Comment

Thanks. Yeah, jQuery makes stuff really easy. At first I was having "emotional" issues with using someone else's code to do stuff I "should" be able to do... but once I got over that, I am seeing that jQuery is just so well thought out and easy to use and Powerful!

Reply to this Comment

I long ago got over the use of someone else's code. As long as it does what I need and does it well (and is legally available), I'm all about shortening my development cycle. And, when the code takes so much of the edge off of browser compatibility issues...bonus. :-)

I just started using jQuery after a year or so of using Prototype and I like it. It does pretty much the same stuff - especially since the selectors got added to Prototype, but Jack Slocum's amazing Ext (nee YUI-ext) library is being integrated with jQuery so that's a huge selling point. His JavaScript UI work is pretty damn cool. I'm still learning jQuery, but all things being equal, I think I'll stick with it.

Reply to this Comment

@Rob,

Yeah, the browser compatibility is great. I like knowing that stuff is just gonna work. I also love that I can stack events, for instance, having as many document "Ready" functions as I want. It's too easy, and something like that is something I know I couldn't do elegantly on my own.

Reply to this Comment

@Ben

Yeah, Prototype offered that capability via Event.observe(), but the chainability was a bit different since not all methods returned the same object as appears to happen with jq.

Somehow, the syntax of jQuery just seems easier/more convenient, as well. Writing it just feels smoother to me. I have no idea how to quantify that. It just is. :-)

Reply to this Comment

@Rob,

I know what you mean. It just feels good. And as far as chainability goes... I like it, but I actually think too much chaining hurts the readability. I am leaning more towards getting a jQuery object as a local function variable and then just running multiple commands on it. I think it keeps the lines shorter and makes it easier to format.

But yeah, something smooth about it.

Reply to this Comment

Interesting. I may consider trying to rebuild this in Spry if you don't mind, although as I said in NYC, I tended to avoid the effects junk. :)

Reply to this Comment

@Ray,

That would be cool. It would be great to see it in Spry as a comparison. That Spry demo you gave was really good. If you want, I can email you the graphics, or you can just grab them from the page... although they are background images, so, not sure how easy that is to grab.

Reply to this Comment

@Ray

I've never used Spry, but I can't imagine that there's anything easier than jQuery. As I said above...smooth. And so freaking intuitive (for most operations) that it kind of makes me smile just a little when I use it. :-)

Reply to this Comment

I'd never heard of jQuery before Ben raved about it recently; but I now already find it indispensible - and incredibly easy to pick up!

I've been using it for both front- and back-end interfaces, and after three weeks of using jQuery have found myself answering a load of newbies' questions on the mailing list...

And yes, it's great to write something and know it will work everywhere!

Reply to this Comment

@Seb,

Glad I could help show you something good... there's probably a few jQuery evangelists somewhere right now shedding a tear of joy :)

Reply to this Comment

@Ray: Don't knock it till you try it. I think you're skered that you might fall in love with it like Ben did. ;o)

@Ben: I'm busting out the hankies. :o)

Reply to this Comment

In all fairness to Ray, his Spry demo last week was very impressive. Spry does some very cool AJAX tag stuff that I have not seen anywhere else. This syntax is WAY off (going off memory), but it was something like:

<div spry:mode="loading">AJAX loading....</div>
<div spry:mode="error">Something went wrong!</div>
<div spry:mode="ready">Hey, that was cool!</div>

And it automatically hooks up all that stuff and hides / shows divs as appropriate. I was impressed with that in the same way I was impressed with jQuery's selector expressions.

I don't think this is something that jQuery does or should do. I feel that these are different solutions / problem domains. But you have to admit, that Spry mode stuff is quite cool.

Reply to this Comment

Thats the problem with spry - it's syntax is invalid. By adding additional attributes to HTML tags you are creating markup that is not accessible, not to mention your page won't validate to XHTML Strict.

Good job with jQuery though, it is so good.

Reply to this Comment

@Ray

My bad, didn't know :( However that still means that there will be markup like:

<div spry:mode="loading">AJAX loading....</div>
<div spry:mode="error">Something went wrong!</div>
<div spry:mode="ready">Hey, that was cool!</div>

Which should all be created with Javascript rather than placed in the page, if you are into progressive enhancement / graceful degredation I guess.

Reply to this Comment

Well a lot of people will differ on what "Should" be done. ;)

In my mind, the code you showed is a perfect example of how Spry is easy to use and powerful. That code is FAR simpler than registering event handlers for objects (which you CAN do with Spry if you want). As for degradation - you can use a simple CSS element (class="SpryHiddenRegion") around you greater div and this will completely hide everything inside. Spry knows to remove this during loading.

Reply to this Comment

To fllowup - if you needed to fix a typo in the portion that shows up during loading, I think the Spry example makes it a heck of a lot easier. It's right there. I don't have to hunt up in JS to find it.

Reply to this Comment

I think one thing to remember, and Ray please correct me if I am way off here, but Spry was developed with the tag-coder in mind. The beauty of this Spry tag/mode system is that you don't have to touch any Javascript.

Reply to this Comment

@Ray

I think Spry definately looks easy for say backend interfaces where you know your public, but as far as using CSS to hide the elements - that is something you could do with any framework but doesn't alter the fact that the content will be confusing to screenreaders / search engines.

Reply to this Comment

I agree with Ben, so it is good for someone who wants to get stuff done fast and knows only a little JS if at all.

By the way how big in filesize is the Spry framework?

Reply to this Comment

@Ben - True - but I hate to say that. It is like saying CF was targetted for non-traditional coders. I can code JS. I like that I don't have to (as much) with Spry. To be clear - you _definitely_ need JS when doing more complex Spry work.

@Shuns - Good point.

Reply to this Comment

@Ray: What I'd like to know is if thats just an example of code that's actually used day-to-day or one used used more as a method to intro folks to the capabilities of Spry. If you wanted to have much broader error handling capabilities or use a different Ajax indicator, is that the same syntax or does it become much more verbose? In essence, how much control do you have by using that syntax?

Reply to this Comment

Right, I see what you are saying. I guess with Spry, just as with any of these other frameworks, it's not that you can't do the JS, it's more that we now don't have to deal with the boilerplate... less boilerplate, less error, faster coding.

Reply to this Comment

@Shuns: Still big. The team will be doing a 'compressed' version soon.

@Rey - This is how I explain it. It might not be best. I describe Spry as having 3 different Event handlers.

The first event handler type is what you saw Ben demonstrate. Tag based. Super simple. Etc. I can't find the docs now but it supports the 'major' states.

THe second and third types are pure JS, and probably very much like other frameworks. These other two types are tied to either the dataset (so you have stuff like, preload, onload, etc) and the region (so you could run stuff after the region is drawn out for example).

Let me know if that doesn't make sense. (Although I'm heading out for a few hours.)

Reply to this Comment

Thats one of the brilliant things about jQuery compared to other frameworks such as Prototype, Scriptalicious, Yahoo it is only like 19kb

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.