Stuff they don’t tell JavaScript noobs: Convert a string into a variable name

November 10th, 2011

Hey, I said this might turn into a series and it’s turned into a series of two! Last week, I put up a post about creating something you’d usually use jQuery to write using pure JavaScript. And as usual, I learned something I never expected to when I was writing my code. It turned out, I had no idea how to convert a string into a variable name. Of course, the answer turned out to simple, but it didn’t turn out to be the way I thought you would do it.

In my earlier post, I needed to see which link was clicked and then hide and display the colored divs based on that. Basically, if you clicked the blue link, then the page would only display the blue divs. I created a couple of arrays, blueDivs and redDivs and to make this work, I had to link the link with the id blue to the array blueDivs.

This is what I tried at first:

1
2
3
4
5
6
function showDivs(el) {
  var div = el + ‘Divs’;
  for (var i = 0; i < div.length; i++) {
    div[i].style.display = 'block';
  }
}

If I pass blue to the showDivs function, then blue plus Divs should give me blueDivs, right? Technically it does, but it’s a string and it’s not going to work because when the loop runs, it’s going to try to go through each character in the string. So this isn’t going to work for me. Why does this happen? Because JavaScript tries to guess what you want to do and any time you add anything to a string, the default result is to create a string. So if you were to write this:

1
2
var myNum = 1 + ' is a number!';
console.log(typeof(myNum));

Even though we’ve got a number in there, it will log out string as the type. So how do I change a string into a variable name? Well, a variable is really an object, so I need to convert our string into an object. How do I do this? Like this:

1
2
3
4
5
6
function showDivs(el) {
  var div = this[el + ‘Divs’];
  for (var i = 0; i < div.length; i++) {
    div[i].style.display = 'block';
  }
}

If you console.log(typeof(div)) on on this example, it will give you an answer of object. In fact, window[el + ‘Divs’] would do the same thing, in this case, I’m using this because it’s not a global variable. Now the variable div will equal blueDivs if I’ve passed blue to showDivs. And when the loop runs, then it will cycle through the blueDivs array.

Once again, this is one of those things that you probably won’t learn until you run into a situation that you need it.

I’ve been thinking about jQuery

November 8th, 2011

The more and more that I work with JavaScript, the less and less I find myself using jQuery. And then I saw this tweet and it made realized that there are two types of jQuery users. There’s the designers and HTML/CSS people that have no interest in programming but use jQuery to add functionality and effects to sites. And there’s the developers who use jQuery as a starting point and move more and more into using pure JavaScript. jQuery isn’t meant more for one group than the other and the great thing about it is that it works for both.

For me, the best thing about jQuery is it made me realized JavaScript isn’t the worst invention in the history of the web like I’d been told. And that the browser is capable of things that perviously I’d only been able to achieve with Flash. In fact, at work for a time, my catchphase must have been “We don’t need Flash to do that.”

But, I’m beginning to sense an wave of anti-jQuery sentiment amongst the web development community. jQuery is on half of the top 100,000 web sites or something like that. And I’ve noticed this being pointed out more and more on tech sites when they talk about jQuery. It almost reminds me of how Adobe and other Flash supporters liked to mention that the Flash Player was on 97% of computers. So what if jQuery is super popular? If you don’t like it, aren’t you just being a web hipster? Maybe, but what if the feelings aren’t towards jQuery itself, but the fact that it seems every designer and developer feels the need to have some jQuery effect on their site, whether it needs it or not.

I’m a fan of Flash and I think it’s the best development tool for games right now, especially if AIR works as good as Adobe claims it does on mobile devices. But I always shake my head when I visit a web site and it has a Flash built navigation. I can’t think of a single reason that Flash ever needs to be used for something like that. People aren’t impressed with the cool lightning effects anymore, in fact, they’re probably annoyed by it. But now it seems jQuery has stepped up to replace those cool nav effects with their own. Done right, a little arrow on the bottom of a web site’s navigation sliding back and forth can add to the site. It’s too bad I’m beginning to see more and more complex animations on drop downs that add nothing to the site.

Wait, am I saying using jQuery on every site is bad? Isn’t that a little hypocritical of me? I’m not saying that at all. In fact, I use jQuery on almost every site I build. But I’m not using it to add effects to most of them, I’m using it to add functionality that some browsers are missing, browsers like IE7 and IE8.

Here’s the thing, I think we need to remember that while jQuery is awesome, it’s not the solution to everything. We need to be careful that we don’t create whatever the jQuery version of Flash intros might be. And there’s no such thing as a jQuery developer and knowing jQuery doesn’t mean you know JavaScript.

