MarkTaff.com

  • Increase font size
  • Default font size
  • Decrease font size
Home Software Joomla! Joomla! Image Captioning

Joomla! Image Captioning

E-mail Print PDF

The stock image captioning application in Joomla! 1.5, caption.js, modifies the DOM of the page in ways that are not standards-compliant.  The application inserts a <div> inside of a <p>, which obviously isn't permitted.  This leads to unpredictable page rendering, and outright chokes Konqueror 3.5.10.  Also, the existing application doesn't work for images inside of a hyperlink, which is downright silly, IMO.

I have rewritten caption.js to produce a valid structure using nested span tags.  This nesting also permits nice styling of captioned image borders.

I have tested this in the current versions of IE, FF, Safari, Konqueror, Opera, and Chrome.  I do not have access to any boxes still running IE 6, so I have not tested it on IE 6.  I'm not too concerned about supporting IE 6, especially as Microsoft is putting the finishing touches on IE 8.  That said, if you have access to IE 6, please let me know if the captioned images look acceptably close to how IE 7 or FF 3 renders them, so I can update this page.

The CSS

To style the captioned image, add these properties to your Joomla! theme's template.css file:

  1. /*
  2.  * BEGIN Properties for Improved Auto-Captioning script, caption.js
  3.  */
  4.  
  5. /* Outermost container holding a captioned image, generated by caption.js */
  6. .captioned_image_container
  7. {
  8. /* How much space between container & surrounding content? */
  9. margin: 8px 8px 2px 8px;
  10. /* How much space on between container & the contained content? */
  11. padding: 0px;
  12. display: block;
  13. text-align: left;
  14. width: auto;
  15. border: 1px solid #ccc;
  16. }
  17.  
  18. .captioned_image_border
  19. {
  20. padding: 0px;
  21. text-align: left;
  22. display: block;
  23. }
  24.  
  25. .image_wrapper, .img_caption
  26. {
  27. }
  28.  
  29. /* Container holding image & maybe a link */
  30. .image_wrapper
  31. {
  32. display: block;
  33. width: auto;
  34. }
  35.  
  36. /* Container holding the image's caption */
  37. .img_caption
  38. {
  39. text-align: center;
  40. display: block;
  41. padding: 2px;
  42. }
  43.  
  44. /* The captioned image itself */
  45. .caption, .caption2
  46. {
  47. padding: 3px;
  48. }
  49.  
  50. /*
  51.  * END Properties for Improved Auto-Captioning script, caption.js
  52.  */
  53.  

Caption.js

