Bobby the Frog [ Credit: tdenham at stock.xchng ]

It's easy to convince your gullible mind that what you want is impossible when 1. it requires JavaScript and 2. JavaScript reads like gibberish. It's easy, that is, until you read 456 Berea Street and come across a god-awfully simple way to do it, at which point you actually have work to do. Grr.

Purpose

Create captionated images with the least amount of effort. While we're at it let's also add drop shadows. We want to do it in a way that doesn't lead to markup hell over time --- which is what usually happens when you have to add extra markup every single time you post an image. Since captions aren't required for user experience, (unobstrusive) JavaScript is the obvious way to go.

Meet the Markup

The only thing different about the markup is that all images that want to show a caption need to add a class definition saying that:

Bobby the Frog [ Credit: tdenham at stock.xchng ]

JavaScript will turn that into:

Bobby the Frog [ Credit: tdenham at stock.xchng ]

Bobby the Frog [ Credit: tdenham at stock.xchng ]

The CSS

Most of this is from the ALA article mentioned previously:

.drop-shadow
 {
  float: left;
  position: relative;
  margin: 10px 3px 0 10px !important;
  margin: 10px 3px 0 5px; 
  background: transparent url(images/drop_shadow.png) bottom right no-repeat !important;
  background: transparent url(images/drop_shadow_ie.gif) bottom right no-repeat;
 } 

 .drop-shadow img
 { 
  padding: 4px;
  display: block;
  position: relative;
  margin: -6px 6px 6px -6px;
  background-color: #ffffff;
  border: 1px solid #a9a9a9;
 } 

 .drop-shadow p
 {
  right: 8px !important;
  right: 11px;
  bottom: 5px;
  color: #eeeeee;
  padding: 5px 10px;
  position: absolute; 
  background-color: #2e333b;
  border-top: 1px solid #111111;
 }

The JavaScript

Download caption.js or copy-and-paste the next bit of code. Since it also uses the excellent Yahoo UI Library, you want that too.

var caption = 
 {
  init : function()
  {
   // Does the browser support the methods we use?
   if ( ! document.getElementById || ! document.createElement || ! document.appendChild )
   {
    return false;
   }

   // Find all images that want to get captionated
   var imageList = YAHOO.util.Dom.getElementsByClassName("captionated", "img", "document");

   for (i = 0; i < imageList.length; i++)
   {
    var current = imageList[i];

    var title = current.getAttribute("title");

    if (title == null || title == "")
    {
     title = current.getAttribute("alt");

     if (title == null || title == "")
     {
      continue; 
     }
    } 

    // Create the required elements

    var parent = current.parentNode;
    var cloned = current.cloneNode(true);
    var dropShadow = document.createElement("div");
    var captionParagraph = document.createElement("p");

    // Set styles

    YAHOO.util.Dom.addClass(dropShadow, "drop-shadow");
    YAHOO.util.Dom.setStyle(captionParagraph, "opacity", 0.8);

    captionParagraph.appendChild(document.createTextNode(title));

    dropShadow.appendChild(cloned);
    dropShadow.appendChild(captionParagraph);

    parent.insertBefore(dropShadow, current);
    parent.removeChild(current);

    // We like having our caption fill the entire width of the image, 
    // so let's do that. 

    var imageWidth = parseInt(current.getAttribute("width"), 10);

    var paddingLeft = parseInt(YAHOO.util.Dom.getStyle(captionParagraph, "padding-left"), 10);

    var paddingRight = parseInt(YAHOO.util.Dom.getStyle(captionParagraph, "padding-right"), 10);

    var finalWidth = imageWidth - paddingLeft - paddingRight;

    YAHOO.util.Dom.setStyle(captionParagraph, "width", finalWidth + "px");
   }
  }
 };

 YAHOO.util.Event.addListener(window, "load", function() { caption.init(); });

Errors?

I'm still very much a JavaScript novice. This little "project" is the first "real" thing that I attempted with JavaScript. So if there's a better way to do stuff or if there are any bugs, drop a comment. :-) One known issue is that I still can't get the padding/margin set right for the caption paragraph to span the whole image. :-(