Become a better JavaScript developer by recreating jQuery effects in raw JS

November 2nd, 2011

A couple of days ago, a client wanted a couple of pages of videos changed to one page with a series of thumbnail links to the videos. And they wanted a way to show all the video thumbs or ones in certain categories. And, of course, I didn’t have a lot of time to build this, so I turned to jQuery. I ended up building a page like this. There’s no fancy effects but it gets the job done. Later on, I began to wonder if I could do the same thing in JavaScript and if it would be anywhere near as simple to write.

First, let’s take a look at the jQuery I wrote to get the effect the first time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$(function() {
  var divs = $('#wrapper div');

  $('#blue').click(function(e) {
    e.preventDefault();
    showBox('.blue');
  });
  $('#red').click(function(e) {
    e.preventDefault();
    showBox('.red');
  });
  $('#show-all').click(function(e) {
    e.preventDefault();
    $(divs).filter('.box').show();
  });
 
  function showBox(box) {
    $(divs).hide();
    $(divs).filter(box).show();
  }
 
});

I’m getting all the divs inside the wrapper div and putting them into a variable called divs. Next, I check to see which of the links you click on and if it’s blue or red, then I run a function called showBox, which hides all the boxes and then shows the ones I want to be shown. If the show-all link is clicked, then I just show all the boxes. I hide all the boxes because it’s easier then remembering which ones are showing and which ones aren’t.

It’s pretty simple and it’s like jQuery code you see everywhere on the web. I used jQuery exactly for the reason it was created, to add an effect to a site quickly and easily and there’s nothing wrong with doing it this way. But I want to get as good as I can at JavaScript, so why not see if I can do this without jQuery. And I did it and I actually learned a thing or two.

Let’s take a look at JavaScript code that does the same thing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var divs = document.getElementsByClassName('box'),
    blueDivs = document.getElementsByClassName('blue'),
    redDivs = document.getElementsByClassName('red'),
    blue = document.getElementById('blue'),
    red = document.getElementById('red'),
    showAll = document.getElementById('show-all');

function hideDivs() {
  for (var i = 0; i < divs.length; i++) {
    divs[i].style.display = 'none';
  }
}

function showDivs(el) {
  var div;
  if (el === divs) {
    div = el;
  } else {
    div = this[el + 'Divs'];
  }
  for (var i = 0; i < div.length; i++) {
    div[i].style.display = 'block';
  }
}

function click(e) {
  e.preventDefault();
  hideDivs();
  var target = e.target.id;
  if (target === 'show-all') {
    showDivs(divs);
  } else {
    showDivs(target);
  }
}

blue.addEventListener('click', click, false);
red.addEventListener('click', click, false);
showAll.addEventListener('click', click, false);

This does the exact same thing as the jQuery code. I used getElementsByClassName to create an array of divs and I also had to create arrays for the blue and red divs, which jQuery did for me. And the event listeners do the same thing as the click method of jQuery. Really, the only difference is that I had to write loops through the arrays myself, which is something else that jQuery did for me in the earlier code.

So people are probably thinking, why do this:

1
2
3
for (var i = 0; i < div.length; i++) {
  div[i].style.display = 'block';
}

when jQuery will just let you do this:

1
$(divs).filter(box).show();

Well, that’s what jQuery is doing behind the scenes. And the big difference going here is this, yes, the JS is about twice as much code in the HTML page, but to make the jQuery work, I need to load a 31KB file. With the raw JS, I have 40 lines or so.

I’m in no way ripping on jQuery here, I use it all the time and on the site I used this on was using jQuery for other things, so it was already loaded. I like to do things like this because it’s a challenge with a definite goal. Challenging yourself like this will help you become a better JS developer and it might lead to you relying on jQuery less.

Some things I’ve learned in 3 years as a web developer

October 31st, 2011

There have to be few industries that move at the speed that the web does. I can’t believe how many things I learn in school are useless now. Yes, that’s right, I learned Adobe Director. In fact, I remember seeing the A List Apart previewing HTML5 and thinking, “Man, that’s going to be so cool in the future.” Flash was going to take over the web and JavaScript was the worst thing ever invented.

So three years later, in a world of hover cars and jet packs, what do I know now? Well, other than the fact that I’m crazy mad that we don’t have hover cars and jet packs, I know that I’m working on with technologies and programming languages that I never thought I would. I remember three years ago looking at people that spent a majority of their time working with HTML, CSS and JavaScript and thinking “Really? That’s what you do? That’s got to be pretty boring.” Now, I’m one of those people and I totally enjoy what I do.