Here is the improved version of caption.js

  1. /**
  2. * @version $Id: modal.js 5263 2006-10-02 01:25:24Z webImagery $
  3. * @copyright Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
  4. * @license GNU/GPL, see LICENSE.php
  5. * Joomla! is free software. This version may have been modified pursuant
  6. * to the GNU General Public License, and as distributed it includes or
  7. * is derivative of works licensed under the GNU General Public License or
  8. * other free or open source software licenses.
  9. * See COPYRIGHT.php for copyright notices and details.
  10. *
  11. * Additional Copyright (c) 2008 Mark A. Taff <marktaff@comcast.net>
  12. * 20081123 Mark A. Taff:
  13. * The existing caption.js handled images within anchor tags inelegantly,
  14. * to be very kind. It now handles them better, so the caption text
  15. * is no longer a hyperlink, just the image is.
  16. *
  17. * In some instances, it also made the link take up the entire block,
  18. * in some cases making large chunks of the page a single link!
  19. * Links should not be so large nor so invisible as to make them easy to
  20. * inadvertently click on. ;-)
  21. *
  22. * Also, this new version spits out a valid DOM based on valid XHTML, so
  23. * Konqueror handles it properly. Konqueror 3.5.10 chokes on the old
  24. * version due to invalid XHTML (<div> inside of <p>).
  25. *
  26. * Changes licensed under the GNU/GPL, see LICENSE.php.
  27. *
  28. * 20090516 Mark A. Taff:
  29. * Incorporated changes submitted by Niklas Albin Svensson (Thanks!) on 20090511,
  30. * Copyright (c) 2009 In Defence of Marxism <webmaster@marxist.com>. Now we look first for
  31. * caption text in the title attribute, then in the alt attribute. This change makes
  32. * the script play nicer WYSIWYG editors.
  33. *
  34. * Also make it respect newlines in the caption, so it works with SlideShowPro Director
  35. * more smoothly. For the old behaviour, set `var respectNewLines = false;` in appendCaption().
  36. */
  37.  
  38.  
  39. /**
  40.  * JCaption javascript behavior
  41.  *
  42.  * Used for displaying image captions
  43.  *
  44.  * @package Joomla
  45.  * @since 1.5
  46.  * @version 1.0-taff-20090516
  47.  */
  48. var JCaption = new Class({
  49. initialize: function(selector)
  50. {
  51. this.selector = selector;
  52.  
  53. var images = $$(selector);
  54. images.each(function(image){ this.createCaption(image); }, this);
  55.  
  56. /** @bug: fixed. Force IE 7 to re-layout page after captions are applied. We just
  57.   * temporarily append an arbitrary string ("forceReflow") to the body tag's
  58.   * classname. This make IE re-calc relatively & absolutely positioned elements.
  59.   */
  60. var body = document.getElementsByTagName( "body" )[0];
  61. var bodyClass = body.className;
  62. body.className = bodyClass+"forceReflow";
  63. body.className = bodyClass;
  64. },
  65.  
  66.  
  67.  
  68.  
  69. createCaption: function(image)
  70. {
  71. var parent = image.parentNode;
  72. var grandparent = parent.parentNode;
  73.  
  74. // Create new elements...
  75. var captioned_image_container = document.createElement("span"); // container to hold captioned_image_border
  76. var captioned_image_border = document.createElement("span"); // container to hold image_wrapper
  77. var image_wrapper = document.createElement("span"); // container to hold image_caption
  78. var image_caption = document.createElement("span"); // container to hold the caption
  79. var text = document.createElement("span"); // span tag to hold the caption text
  80. var caption = "";
  81.  
  82. // Get the caption text, check first for title, then for alt
  83. if ( image.title != "" )
  84. { caption = image.title; }
  85. else if ( image.alt != "")
  86. { caption = image.alt; }
  87. else
  88. { caption = ""; }
  89.  
  90. // ...and assign their CSS classes, as needed
  91. captioned_image_container.className = "captioned_image_container";
  92. captioned_image_border.className = "captioned_image_border";
  93. image_wrapper.className = "image_wrapper";
  94. image_caption.className = "image_caption";
  95.  
  96.  
  97. // Get spec'd width, alignment & float properties from image
  98. var image_width = image.getAttribute("width");
  99. var align = "";
  100.  
  101. if (image.style.styleFloat)
  102. {align = image.style.styleFloat;} // IE
  103.  
  104. else if (image.style.cssFloat)
  105. {align = image.style.cssFloat;} // Standards-compliant browsers
  106.  
  107. else if (image.getAttribute("align"))
  108. {align = image.getAttribute("align");} // Non-CSS, old HTML
  109.  
  110. else
  111. {align = "";}
  112.  
  113. // Is the image within an anchor tag?
  114. if (parent.nodeName == "A")
  115. {
  116. var link = parent;
  117.  
  118. // Insert new span container right before the link
  119. grandparent.insertBefore(captioned_image_container, parent);
  120. captioned_image_container.appendChild(captioned_image_border);
  121. captioned_image_border.appendChild(image_wrapper);
  122.  
  123. // Set alignment/float
  124. captioned_image_container.setAttribute("style","float: "+align);
  125. captioned_image_container.style.styleFloat = align; // IE
  126.  
  127. // Reparent the link
  128. var removedLink = grandparent.removeChild(link);
  129. image_wrapper.appendChild(removedLink);
  130.  
  131. // If the caption is set
  132. if ( image.title != "" || image.alt != "" )
  133. {
  134. // Insert & format new span for caption
  135. captioned_image_container.appendChild(text);
  136. text.setAttribute("style","display: block");
  137. text.className = this.selector.replace('.', '_'); // Set span class
  138.  
  139. // Insert the caption itself
  140. this.appendCaption(caption, text);
  141. }
  142. }
  143. else // Image without a link
  144. {
  145. // Insert new span container right before the image
  146. parent.insertBefore(captioned_image_container, image);
  147. captioned_image_container.appendChild(captioned_image_border);
  148. captioned_image_border.appendChild(image_wrapper);
  149.  
  150. // Set alignment/float
  151. captioned_image_container.setAttribute("style","float: "+align);
  152. captioned_image_container.style.styleFloat = align; // IE
  153.  
  154. // Reparent the image
  155. var removedImage = parent.removeChild(image);
  156. image_wrapper.appendChild(removedImage);
  157.  
  158. // If the caption is set
  159. if ( image.title != "" || image.alt != "" )
  160. {
  161. // Insert & format new span for caption
  162. captioned_image_container.insertBefore(text, null)
  163. text.setAttribute("style","display: block");
  164. text.className = this.selector.replace('.', '_'); // Set span class
  165.  
  166. // Insert the caption itself
  167. this.appendCaption(caption, text);
  168. }
  169.  
  170. } // End if (parent.nodeName=="A") ... else
  171.  
  172. // Set widths/heights as needed for the various containers
  173. image_wrapper.style.width = image.offsetWidth+"px";
  174. image_wrapper.style.height = image.offsetHeight+"px";
  175. captioned_image_border.style.width = image_wrapper.offsetWidth+"px";
  176. captioned_image_container.style.width = captioned_image_border.offsetWidth+"px";
  177.  
  178. }, // End method createCaption(element)
  179.  
  180.  
  181.  
  182.  
  183. // Inserts a caption, respecting newlines
  184. appendCaption: function(caption, text)
  185. {
  186. // Set to false ignore newlines in caption text
  187. var respectNewLines = true;
  188.  
  189. if (respectNewLines)
  190. {
  191. var captionLines = caption.split("\n");
  192.  
  193. for(i=0; i < captionLines.length; ++i)
  194. {
  195. line = document.createTextNode(captionLines[i]);
  196. br = document.createElement("br");
  197. text.appendChild(line);
  198. text.appendChild(br);
  199. }
  200. }
  201. else
  202. {
  203. text.appendChild(caption);
  204. }
  205. }
  206.  
  207. });
  208.  
  209. document.caption = null
  210. window.addEvent('load', function() {
  211. var caption = new JCaption('img.caption')
  212. document.caption = caption
  213. });
  214.  

Download & Install

I strongly suggest that you rename the existing caption.js (to caption.js.bak, for example) rather than overwriting or deleteing it.  That way, you can always easily reinstall the original should you need to.  Download caption.js. Once you have the original archived, simply upload the new version.  Don't forget to add the new CSS properties to your template.css file.

 

 

Last Updated ( Wednesday, 28 January 2009 22:05 )  

Quotes, Aphorisms & Epigrams

Computers do not solve problems, they execute solutions. Laurent Gassar