It’s likely obvious to anyone visiting this site: Treehouse is our primary sponsor. I like that. Not only because they offer structured learning that compliments the learning material I have here, but also because having a single main sponsor means we can spend more time integrating ads into the site in a fun way.
In talking to the folks over at Treehouse, they told me they had some new jQuery based content worth promoting. I thought I’d create a little interactive area to kind of wet people’s whistle on what jQuery can do, and get them excited to learn more about it.
Let’s go through how it was built.
The Idea
- Have a “canvas” (not
<canvas>
, just an area where things happen) - Have a series of five bits of simple jQuery code
- Click a button, code runs, something happens in canvas
- You can see the code you are about to execute
- It should be visually clear the code you see is what is running and making the changes
- The whole time, the canvas area is a clickable ad for Treehouse (users aren’t required to interact with the jQuery stuff, it’s still just an ad)
- You can start over with the interactive steps when completed

Here’s what we end up with. Demo on CodePen:
The HTML
Relevant bits commented:
<div class="ad">
<!-- Our jQuery code will run on elements in here -->
<div class="canvas" id="canvas">
<a id="treehouse-ad" href="http://teamtreehouse.com" target="_blank">Team Treehouse!</a>
<img src="//css-tricks.com/wp-content/themes/CSS-Tricks-10/images/mike-standard.png" alt="Mike">
</div>
<div id="code-area-wrap">
<h3>jQuery
<!-- We'll increment the "step", so we need an element to target -->
<span id="step-counter">1/5</span>
</h3>
<!-- Code is visually displayed in here -->
<pre class="code-area" id="code-area">var treehouse =
$('#treehouse-ad')
.addClass('button');</pre>
</div>
<div class="run-code-wrap">
<!-- This will be pressed to run the code -->
<a href="#" class="button" id="run-code">Run Code</a>
</div>
</div>
The CSS
Not much interesting here, so let’s not dwell on it. Essentially I made the ad re-use styles already in use on CSS-Tricks, so the ad feels at home. The block of code uses the same code styling as anywhere else on the site. The module has a bar on top like all other modules. The button is the global button style. That kind of thing.
I put a dotted border around the “canvas” as I thought that gives it a bit of an editable/target kind of feel.
The JavaScript
Now we need to make this thing work. Which means…
- When button is clicked…
- Execute the code
- Increment the step
- If it’s the last step, put stuff in place to start over
The Structure
The JavaScript we write is essentially a “module”. It’s all related to each other. We should give it some structure to make that obvious. The best way I know how is to make an object that contains it all.
var TreehouseAd = {
// Everything related to this ad goes in here.
};
That usually ends up something like this:
var TreehouseAd = {
importantVariableOne: "foo",
importantVariableTwo: "bar",
init: function() {
// The one function that will get called to kick things off
this.bindUIActions();
},
bindUIActions: function() {
// bind events here
// have them call appropriately named functions
$("button").on("click", function(event) {
TreehouseAd.doSomething(event, this);
});
},
doSomething: function(event, target) {
// do something
}
};
TreehouseAd.init();
Using structure like this makes for more readable code, more testable code, and just all around feels better than a bunch of disparate functions and variables (spagetti).
The “Steps”
We’ll have five steps. As in, the different bits of jQuery that execute and do different things to our ad canvas.
- Add a “button” class to the link
- Move it up a little bit (demonstrating animation)
- Change the text of the button
- Add a new element
- Add class to the entire ad, giving it a finished feel
We’ll also need to do two things with each bit of code:
- Display it
- Execute it
We’d rather not maintain the code in two separate places, so let’s just not. We’ll store the five different code bits in an array (giving it some structure, rather than five separate variables). Each item in the array is a string of code. We can grab that string and display it, or grab that string and eval()
it.
var TreehouseAd = {
...
codeText: [
"code for step 1",
"code for step 2",
...
],
...
}
That ends up like:
codeText: [
"treehouse = \n\
$('#treehouse-ad')\n\
.addClass('button');",
"treehouse.animate({\n\
top: '-40px'\n\
});",
"treehouse.text(\n\
'Learn jQuery at Treehouse!'\n\
);",
"$('<div />', {\n\
id: 'tagline',\n\
text: "Hi, I'm Mike."\n\
}).insertAfter(treehouse);",
"$('#canvas')\n\
.addClass('all-done');\n\n\
console.log('Thanks for playing!')"
],
Notice all the slashes and ‘n’s at the end of the lines? A string that ends in “\” in JavaScript just means “this string to be continued on next line.” It doesn’t end up in the string itself. “\n” means “new line,” in our case, we need that so the code is formatted correctly when we place it inside the <pre>
element. It won’t effect the eval()
.
The Animation
To make it visually clear what is going on when you press the “Run Code” button, I thought having the code kind of slide up and fade into the “canvas” would be a cool idea. The steps then become:
- Make a clone/duplicate code area directly on top of existing one
- Animate position upwards while fading out
- Remove clone when done
- Wait to change code text until animation has completed
I think of this action as one “chunk” of functionality. Meaning it deserves it’s own function as part of our object.
var TreehouseAd = {
...
codeArea: $("#code-area"),
delay: 400,
animateCode: function() {
this.codeArea
.clone()
.addClass("clone")
.insertAfter(this.codeArea)
.animate({
top: "-60px",
opacity: 0
}, TreehouseAd.delay, function() {
$(".clone").remove();
});
},
...
};
The Guts
The final code ends up like this. This has the logic in it for running the code and resetting and all that.
var TreehouseAd = {
step: 0,
delay: 400,
codeArea: $("#code-area"),
counter: $("#step-counter"),
init: function() {
this.bindUIActions();
},
codeText: [
"treehouse = \n\
$('#treehouse-ad')\n\
.addClass('button');",
"treehouse.animate({\n\
top: '-40px'\n\
});",
"treehouse.text(\n\
'Learn jQuery at Treehouse!'\n\
);",
"$('<div />', {\n\
id: 'tagline',\n\
text: "Hi, I'm Mike."\n\
}).insertAfter(treehouse);",
"$('#canvas')\n\
.addClass('all-done');\n\n\
console.log('Thanks for playing!')"
],
bindUIActions: function() {
$("#run-code").on("click", function(e) {
e.preventDefault();
TreehouseAd.animateCode();
TreehouseAd.runCode();
});
},
animateCode: function() {
this.codeArea
.clone()
.addClass("clone")
.insertAfter(this.codeArea)
.animate({
top: "-60px",
opacity: 0
}, TreehouseAd.delay, function() {
$(".clone").remove();
});
},
runCode: function() {
setTimeout(function() {
if (TreehouseAd.step < 5) {
eval(TreehouseAd.codeText[TreehouseAd.step]);
TreehouseAd.step++;
TreehouseAd.counter.text((TreehouseAd.step+1) + "/5");
TreehouseAd.codeArea.text(TreehouseAd.codeText[TreehouseAd.step]);
}
if (TreehouseAd.step == 6) {
// reset canvas
treehouse
.text("Team Treehouse!")
.removeClass()
.removeAttr("style");
$("#tagline").remove();
$("#canvas").removeClass("all-done");
$("#run-code").text("Run Code");
TreehouseAd.step = 0;
TreehouseAd.codeArea.text(TreehouseAd.codeText[TreehouseAd.step]);
TreehouseAd.counter.text((TreehouseAd.step+1) + "/5");
}
if (TreehouseAd.step == 5) {
$("#run-code").text("Start Over");
TreehouseAd.codeArea.text("");
TreehouseAd.counter.text("Done!");
TreehouseAd.step++;
}
}, TreehouseAd.delay);
}
};
TreehouseAd.init();
The End
Again, the demo on CodePen:
You can also see a modified version of it live on this site! We’ve changed it up a few times already for funzies. Probably will keep doing so. Big thanks to Treehouse for letting me do fun stuff like this. Check them out if you are a fan of CSS-Tricks.
That’s brilliant! I can see people copying same idea for their websites for interaction with visitors and to keep them longer on the website. And, yes I am going to try it on my site too.
Why not store the steps in the array as functions, then call
.toString()
on them to extract the code?Here’s a quick sample:
http://codepen.io/JosephSilber/pen/xAuEk
Looks like a great way of handling it to me!
Coming to think of it, there’s just one problem with this solution: you can’t minify the JS.
You’ll have to maintain the function and the display text separately.
I’ve been using that sort of structure on all my JS lately, and I find it’s so much nicer.
One thing I like to do with my code, which I picked up from others, is use a “settings” object to hold any cached items and values. So, instead of just declaring a bunch of naked variables at the top, it looks something like this:
So, as I’ve done in the
init()
function, I can access any of those settings using “s.whatever”. The only flaw is that you have to define the settings at the top of each function using “this.settings”.I don’t know if this is the best way to do this sort of thing, but I find it saves a bunch of characters, so you don’t have to do “ModuleName.variableName” every time you want a cached object.
Just be careful with that global. You want to properly declare that:
Yes, that’s right. My example was more or less theoretical. Not meant to be copy/pasted.
I usually do this something like this at the top:
And along those same lines, the other code should be “var ModuleWhatever…” because that too was global as I had written it.
Well in that case, there’s no reason for
s = this.settings
at the beginning of each function.Once you did that in your
init
function, it’ll be available throughout your module, since they all have access to the parent closure.Yes, you’re right… Hmm, that actually makes it much easier. I think some of my old code has a few redundancies! :) Thanks for pointing that out.
Pretty cool… but then you have that global “s” which scares me. I think I’d prefer the repetitive
s = this.settings;
in general.@Chris I don’t think we’re talking about polluting the global namespace here. We’ll have all this in its own closure:
True.
I really love this ad. A lot of my job involves trying to make our advertisements more interesting and evaluating statistics about our advertisements. Your ad is interactive, it’s catchy, it’s very well targeted at the proper demographic… It’s pretty much perfect. Good job, as always. :)
I too have been structuring a lot of my javascript like this lately. Some things I hadn’t considered in there as well though. One thing that I have been fighting with lately is putting jquery in my functions/modules.
Obviously it could have no merit if I just know jquery will be there but I still for some reason have been fighting with relying on jQuery to be there or not.
I’d be interested to see the statistics for this ad. What percent go through all five steps and click the button, which go through all five but don’t click, do some stop at step 3, etc. Would be an interesting study since this form of advertisement is very unique.
Chris: Why do you need to declare e.preventDefault() in this block of code? Just curious… Thanks!
I probably have a href=”#” on the link so it has a proper cursor and hover state and stuff. But that href will jump to the top of the page if that line isn’t there.
That line prevents the browser from following the link in the href attribute of the a tag.
Awesome! I should have been using this for a while now ;). Thanks!
Not to be a downer on this “interactive” ad but it took me forever to even figure out what part of the ad was “Interactive” AFTER being told it was. This is due to the fact that I saw the green “treehouse” box and thought that was the ad and everything else was unrelated content. It took me a long time to read the small paragraph below the code that said it had something to do with Treehouse.
I think this is because of the dotted border around the main Treehouse ad area. It separates it, and since I’m not used to seeing interactive ads it requires a big jump for me to associate the content inside the box with the content below.
While it may be cool interaction it fails on a basic level because it takes so long to figure out that it’s somehow related to Treehouse. I’d be curious to see if the number of people interacting with the content is worth making it an interactive ad?
Thanks for the thoughts. All good stuff to consider in the future.
I feel like “Run Code” is a pretty strong verb-y button and curious folks might just click to see what it does.
It’s also kind of good that you did see the Treehouse area and just glossed over the stuff below it. It needs to be an ad first and anything else second.
Awesome as always Chris!! Thanks!
@Chris – “Run Code” can / will also scare some, already overly-cautious, users out there…. lol
@Louis – THANK YOU for bringing up the “settings” object…. I now have realized that I have some reduncancies to clean up as well…. hahaha…