How to Auto Caption Images Using MooTools

MooTools is a powerful open-source JavaScript framework that can greatly enhance the way you build your web interfaces. Using MooTools will allow you to write succinct and elegant JavaScript within an intuitive framework. In this tutorial, we’re going to auto caption images on-the-fly using a bit of MooTools magic.

How to Auto Caption Images Using MooTools tutorial - leading image.

Together, we’re going to write a simple script that will:

  • Select all images with the class of captioned
  • Take its title attribute or alt attribute
  • Display it right below the image

You can see a live demo here. View the source code to explore for yourself how it works. You can download the source file package here.

HTML and CSS

The first thing we want to do is mark up our images. The HTML markup is simple:

<img class="captioned" src="red_rocks.jpg"
title="Photo of Red Rock Mountain." width="300" height="201" />

A few important points here:

  • If our image has both a title and an alt attribute, we’ll take the value of the title attribute over the alt attribute.
  • If our <img> doesn’t have a title or alt attribute, we’re going to alert the user that it needs one.
  • Declaring the value of the width property is required or our script will break.

CSS

Nothing fancy here, just a few basic style rules to make our caption pretty:

img {
padding:5px 0;
}
div.figure {
width:310px;
text-align:center;
border:1px solid #ccc;
background-color:#f2f2f2;
margin:5px;
float:left;
}
p.caption { padding:0; margin:0 0 5px 0; font:italic 12px Georgia, "Times New Roman", Times, serif; color:#333333; }

div.figure will be the container of our image and caption. p.caption will be our actual caption. We’re going to use MooTools to insert these two things in our Document Object Model (DOM).

The code logic: manipulating the DOM

Before we get into any code-authoring, let’s step through the logic of what we’re trying to accomplish.

First, we’re going to select all of the images in our structure that has a class of captioned. Then for each image that matches our criteria, we’re going to:

  1. Determine whether it has an alt or title attribute.
  2. If it has neither an alt or title attribute, we don’t do anything to the image and warn the user that the image needs at least one for our script to work.
  3. If we find both a alt and title attribute, then we will use the title attribute value for our caption.

Once we get the text for our caption, we will create a new DOM element, a paragraph element (<p>) called caption which will contain our caption text.

Once caption is created, we’ll create another DOM element (a div) to contain our image and caption. We will call this new DOM element figure.

Through DOM manipulation, we’re going to end up with an HTML structure like this:

<div class="figure">
  <img class="captioned" src="red_rocks.jpg"
    title="Photo of Red Rock Mountain." width="300" height="201" />
  <p class="caption">Photo of Red Rock Mountain.</p>
</div>

Of course, this will happen behind the scenes, but that’s basically what our HTML will look like after our MooTools script runs.

Initializing MooTools

Now that we have our HTML and CSS set up and we have a rough overview of what we’re going to do – we’re ready to start scripting!

First, we’ll initialize MooTools by wrapping all of our code inside the ‘domready’ event listener.

window.addEvent('domready', function() {
     ... Our code goes in here ...
});

What this method does is it tells MooTools that as soon as the DOM is ready, we’ll run our code. This way, we’re not waiting for the page to load before we execute our JavaScript.

Selecting and iterating through our images

We’ll select our images to be captioned by using the $$() function which is often called the "dollars" function. $$() is very intuitive and works almost exactly like CSS selectors. To select all images that have the class captioned, we write:

$$('img.captioned')

Tip: we can also just use $$('.captioned') assuming that you only use this class for images. To be safe – I’ve chosen to increase the specificity of our selector.

Next,we will iterate through each image that matches our criteria using the .each() method.

window.addEvent('domready', function() {
  $$('img.captioned').each(function(el) {
    ...Everything we write will go in here...
  });
});

Getting the text for our caption

We’re going to use the getProperty() method to pull out the title attribute value.

We’ll put this value inside a string variable called captionText.

To get the value, we write:

var captionText = el.getProperty('title')

In our HTML markup, the value of captionText should now be:

"Photo of Red Rock Mountain."

But we have to consider the situation that the image might have both an alt and a title property declared.

So, we’re going to use a ternary control structure to check if there’s a title and if we find it, then we’ll use that for our caption; if not, we’ll try to see if there’s an alt property and use that instead. If they both don’t exist, then captionText gets assigned a null value.

All together, our ternary operator is:

var captionText = ( el.getProperty('title')!=null )
                  ? el.getProperty('title') : el.getProperty('alt');

Note: ternary operators are just shorthand for if statements. You can easily convert the above code into nested if statements and it will work just fine. Have a go at it, convert this bit to an if structure. If you need help ask in the comments.

In plain english, this all translates to "If the current object’s title attribute value is not null, then captionText will take on that value; otherwise, captionText will take on the value of the alt attribute."

Explore: Here’s a good spot to explore by yourself. Try to modify our ternary operator so that the alt attribute takes precedence over the title attribute.

Making sure we have a caption

Before we do anything else, we have to make sure that our object will have a caption.

So we make sure the captionText doesn’t contain a null value. We’ll do this with a basic if control structure

if ( captionText!=null ) {
  //code to execute if we have a caption
} else {
  //code to execute if we encounter an error (Error-handling code goes here).
}

Error-handling

Let’s jump ahead to our error-handling and reporting. The method we’ll use is very rudimentary: if we find that the current object doesn’t have a caption (i.e. captionText != null evaluates to false), then we’re going to tell the user that this image needs either a title or an alt attribute.

alert('The image: "'+el.getProperty('src')+'" needs a title or alt value.');

To help identify the image, we take the src value, which outputs the location of our image.

IMPORTANT: This type of error-handling and reporting isn’t good practice; we used this in the example to make things easier on ourselves. But in production, you would want to replace this code with a better way to handle errors.

Messing around with the DOM

Now, we’re going to get into the thick of things – DOM manipulation. We’re going to insert two new elements in our Document Object Model; they are figure and caption.

The first element we’re going to make is the figure element. This element will be a div element that will contain our image and our other new element (caption).

Declaring our figure prototype

In order to create a new element in MooTools, we use the following structure:

var elementName = new Element('type of element', {its  properties})

We want figure to be a div with a class of figure and 10 pixels wider than our image (so that we have a 5-pixel margin on the left and the right).

Our prototype for figure then becomes:

var figure = new Element('div', {
  'class' : 'figure',
  'styles' : {
    'width' : el.get('width').toInt() + 10
  }
});

To get the width, we use the get() method, and then we convert the value to an integer with the .toInt() method. We then add 10 pixels (+ 10) to the width so that we get the 5-pixel margin on either sides of the image.

Are you with me so far? Keep up, we’re almost there!

Declaring our caption prototype

So we just built our first new element, figure. Now we have to build our second element, caption. caption will be a paragraph element (<p>) and will contain the caption’s text we took from our image (remember: it’s inside captionText).

Let’s get right to it, here’s our caption element prototype:

var caption = new Element('p', {
  'class' : 'caption',
  'html' : captionText
});

Review: Go to the MooTools Doc entry on the Element method: constructor to learn more about creating new elements.

In the above construction, we created a new element called caption. We told MooTools that we want it to be a paragraph (<p>) element that has a class of caption and the HTML that should be inside it is equal to captionText.

Manipulating the DOM

Wrapping our object inside figure

The first DOM manipulation that we’ll pull off is wrapping our object inside our figureelement. We’ll use the wraps() method which (as the name implies) wraps the target object of the method with the argument you pass into it.

with this in mind, all we have to do is write:

figure.wraps(el);

Inserting caption into the DOM

After that, we want to insert caption after our image. We’ll use the inject() method for this.

caption.inject(el,'after');

Summing up

Let’s bring everything together in one big chunk. Here’s the entire MooTools script.

window.addEvent('domready', function() {
  $$('img.captioned').each(function(el) {
    var captionText = ( el.getProperty('title')!=null )
                    ? el.getProperty('title') : el.getProperty('alt');
    if ( captionText!=null ) {
      var figure = new Element('div', {
        'class' : 'figure',
        'styles' : {
          'width' : el.get('width').toInt() + 10
        }
      });
      var caption = new Element('p', {
        'class' : 'caption',
        'html' : captionText
      });
      figure.wraps(el);
      caption.inject(el,'after');
    } else {
      alert('The image: "'+el.getProperty('src')+'" needs a title or alt value.');
    }
  });
});

What did we just do?

In this tutorial, we used the MooTools JavaScript framework to automatically display captions below images that have the class of captioned. We did this by selecting all the elements that matched our criteria, iterated through the matched set, and for each object in the matched set, we:

  1. Determined our caption’s text by getting the value of the object’s title attribute, and if it didn’t have one, then we defaulted to its alt attribute.
  2. Constructed the figure element that wraps around our image and caption.
  3. Constructed the caption element, a paragraph that has our image’s caption.
  4. Wrapped our image inside the figure element using the wraps() method.
  5. Injected caption right after our image using the inject() method.

We also made a very basic error-handling system that warns the user via an alert message that a title or alt value is required.

Review questions for beginners

This script is far from perfect. I chose to leave it that way to encourage you to explore MooTools and analyze the code we wrote together.

Here are some questions to try and answer yourself. I will post the answer in the comments section at a later date.

  1. Our script will break if the image doesn’t have a width attribute; what are some error-handling operations we can perform to prevent our script from breaking?
  2. What are other MooTools methods that could work in setting the width of the figure element?
  3. Is the .toInt() method a MooTools method or a native JavaScript method?

Download

You can download the source file package here. Please read README.txt for instructions on how to use this package.