Search

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 http://tech-cats.net/blog/examples/createParagraphPreview.html

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.

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

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

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
  $(currentElement).update(toggleCaption);

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

  // Return false so the link does not go anywhere
  return false;
}
</script>

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);
    });
    
    or
    document.observe("dom:loaded",
    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 http://tech-cats.net/blog/examples/createParagraphPreview.txt

// //]]>