Friday, February 01, 2008

Create a Paragraph Preview with Prototype.js

Creating a paragraph with expandable text can be quite useful if you have a lot of text on your page but do not want all of it to show in the same time. Something to the effect of:

This is a short preview of the paragraph (More)

so when the user clicks on "More" the full paragraph will be displayed like so:

This is a short preview of the paragraph and here is the more text you wanted to see.(Less)

You can see the simple example in action at

Here is how to create this with some simple HTML and JavaScript. The JavaScript relies on Prototype.js but it can be easily re-implemented with a different JavaScript framework.

	This is a short preview of the paragraph
	<div id="moreText" style="display: none">
	and here is the more text you wanted to see.

	<a class="showMore" href="#" rel="moreText">
		<span id="do_more_less">More</span>

And the JavaScript to do the magic:
<script type="text/javascript">
// For each link element that has the class name "showMore",
// tie the 'click' event to the 'showHide' function
Event.observe(window, 'load',
function() {
	$$('a.showMore').invoke('observe', 'click', showHide);

function showHide(event)
  // Use the event to get the id of the element that invoked the function
  var currentElement = Event.element(event);

  // Get the parent node of that element and the value of it's "rel" attribute
  var toggleContainer = $(currentElement).parentNode.getAttribute('rel');

  // Get the toggle caption based on the html of the clicked element
  var toggleCaption = ($(currentElement).innerHTML.toLowerCase() == "more") ? "Less" : "More";

  // Update the current element with the new caption value

  // If the container to be toggled exists, toggle it's visibility
  if ($(toggleContainer)) {

  // Return false so the link does not go anywhere
  return false;

Something to keep in mind is that you cannot simply copy the JavaScript in the head of the HTML page. That is because the line "$$('a.showMore').invoke('observe', 'click', showHide);", needs to fire after the HTML has been rendered. To resolve this, we can one of two things:

  1. Put the script in the head tag but wrap it inside a window load observer or dom:loaded event (if you are using Prototype v1.6) like so:
    Event.observe(window, 'load',
    function() {
    	$$('a.showMore').invoke('observe', 'click', showHide);
    function() {
    	$$('a.showMore').invoke('observe', 'click', showHide);
  2. Put the script as the last thing on the page, after the html.

The code can also be downloaded at

// //]]>