I’ve learned that every programming language on the web sucks and is going to die. Or it’s totally awesome and is going to take over. Or make a comeback. Or it’s underrated. For every blog post I’ve see about Java being this close to disappearing from the world forever, followed by one talking about how there’s never been more Java work out there.

I’ve learned that people can get way too involved in whether the language they like is better than one they don’t. Whether or not a language uses curly braces shouldn’t matter if the end product is great or if the programmer likes it. Pick your language and become awesome at it. Being awesome at PHP will always be better than being OK at Ruby. Unless, of course, you really hate curly braces.

I’ve learned that we as web designers and developers should never let a company tell us what technologies should do. But at the same time, don’t refuse to use any technology just because of who makes it.

I’ve learned that comparing yourself to your idols can be the worst thing you can do. Just because they can make something amazing using a cutting edge feature, doesn’t mean they know how to build a WordPress theme or a Flash game. Don’t look down on what you can do because of what others can do.

I’ve learned that just because a blog gets thousands of hits a day, doesn’t mean you should give a crap what that person has to say. And I’ve learned that just because a person has 30 followers on Twitter, doesn’t mean they don’t know what they’re talking about.

Some things have stayed the same. Superman is still the best superhero. Apple fanboys are annoying. And I’ll try every code editor I come across.

Stuff they don’t tell JavaScript noobs: Making copies of arrays

October 23rd, 2011

I’ve decided to do a series, it might be a one post series but I hope not, about the situations I’ve come across while learning JavaScript. JavaScript has been around for forever in internet years and I’ve discovered a couple of things about it so far. There’s two main types of JavaScript articles out there, tutorials for absolute beginners and expert articles written for other experts. I’m generalizing, but it’s pretty close to being true. When you’ve moved on pass the beginner stage, it’s amazing how hard it can be to find out the solution to a problem you’ve run into. A few months ago, I ran into a problem that I think is a pretty good example of this.

Let’s say we want to make a copy of an string variable:

1
2
3
var var1 = 'Hello';
var var2 = var1;
console.log('var1: ' + var1, ', var2: ' + var2); // logs var1: Hello , var2: Hello

This is exactly what we expect, now let’s say we want to change var1:

1
2
var1 = 'Goodbye';
console.log('var1: ' + var1, ', var2: ' + var2); //logs var1: Goodbye , var2: Hello

var1 has changed to ‘Goodbye’ and var2 is still ‘Hello’. We created and set var1 to ‘Hello’ and then we created var2 and also set it to ‘Hello’. Although we set var2 by writing var2 = var1, we weren’t saying var2 equals var1, we were saying var2 equals ‘Hello’. So when we then set var1 to ‘Goodbye’, var2 didn’t change as well. This works like it should, so what’s my point? Well, arrays don’t work this way:

1
2
3
var array1 = [1, 2, 3, 4, 5];
var array2 = array1;
console.log(array1, array2); //logs [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]

Alright, so just like our string variables, our arrays both equal the same thing. Let’s change array1 and see what happens:

1
2
array1.splice(2, 1);
console.log(array1, array2);  //logs [1, 2, 4, 5] [1, 2, 4, 5]

First thing we’re doing here is using the splice method to remove an item from our array1 array, in this case, the third item (the third item because it starts at zero, so two means the third spot in the array). But when we console.log out both arrays, the 3 is missing from the first array like we would expect, but it’s also missing from the second array. But we didn’t touch the second array and when we changed var1, it didn’t affect var2, so what’s happening? Well, when we wrote array2 = array1, we weren’t assigning the value of array1 to array2 rather we were setting array2 to reference array1. Then whatever changes are made to array1 is reflected in array2. In fact, if we’d wrote array2.splice(2,1), the change would show up in array1.

So what do we do to have the second array copy the first, not just reference the same array? Let’s make two more arrays:

1
2
3
var array3 = [1, 2, 3, 4, 5];
var array4 = array3.slice();
console.log(array3, array4); //logs [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]

The difference between this group of code and the last is one this, we’re using the slice method to copy the contents of array3 into array4. This can get a little confusing, to cut things out of an array, we used the splice method, to copy, we use the slice method. It’s one of those naming conventions that have been in programming for years which doesn’t really make sense, but there’s nothing we can do about it. Now, what does using the slice method instead of array3 = array4 let us do?

1
2
array3.splice(2, 1);
console.log(array3, array4); //[1, 2, 4, 5] [1, 2, 3, 4, 5]

Alright, now we’ve made a change to array3 and it hasn’t affected array4! Pretty simple now that we know how to do it.

