Prototip was developed by Nick Stakenburg and can be downloaded from http://www.nickstakenburg.com/projects/prototip2/. The latest version of Prototip is 2.0.5. You can download a trial of the plugin from the link above, which can be used for testing purposes (you’ll need this if you intend to follow along with the code examples in this article), but to use the plugin on single or multiple domains, you need to purchase a license.
You can also download the source files for this article in zip form.
The plugin is licensed as Creative Commons by-nc-nd, which means that there are certain conditions that must be met to use it; specifically, you must attribute the work to the author, you may not use the plugin commercially (i.e, you may not sell it), and you may not build upon, alter or make derivatives of it.
There are a range of pricing options that should suit most developers. These are outlined below:
Single non-commercial domain | 3 (approx $4 or £2) |
Unlimited non-commercial domains | 15 (approx $19 or £12) |
Single commercial domain | 49 (approx $63 or £41) |
Unlimited commercial domains | 295 (approx $378 or £248) |
Now that we have seen what Prototip is, where it can be found, and how much it costs, let’s see how easy it is to use. You’ll need to unpack the downloaded plugin, and will also need to download and unpack the Prototype library, and optionally the Scriptaculous effects library. To download both Prototype and Scriptaculous in a single package, visit http://script.aculo.us/downloads and choose the latest version.
We’ll need to set up a basic development area for the libraries and plugins to reside in; create a new directory on your C drive called prototip . Next, unpack the scriptaculous zip file into this folder, which will preserve the Prototype and Scriptaculous directory structure. In the Prototip zip file there are three folders: images , css and js . These can all be unpacked to the prototip directory as well. Finally, create a new folder within the prototip folder called pages .
{mospagebreak title=Basic Implementation}
Now that we’re ready to put Prototip to use, let’s make a basic example page that has some images on it which will produce the tooltips when they are hovered over — something like the following screen shot:
In a new page in your text editor start with the following code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<link rel="stylesheet" type="text/css" href="../css/prototip.css">
<link rel="stylesheet" type="text/css" href="../css/mytips.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Prototip Example</title>
</head>
<body>
<div id="container">
<label>Option 1</label><select><option>Choose an Option</option></select><a class="tip" id="help1" href="#" title="Help for option 1"></a>
<label>Option 2</label><select><option>Choose an Option</option></select><a class="tip" id="help2" href="#" title="Help for option 2"></a>
<label>Option 3</label><select><option>Choose an Option</option></select><a class="tip" id="help3" href="#" title="Help for option 3"></a>
<label>Option 4</label><select><option>Choose an Option</option></select><a class="tip" id="help4" href="#" title="Help for option 4"></a>
<label>Option 5</label><select><option>Choose an Option</option></select><a class="tip" id="help5" href="#" title="Help for option 5"></a>
</div>
<script type="text/javascript" src="../scriptaculous-js-1.8.2/lib/prototype.js"></script>
<script type="text/javascript" src="../scriptaculous-js-1.8.2/src/effects.js"></script>
<script type="text/javascript" src="../js/prototip.js"></script>
</body>
</html>
Save this as prototip1.html in your pages folder. It is essential that pages which use the Prototip plugin are placed in a folder at the same directory level as the images folder. This is because some of the elements that make up the tooltips have style attributes written to them when they are dynamically created by the plugin.
Our page contains the elements making up our test form; the labels, selects and the links that we’re going to use as the tooltip triggers. Each link has several attributes, including a title for use in situations where JavaScript is disabled. This is an important aspect of progressive enhancement, in which we define an inner core of base content, then where possible extend it. Following this we link to the Prototype, Scriptaculous and Prototip script files.
{mospagebreak title=The Style Sheet}
Our custom style sheet initially is going to be as simple as the page, and consists of the following selectors and rules:
#container {
width:243px; height:120px; border:1px solid #000000; padding:15px;
position:absolute; top:100px; left:100px;
}
#container label, #container select {
float:left; margin-right:12px; font-size:11px; font-family:Verdana;
font-weight:bold; position:relative; top:2px;
}
#container a {
float:left; width:25px; height:25px;
background:url(../images/help.gif) no-repeat;
}
This can be saved in the css folder as mytips.css . These two files (as well as the image used for the help icons, which can be found in the code download for this article and should be dropped into the images folder) should all go together to make the page from the first screen shot, although it won’t actually do anything yet.
Now for the fun part; after the <script> that links to prototip.js, add the following code:
<script type="text/javascript">
//get all trigger elements
var triggers = $$(".tip");
//add prototip for each trigger
triggers.each(function(item) {
//define each individual prototip
new Tip (item, item.readAttribute("title"));
//remove titles
item.writeAttribute("title", "");
});
</script>
We first get all of the anchor elements within our container and store them in the triggers array using standard Prototype syntax. We get the elements based on the class name tip which we gave to the anchors in the underlying HTML.
We then use Prototype’s each() method to iterate over each element stored in the array and execute an anonymous function for each one. Within this function we define a new Prototip tooltip using the Tip() constructor.
This constructor takes two arguments in this example. The first is the trigger element, which is the element on the page that will generate the tooltip when it is hovered over. The second argument is the content to use for the tooltip.
We pass our anonymous function the item argument, which contains the current item from the array. We specify the current item as the trigger and the title attribute (which we added in the underlying HTML) as the tooltip’s content.
Finally we use Prototype’s writeAttribute() method to set the title attribute to an empty string, which prevents the default OS tooltip from displaying, as well as the Prototip tooltip.
The result of this code is that, when the page is run, a new Prototip tooltip is created for each anchor element, as shown in the following screen shot:
As you can see, the standard tooltip generated by the OS is replaced by a very attractive Prototip complete with styling and behavior. The tooltip will automatically track with the mouse, will automatically be given cross-browser image-free rounded corners, and have its z-index adjusted so that it appears on top of other elements on the page. And this is just the default implementation with no additional configuration!
{mospagebreak title=Improving the Configuration}
Let’s move things up a notch by configuring some additional properties and improving our custom tooltips a little. Change the code in the last <script> tag to read:
<script type="text/javascript">
//get all trigger elements
var triggers = $$(".tip");
//define object containing tip contents
var content = {
tip1: "This is the help for option 1 etc…",
tip2: "Lorem ipsum dolor etc…",
tip3: "Lorem ipsum dolor etc…",
tip4: "Lorem ipsum dolor etc…",
tip5: "Lorem ipsum dolor etc…"
};
//add prototip for each trigger
triggers.each(function(item, i) {
//define each individual prototip
new Tip (item, content["tip" + i], {
title: item.readAttribute("title"),
style: "protoblue",
stem: "leftMiddle",
hook: { tip: "leftMiddle", mouse: true },
offset: { x:30, y:0 }
});
//remove titles
item.writeAttribute("title", "");
});
</script>
Save this version of the page as prototip2.html in the pages folder. The major addition to the code is the use of two new objects. The first is a literal object that we define to hold the text strings that will be used for the content of each tooltip. Storing these strings in an object is efficient and makes them easily retrievable later on in the code.
The second object is also a literal object, and is supplied to the Tip constructor as an optional third argument. This object contains the names of the properties and the values that we want to configure, and will be used internally by the Prototip plugin when it is initialized.
We configure a number of properties in this example. Let’s look at each one in turn. The title property is used to configure a heading for the tooltip. In this example we will be using the contents of the title attribute that we specified in our underlying HTML, instead of using this for the content as we did before.
We can specify a new theme for the tooltips using the style property; we can pick from a number of built-in themes for the plugin, or define a custom theme using the style property. The built-in themes we can choose from are:
default
protoblue
darkgrey
creamy
protogrey
The property we configure next is the stem property, which gives the tooltip a little speech-bubble spike to the specified bit of it. We’ve specified leftMiddle as the value of this property, but can pick from a number of compass-point locations around the edge of the tooltip. The stem property is set to false by default.
Following this, we define the hook property. Hooking describes how the tooltip is anchored to the target element (or mouse pointer); in the first example, the top-right corner of the tooltip was anchored to the bottom-left corner of the mouse pointer. In this example, the middle of the left edge of the tooltip will be anchored to the mouse pointer. This property takes the same compass-point values as the stem property.
You should note that both the stem and hook properties may be overruled depending on the size of the viewport and the value of the viewport property. The viewport property, which defines whether the tooltips should stay within the viewport or not, is set to true by default, and because we are hooking to the mouse pointer and not the trigger element, the tooltip will automatically hook to the opposite side of the mouse pointer using the opposite edge of the tooltip.
Finally we set the offset property; this property controls how far from the hooking element the tooltip should appear. We can set values for the x and y axis , which are relative to the tooltip. If we supply strings as the values of these properties instead of integers, they become absolute dimensions.
Another additional difference between this and the first example is that the anonymous function within the each() method is passed a second argument, i, which is the index of the current iteration. We use this to retrieve the correct string from the contents object on each iteration in the same way that we would use x in a traditional for…next loop. The following screen shot shows how the tooltips should now appear:
Summary
If you’re already making the most of Prototype, Prototip is the ideal tooltip solution; it is efficient and lightweight (a smaller version of the file we’ve used in this example is available), and very easy to configure, style and implement. We’ve only looked at a few of the more basic configurable properties in this article, but there are many more that are available for fine-tuning the plugin. In part two of this two-part tutorial we’ll be looking at how we can use the plugin’s built-in functionality for AJAX tooltips.