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.
Together, we’re going to write a simple script that will:
- Select all images with the class of
captioned
- Take its
title
attribute oralt
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:
- Determine whether it has an
alt
ortitle
attribute. - If it has neither an
alt
ortitle
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. - If we find both a
alt
andtitle
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 figure
element. 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:
- 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 itsalt
attribute. - Constructed the
figure
element that wraps around our image and caption. - Constructed the
caption
element, a paragraph that has our image’s caption. - Wrapped our image inside the
figure
element using thewraps()
method. - Injected
caption
right after our image using theinject()
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.
- 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? - What are other MooTools methods that could work in setting the width of the
figure
element? - 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.
- sr-auto-caption-1.0.zip (ZIP, 71.3 KB)