I’m sure I had read a few times about arrays referencing each other, but it’s one of those things that won’t stick in your head until you’ve actually run into a situation where it’s causing you some problems. It was pretty surprising how long it took me to find something online that explained what was happening. I’m guessing most people just assume a beginner will read and remember everything in the arrays chapter in JavaScript: The Definitive Guide.

More advanced HTML5 canvas sprite sheet walk cycle animation

October 16th, 2011

One of the key tricks that have been used for at least 30 years by game developers is using sprite sheets to animate characters. This can be done using the HTML5 canvas tag and I’ve talked about it on here before. But there’s a big difference between making it look like a space ship is tiling to the side and making a animated person look like he’s walking across the screen. For the space ship, all we had to do was change the source position of the sprite sheet if a certain key was pressed, but to make a character look like they’re walking, we’ll have to cycle through a series of images. Check out my earlier tutorial on sprite sheets to understand the basics of what we’re doing.

Here’s a demo of what we’ll be making. And here’s the sprite sheet. I didn’t create this, I got it form a demo made by John Graham. Now, if John Graham has already made a demo, then why am I making another one? John’s demo involves making the character walk by clicking buttons, I wanted it to work with the left and right arrow keys. Plus, I wanted to challenge myself to simplify his a bit and I think I pulled that off.

To power this, we’ll be using requestAnimationFrame() which runs at 60 frames a second and we’ll make our guy take about 4 steps a second. The way to make this work, is when the right or left arrow key is pressed, we’ll have a counter variable that is increased by one every frame and when it gets to a multiple of 15, it will change the source position of the sprite sheet. Then when it gets to a certain number, in our case 90 (15 for each frame on the sprite sheet), it will go back to the first frame. Also, it will reset to the standing frame when the key stops being pressed.

Now onto the code. First, here’s all our variables:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var canvas = document.getElementById('canvas'), // get our canvas tag in the DOM
    ctx = canvas.getContext('2d'), // set the context of the canvas
    character = new Image(), // create a new image object for our sprite sheet
    player = { // create our player object
      x: 0, // set the player’s x position
      y: 50, // set the player’s y position
      w: 104, // set the player’s width
      h: 149, // set the player’s height
      sx: 0, // set the player’s image’s source x position
      sy: 301, // set the player’s image’s source y position
      faceRight: true, // this will tell the code our player is facing right to start
      faceLeft: false, // this is set to false so our player will face right
      counter: 0, // counter we use to know when to change frames
      step: 15, // we change frames every 15 frames, so increase or decrease this number if you want the player to walk faster or slower
      nextStep: 0, // this increases with each frame change
      endStep: 90,  // when counter equals this number, everything resets and we go back to the first frame
      start: { // sets the start postions of our source
        rightX: 0, // start x position when facing right
        leftX: 100, // start x position when facing left
        y: 301 // start y position is the same for both
      }
    },
    key = { // the variables we’ll use to see if a key is being pressed
      right: false,
      left: false
    };

The comments explain what all the variables are for. Next, we’ll take a look at the function that draws our character:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function drawPlayer() {
  if (key.right === true) {
    move(0, true, false);
    player.x += 1;
    if (player.x > canvas.width + player.w + 1) {
      player.x = -player.w;
    }
  }
  if (key.left === true) {
    move(150, false, true);
    player.x -= 1;
    if (player.x < -player.w - 1) {
      player.x = canvas.width + player.w;
    }
  }
  if (key.right === false && player.faceRight === true) {
    player.sx = player.start.rightX;
    reset();
  }
  if (key.left === false && player.faceLeft === true) {
    player.sx = player.start.leftX;
    reset();
  }
  ctx.drawImage(character, player.sx, player.sy, player.w, player.h, player.x, player.y, player.w, player.h);
}

The drawPlayer() function’s main purpose is to key if the user is pressing one of the arrow keys and if they are which one. If a key isn’t being pressed, then which direction is the player facing. It then calls the appropriate function and draws the character on the canvas. If the right arrow key is pressed, then a function called move is called, a few things are passed to it which we’ll look at in a minute. Then player.x is increased by one, moving the character across the canvas. Finally, it checks to see if the character has gone off the canvas completely and if it has, the character is repositioned to the other side of the canvas instead of just stopping it at the edge. When the left arrow is pressed, the same thing happens, just in the opposite direction. Finally, when the key is not pressed anymore and depending on which way the character is facing, the source image positioning is reset.

