JQuery_ Novice to Ninja - Earle Castledine [55]
The basis for our widget is a JavaScript object literal (the same kind we’ve been using to pass sets of multiple options to jQuery actions) to define the name of our widget: var gallery = {};. As we’ve seen so far, object literals are enclosed in curly braces ({}). The object is empty to start with, but we’ll be filling it up soon enough. Putting all our code in an object like this will give our code a named boundary, which limits the chance of any of our scripts conflicting with others that may be in the page. Setting up an empty object is how we’ll begin implementing most of our widgets.
Next, we can add properties and methods to make our widget actually perform functions. By adding properties to our object, we remove the risk that any variables in the page might be overwritten by other scripts:
chapter_04/15_iphoto_style_slideshow/script.js (excerpt)
gallery.trigger = $("#photoshow .photoshow-trigger");
gallery.content = $("#photoshow .photoshow-content");
gallery.scroll = false;
gallery.width = 240;
gallery.innerWidth = gallery.content.width();
gallery.timer = false;
When we write gallery.timer = false, it’s the same as if we’d written:
var gallery = {
var timer = false;
}
The . (dot) notation is a shortcut for reading and writing properties of objects from outside of the object’s declaration. If it’s a little unclear, be assured it will make more and more sense as you see it used in our examples.
Let’s take a look at what we’ve made for ourselves: gallery.trigger is a reference to a jQuery selection of our trigger link, and gallery.content is our list of images. We can now utilize these much shorter names, which saves us typing out the full selector string every time we want to use them. It also means we can easily point out a script at a different gallery on a different page, just by changing these values.
The next properties we assign to our gallery object are functions. We have gallery.offset, which sets how far we move the sliding list; gallery.slide, which moves the list and causes it to keep moving; the cunningly named gallery.direction that sets the direction of the slideshow’s scroll; and a trusty initializing method, gallery.init. Let’s take a look at each in turn:
chapter_04/15_iphoto_style_slideshow/script.js (excerpt)
gallery.offset = function() {
var left = gallery.content.position().left;
if (gallery.scroll == '>') {
if (left < 0) {
left += gallery.width;
}
} else {
if (left <= 0 && left >= ((gallery.innerWidth * -1) +
↵(gallery.width * 2))) {
left -= gallery.width;
}
}
return left + "px";
}
The first task we do in gallery.offset is set a variable holding the left property of our list relative to the holding div. By using position rather than offset, jQuery saves us the trouble of working where the gallery is relative to the viewport.
We then check the direction we want to scroll the thumbnails, and that we still have room to scroll, and if all’s well we generate the new value for left (by adding our 400px width property to the current left value) and return it. Note that we need to add "px" to the value before returning it, since we’ll be using it as a CSS property.
So gallery.offset does nothing but calculate how far to slide the gallery along. You might be thinking, “Why not just calculate that inside the gallery.slide function?” By moving this functionality into its own method we make it more usable, should we ever need to access it from a different context than sliding the gallery. It also helps us to avoid nesting our code too deeply, which would make it more difficult to read. Here’s the function:
chapter_04/15_iphoto_style_slideshow/script.js (excerpt)
gallery.slide = function() {
if (gallery.timer) {
clearTimeout(gallery.timer);
}
if (gallery.scroll) {
$(gallery.content)
.stop(true,true)
.animate({left: gallery.offset()}, 500);
gallery.timer = setTimeout(gallery.slide, 1000);
}
}
Our slide method’s first job is to check if gallery.timer is set. If it is, setTimeout has already been called, so we call clearTimeout just to be on the safe side. We