Let’s take a look at the move function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function move(yPos, right, left) {
  player.faceRight = right;
  player.faceLeft = left;
  if (player.counter === player.endStep) {
    player.sx = 0;
    player.counter = 0;
    player.nextStep = player.step;
  } else if (player.counter === player.nextStep) {
    if (player.sy === player.start.y) {
      player.sx = 0;
    } else if (player.sy === yPos) {
      player.sx += player.w;
    }
    player.sy = yPos;
    player.nextStep += player.step;
  }
  player.counter += 1;
}

Remember in the drawPlayer() function that we were passing a few things to the move function? Well, here’s what they meant, the first one was the y position of the source image, the second two say which way the player is facing. We first assign the true or false values to player.faceRight and player.faceLeft. Next, we check to see if player.counter has reached the limit we’ve set for it of 90, which is what player.endStep is equal to. If it has, then we reset the source image x position to 0, player.counter to 0 and player.nextStep back to 15 which is what player.step is set to. This will have mean that we’ve got to the final frame and want to start the walk cycle all over again. Next, if player.counter doesn’t equal player.endStep, then we check to see if it equals player.nextStep, which is our check to see if we need to change to the next character frame on our sprite sheet, and remember, we switch every 15 frames that we draw per second. If player.counter does equal player.nextStep, we need to check one more thing, are we just starting to walk? If we are then we set the player.sx to 0 or else we’d skip to the second frame of our walk cycle. If we haven’t just started walking, then we increase our source position by the width of our the width of our viewing area and we’ll see the next frame in our walk cycle. Finally, we increase player.counter by 1.

Finally, we have our reset function, which just resets everything back to our starting values when the player stops moving:

1
2
3
4
5
function reset() {
  player.sy = player.start.y;
  player.counter = 0;
  player.nextStep = 0;
}

You can take a look at the complete code by viewing the source on the demo. Hopefully this helped you out.

Quick overview of using addEventListener in HTML5 games

October 9th, 2011

Coming from ActionScript, there are a few things that I forget people who are learning JavaScript who have programming backgrounds with languages like PHP or even straight up HTML/CSS might not be familiar with some of the functions or methods I use in my tutorials. One thing that I’ve had a few questions about was addEventListener, which is something that you learn about right away when working with AS3. It’s a little different with JavaScript but the basics are the same. This isn’t going to be anything indepth, I’m going to explain enough about it so that when you’re building a game or something, you’ll know what’s going on.

First off, the basic explanation of addEventListener is pretty simple. Let’s take this line of code as an example:

1
window.addEventListener('keydown', keyDown, false);

This line does this, add an event listener to the window object, the event to listen for is the keydown event. When that event happens, run a function called keyDown. Finally, there’s a Boolean for if you want to useCapture or not. If useCapture is set to true, then the window object in our example would get notified of the event before the keyDown function would. In the context of a game, I think you’ll have this set to false nearly every, if not all the time.

Another question I’ve been asked has been about what is set to, in our example, the keyDown function. Take a look at this code:

1
2
3
4
5
function keyDown(e) {
 if (e.keyCode === 39) { //39 is the keyCode # for the right arrow key
   //do something awesome
 }
}

So when the key is pressed and the keyDown function is called, it’s passed the parameter e. What is this e? In this case, e is short for event. Some people use event, other evt, but I like e because it’s nice and short and you still know what it means. In the case of a game and in the above code example, we check to see if the key being pressed is the right arrow key, which has the keyCode number of 39. How do we know this? Well, if you were to console.log out e, this is what you would get:

You’ll see in the picture all the things that the browser gives us access to. In the case of a game, we’re interested in the keyCode which you’ll find about halfway down. To access that, we just write e.keyCode and we’ll get the number of whatever key is pressed. Then we can check and see with arrow key has been pressed and then, say, move a character in the right direction.

For the most part, the three event types that you’ll be listening for when making games are keydown, keyup, mousemove, mouseover and click. Keydown and keyup will usually be used together, for example, you’re moving a ship around in a shooter game, keydown will move the ship when the key is pressed and keyup will stop it when the player stops pressing the key. The other three, of course, are used with the mouse and are pretty self explanatory.

Remember, console.log is your best friend when it comes to learning JavaScript. If you don’t understand something, like say, a parameter that’s being passed to a function, just log it out. Most of the time it will show you exactly what you were wanting to know.

Recreating Facebook’s “Introducing Timeline” page banner effect with jQuery

September 25th, 2011

I think I have something in common with a lot of web developers out there and it’s when I see something cool or interesting on a web page, I need to figure out how it was done or at least a way to recreate it.The latest thing I’ve seen that I wanted to know how it was done was the banners on Facebook’s page to introduce their new Timeline layout. They fade in and out because of how far the visitor has scrolled down the page as well as sticking to the top of the page when the page has scrolled past their original position. I was the combination of the fading and sticking to the top of the page that caught my attention. That and the fact that the Facebook has a ton of JavaScript files loaded on the page and I have no idea where the code is that produces the effect. So I figured out to to do the same thing using jQuery.

To pull this off, we need to use two jQuery methods, .scroll(), .scrollTop() and .offset(). In my demo, the HTML file has 3 divs, each has a picture and the second two both have a banner inside:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="wrapper">
  <div id="content_1" class="content">
    <img src="images/ironfist.jpg" alt="" />
  </div>
  <div id="banner_1" class="banner">
    <h1>Banner!</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec leo sapien, accumsan id suscipit ac, fermentum quis metus. In at augue urna, et vulputate turpis.</p>
  </div>
  <div id="content_2" class="content">
    <img src="images/drstrange.jpg" alt="" />
  </div>
  <div id="banner_2" class="banner">
    <h1>Banner!</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec leo sapien, accumsan id suscipit ac, fermentum quis metus. In at augue urna, et vulputate turpis.</p>
  </div>
  <div id="content_3" class="content">
    <img src="images/adamstrange.jpg" alt="" />
  </div>
</div>

The only CSS that we have that matters to the effect is the sticky class:

1
2
3
4
.sticky {
  position:fixed;
  top:0;
}

This class will be added to a banner when it hits the top of the browser’s viewing area and it will cause the banner to stick to the top. Now on to the fun part, the jQuery.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$(function() {
  var $window = $(window);
  var banner1 = $('#banner_1');
  var banner2 = $('#banner_2');
  var content1 = $('#content_1');
  var content2 = $('#content_2');
  var content3 = $('#content_3');

  $($window).scroll(function() {
    var windowTop = $($window).scrollTop();
    var banner1Top = $(banner1).offset().top;
    var banner2Top = $(banner2).offset().top;
    var content1Height = $(content1).height();
    var content2Height = $(content2).height();
    var content1Top = $(content1).offset().top;
    var content2Top = $(content2).offset().top;
    var content3Top = $(content3).offset().top;

    function fadeIn(obj) {
      $(obj).stop().fadeTo('fast', 1);
    }
    function fadeOut(obj) {
      $(obj).stop().fadeTo('fast', 0);
    }
    if (windowTop < content1Top + content1Height / 2) {
      fadeOut(banner1);
    }
    if (windowTop > content1Top + content1Height / 2) {
      fadeIn(banner1);
      fadeOut(banner2);
    }
    if (windowTop > content1Height + (content2Height / 2)) {
      fadeOut(banner1);
      fadeIn(banner2);
    }
    if (windowTop > banner1Top) {
      $(banner1).addClass('sticky');
      $(content2).css('paddingTop','100px');
    } else if (windowTop < content2Top) {
      $(banner1).removeClass('sticky');
      $(content2).css('paddingTop','0');
    }
    if (windowTop > banner2Top) {
      $(banner2).addClass('sticky');
      $(content3).css('paddingTop','100px');
    } else if (windowTop < content3Top) {
      $(banner2).removeClass('sticky');
      $(content3).css('paddingTop','0');
    }
  });
});

First we just grab all the elements from the DOM that we need, the window, the divs and the banners. Then we run a function every time window scrolls using $($window).scroll(). Every time the page scrolls we find how far up it has with the scrollTop method and we use .offset().top to find the top position of all of our elements. Then we use if statements to check the positions to whether to fade in or out the banners. With the first banner we fade it in when half the first div has scrolled over the top of the viewing area. And then we fade it out if the page scrolls back to the top or if it scrolls the next banner into view. Thanks to jQuery, it’s actually easy to create these effects.

The second part where the banner is stuck to the top of the page is achieved by adding the sticky class to the banner when it’s offset().top is higher than the window’s top and if the page scrolls back down, then we remove the class and it banner goes back to it’s original position. There’s just one other little thing, when the sticky class is added to the banner, it’s taken out of the flow of the page, so the div’s content jumps up the height of the banner. So, when the sticky class is added to the banner, we add 100 pixels of padding to the top of the div sot that the picture’s position stays the same. And we remove the padding when the sticky class is removed from the banner.

You can check out the demo here.

It works in Firefox, Chrome and IE9. I’m not sure about the other versions of IE but I’m sure with some extra jQuery it could be made to work if there’s any problems.

It’s pretty crazy how simple this is to do with jQuery, although, I’m sure that the Facebook page creates the effect using raw JavaScript. But, I think this is one of the things jQuery is perfect for, it makes it so easy to create effects like this and I personally think the extra KBs it costs to load jQuery is worth it. And to any web designers and developers that are just starting out, this is a perfect example of how to become a better developer. You never know if you’ll ever get to create something like this, so something like this is perfect to figure out on your own, so you can tell people you know how to do that.

My extremely simple jQuery image slider

September 18th, 2011

If there’s two things every web designer and developer knows it’s 1) There’s as many jQuery image sliders as there are stars and 2) Clients seem to think every web site needs one. And because there are so many out there, I never felt the need to even start building my own, why try to re-invent the wheel. I’ve never had a complaint about any that I’ve used and for the most part, I’ve been really happy with all the options you get with the good ones, like the Nivo Slider. But for a project at work, all I needed was an image slider that slide the images right to left and that’s it. So, I took an hour or so out of my day to make my own.

Check out the demo.

So how simple is this thing? Well, it only does one thing, it slides the images from right to left. That’s it, no thumbnails, no next or previous buttons. Just a simple image slider. I’m not going to go line by line in through the code like I usually do because if you’ve don’t anything with jQuery, you should be able to figure it out, but here’s the basics on how it works. first the HTML:

1
2
3
4
5
6
7
8
<div id="slider_container">
  <div id="slides">
    <img src="images/img_1.jpg" alt="" />
    <img src="images/img_2.jpg" alt="" />
    <img src="images/img_3.jpg" alt="" />
    <img src="images/img_4.jpg" alt="" />
  </div>
</div>

We need two divs, an outside container, here with the id of slider_container and an inner div with the id of slides. The outside div will be given a position of relative so that we can manipulate the position of the inner div. The inner div will have it’s width set to the combined width of the images so that we can move it to achieve our slide effect. Now the CSS:

1
2
3
4
5
#slider_container {
  width:450px;
  height:300px;
  overflow:hidden;
}

We need to set the width and height of our container to the same dimensions as our images so that our jQuery code will know how to position our images and how much to move. We could set the overflow in the jQuery code but then you would see all the images if the page takes a bit to load. This way even if it takes a second or two for the code to run, the visitor will still only see the first image. Finally, the jQuery code that makes it run:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$(window).load(function() {
  var slideContainer = $('#slider_container'), slidesHolder = $(slideContainer).children(), slideWidth = slideContainer.width(), slidePos = 0, slides = $(slidesHolder).children(), slideTotal = slides.length, currentSlide = 0, delay = 3000, slideTime = 800;
  $(slideContainer).css({
    'overflow':'hidden',
    'position': 'relative'
  });
  $(slidesHolder).css({
    'position': 'absolute'
  });
  for (var i = 0; i < slides.length; i++) {
    $(slides[i]).css({
      'position': 'absolute',
      'top': '0',
      'left': slidePos + 'px'
    });
    slidePos = slidePos + slideWidth;
  }
  $(slidesHolder).css('width', slidePos + slideWidth);
  $(slides).first().clone().css({
    'left': slidePos  + 'px'
  }).appendTo(slidesHolder);
  function animate() {
    $(slidesHolder).delay(delay).animate({
      left: '-=' + slideWidth
    }, slideTime, function() {
      if (currentSlide < slideTotal - 1) {
        currentSlide++;
        animate();
      } else {
        $(slidesHolder).css({
          'left': 0
        });
        currentSlide = 0;
        animate();
      }
    });
  }
  animate();
});

Here’s how this dealie works. We position all the images in a row so that we can move the inner div one image width to the left. In order to make it seem infinite, we clone the first image and place it on the end of the row of images. When the slider reaches the cloned image, it will look like the slider has gone completely around and the code repositions the inner div back to zero, which the viewer will never notice. Now we have a infinite images slider that’s only about 40 lines of code. There are two variables, delay and slideTime that control the duration of the slider. The delay variable is how long the picture stays still and it’s set to 3 seconds. slideTime is how long it takes to slide from one image to the next and I’ve set that to 0.8 seconds. Just change those to what you want for your slider.

I’ve also made a plugin version that you can download here.

Call it like this:

1
2
3
$(function() {
  $('#slider_container').SimpleSlider();
});

And to set either delay or slideTime:

1
2
3
4
5
6
$(function() {
  $('#slider_container').SimpleSlider({
    delay: 5000,
    slideTime: 1000
  });
});

I’ll be honest with you, the main reason I built this was because the project I was working on was pretty standard, so I thought to make it more interesting, I’d see how quickly I could whip this up. It had been a while since I’d done anything major with jQuery, which sucks because I really like working with it. Feel free to use either the slider code or the plugin if you just want something that’s 2KB.

What’s up with prototypes in JavaScript?

August 30th, 2011

I’ve had a few people ask me what’s the deal with prototypes in JavaScript and I’ll be honest, at first I didn’t know. I have to say that most of the explanations show how to create a prototype object but never really said why, at least clearly. Most seemed to be written by really experienced programmers who were trying to explain it to other experienced programmers coming from a different language. And when you’re a beginner, seeing something like this can be confusing:

1
2
3
4
5
6
7
var Foo = function() {
 this.width = 100;
 this.height = 100;
}
Foo.prototype = function() {
 this.color = ‘red’;
}

If you don’t understand what’s going on here, I’ve created a variable called Foo which I’ve give height and width properties, they could have been anything, I just picked these two. Next, I added another property to the Foo object called color. Now I have access to Foo.width, Foo.height and Foo.color. This is the way most of the examples I’ve seen have been written and I think a lot of beginners won’t get the point of the prototype object, they’ll just be asking why not just add the color property when you first create the Foo object.

It’s a good question and if you’re not familiar with Object Oriented Programing, it might be hard to figure on your own. Here’s a simple example of where you could use the prototype object to add to an object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Prototype Test</title>
<style>
body {
   margin:0;
   padding:0;
   background:#000;
}
canvas {
   display:block;
   margin:30px auto 0;
   background:#fff;
}
</style>
</head>

<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script src="Square.js"></script>
<script>

</script>
</body>
</html>

Here’s an HTML page with a canvas and a link to a JavaScript file called Square.js. We’re going to use Square.js to create a couple of squares on the canvas in a really simple example of OOP. Here’s what’s in the Square.js file:

1
2
3
4
5
6
var Square = function(x,y) {
   this.x = x || 10;
   this.y = y || 10;
   this.w = 100;
   this.h = 100;
}

Square has four properties, x, y, w, and h. So, it will contain the x and y positions of the square and set the width and height to 100 pixels. I’ve set it up so that you can either pass the x and y coordinates to the square but if you don’t, it will default to 10 for either. That’s all we need to know about the Square object because we aren’t going to touch it again. Now, let’s write some code in the script tags in our HTML file. We’ll start off with a couple of variables:

1
2
var sq = new Square(120,200);
var sq2 = new Square();

I’m sure some people are wondering what’s going on here. Well, it’s actually pretty simple, we’re creating two objects, sq and sq2 and we’re giving the properties of the Square object but they’re both they’re own separate object. If this was a language like ActionScript 3, we’d say they were both created using the Square class. We’re also passing x and y coordinates to sq but not to sq2. Now let’s get prototyping!

1
2
3
4
5
Square.prototype = function(c) {
   this.color = c;
}
sq.color = '#00f';
sq2.color = '#f00';

All we’re doing here is adding a new property to the Square object called color so we give our squares their own colors. Now the point of doing this is this: We want to add to a new property of our Square class but we don’t want to change the original object because this might be something that we just need for this project.

And the rest of our JavaScript to actually draw the squares:

1
2
3
4
5
6
7
8
9
10
function init() {
   var canvas, ctx;
   canvas = document.getElementById('canvas');
   ctx = canvas.getContext('2d');
   ctx.fillStyle = sq.color;
   ctx.fillRect(sq.x,sq.y,sq.w,sq.h);
   ctx.fillStyle = sq2.color;
   ctx.fillRect(sq2.x,sq2.y,sq2.w,sq2.h);
};
init();

When this code runs, we get a red square and a blue square, both created using the Square object. So what’s the benefit of this? Well, let’s say you’re building a game, you can create a basic enemy class that would give all your enemies the same basic behaviors and properties instead of having to re-code them for each enemy. And then for each different type of enemy, you could use the prototype object to add the different or extra features they would all have. OOP is a really powerful way to code and JavaScript’s prototype makes it even better. As long as you know how to use it, that is.

Here’s the complete code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Prototype Test</title>
<style>
body {
    margin:0;
    padding:0;
    background:#000;
}
canvas {
    display:block;
    margin:30px auto 0;
    background:#fff;
}
</style>
</head>

<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script src="Square.js"></script>
<script>
var sq = new Square(120,200);
var sq2 = new Square();
Square.prototype = function(c) {
    this.color = c;
}
sq.color = '#00f';
sq2.color = '#f00';

function init() {
    var canvas, ctx;
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');
    ctx.fillStyle = sq.color;
    ctx.fillRect(sq.x,sq.y,sq.w,sq.h);
    ctx.fillStyle = sq2.color;
    ctx.fillRect(sq2.x,sq2.y,sq2.w,sq2.h);
};
init();
</script>
</body>
</html>