JavaScript is the new black, in website development terms at least. But if your scripts aren't dressed in the latest unobtrusive styles and accessorised with some stylish progressive enhancement you'll be laughed at.
So what's a bunny to do? Why, get Performing! Performer is a library of functions built on the magnificent Prototype framework, however it's completely unobtrusive. That's right, it uses HTML element attributes to hook into the Prototype DOM and AJAX functions dynamically.
Let's say you want to have a particular paragraph on your web page that is hidden by default, but you want it to appear when someone clicks a link. For this example the code will look something like this:
<h1>The Magical Disappearing Paragraph!</h1> <p>You think there's just one paragraph here, right? Wrong! <a href="#">Click me to see the magic in action!</a></p> <p>Hurrah! It works! <a href="#">Now click me to unleash the powers of disappearance.</a></p>
Pretty and simple, yes? But it doesn't do anything yet. So let's add some Performer eye of newt and hair of frog to our HTML.
<h1>The Magical Disappearing Paragraph!</h1> <p>You think there's just one paragraph here, right? Wrong! <a href="#" "class="toggler" rel="extrainfo">Click me to see the magic in action!</a></p> <p id="extrainfo" class="hider">Hurrah! It works! <a href="#" "class="toggler" rel="extrainfo">Now click me to unleash the powers of disappearance.</a></p>
As you can see, the second paragraph appears and disappears as if by magic. You want to know the best part? If the browser you're using doesn't have JavaScript enabled then the second paragraph is never hidden, therefore you see it absolutely fine.
Well, let's take a look at what we added, and I'll explain how I think it works (because, frankly, I only have a tenuous grasp of this stuff).
So we can get to the second paragraph it is given an id of extrainfo. We also give it a class of hider, which tells Performer to hide that paragraph when the page is loaded. Because Performer only works when JavaScript is enabled, visitors with no JavaScript support will still see the paragraph.
To toggle the visibility of the extrainfo paragraph we add some attributes to the link. Those attributes are:
class="toggler"rel="extrainfo"And that's it! When the page is loaded Performer firstly find all the elements with a class of 'hider' and hide them, then it will find the links with a class of 'toggler', get the id of the element that each of those links is meant to toggle, and when the toggler links are clicked it toggles the visibility of the relevent element. Phew! It sounds a lot, but as you can see it's really easy to use.
As the second paragraph is only hidden when JavaScript is enabled, therefore people without JavaScript will still get to see it, you can leave the href of the link as '#' (i.e., going nowhere). However if you want to you can set this attribute to anything you like. You can also add other class names to the class attribute of any Performer element (say if you want to add your own styles) and Performer will work round them, thanks to the magic of Prototype.
That example is pretty simple, but it shows the basic idea behind Performer - that existing but rarely-used element attributes can store information about advanced functionality.
Let's try something a little more advanced - loading information from another page to update the contents of a particular element. This is the crux of that oh-so-fashionable AJAX thing which is currently taking the web by storm. Let's start with some simple HTML with the required Performer attributes.
<h1>The Wondrous Clicky Updaty Thingy!</h1>
<p>So you want to see what the current time is, yes? No problem! <a href="demo3.php" "class="loader" rel="time.php" rev="timedisplay">Click me to update the time below.</a></p>
<p id="timedisplay">The current time is: <?php print date("H:i:s"); ?></p>
The astute among you will notice I've added something extra in there, namely some PHP code which displays the current server time. Note: this is the current time on the web server, not necessarily the current time on your desktop machine.
When the page is loaded the current server time is shown, click here to see it in action. When you click the link to update the time a behind-the-scenes JavaScript call is made that fetches some text (i.e. the new current time) from another page and displays it in the named element. Just like before we've got some attributes that tell Performer what action it needs to perform.
class="loader"rel="time.php"rel="timedisplay"The code on the time.php page is merely:
The current time is: <?php print date("H:i:s"); ?>
If the gods are smiling on us we should be able to see the time being updated. And all without writing a single line of JavaScript, just a couple of extra attributes for our link. Note that the href attribute of the link is set to 'demo3.php' (the same page) so that if JavaScript isn't enabled the user still gets the current time - by reloading the page. All the Performer functions work like this, so you never have to override the natural action of the link.
In essence this is what Performer does - allows you to unobtrusively add some simple dynamic effects to pages without writing any JavaScript code. There are just two things you need to do to each page you want to use Performer on. One is include the Prototype framework script, and the other is include the Performer library. Sample code to do this is shown below:
<script type="text/javascript" src="prototype.js"></script> <script type="text/javascript" src="Performer.js"></script>
Because Performer stops the natural action of any link it processes, you don't have to worry about your carefully crafted href attribute being loaded by mistake. At the moment there are two types of Performer actions: ones that happen when the page is loaded (such as Hider) and ones that happen when a link is clicked (such as Toggler and Loader). Eventually I will be updating Performer so it can be hooked into other types of elements actions, such as the pressing of a button.
Now some of you may be thinking "Why bother?", and you'd be perfectly within your right to do so. Well, the answer is this. I use this set of functions almost every day when building websites, and I thought some other people might like it. So there you have it; I'm just a nice guy giving stuff away.
Here are brief details of the functions currently available in Performer. Most of these are triggered by a link being clicked unless otherwise stated. For full details please refer to the documentation.
textarea or input box.H1, H2, blockquote and many more) into an inline form when the text is clicked. This allows you to provide in-place editing for short pieces of text (usernames, password etc.).textarea or input type="text" element to prompt the user on what they should type in. The text disappears when they click into the element, and reappears if the box is still empty when they click out.Please note the current version of Performer has been rewritten to work with prototype 1.6. If you need the older version of Performer which works with prototype 1.5 then you can download it here.
Just click here to download the current version of Performer. You'll also need the Prototype JavaScript file, and I recommend you follow Andrew Duponts instructions to reduce the size of Prototype by quite a lot. It appears that this doesn't work with prototype 1.6, so until a way can be found to compress prototype I'm afraid you're stuck with the full version.
I heartily thank kourge for suggestions and help with streamlining the JavaScript code, and Pete Yandell for reminding me I need to keep Performer up to date.
Remember to check back regularly for updates to Performer, I have a lot more planned for it.
Performer is licensed under a Creative Commons Attribution-Share Alike 3.0 License.
All elements using Performer functions require a id attribute, whether they are links, textual elements, form fields or anything else. The id must be unique on the page, and is vital for Performer to know what elements it is dealing with.
Here are details of all the functions that Performer offers.
Sets the element as being invisible. This happens when the page is loaded.
class Requiredhider'.<p class="hider">This element will be made invisible when the page loads</p>
Toggles the visibility of an element. This happens when the link is clicked.
class Requiredtoggler'.rel Requiredid attribute of the element to be toggled.<p><a href="#" class="toggler" rel="targetelement">Toggle element</a></p> <p id="targetelement">Target element</p>
Loads content from a remote file into an element. This happens when the link is clicked.
class Requiredloader'.rel Requiredid attribute of the element to be filled.rev Required<p><a href="#" class="loader" rel="targetelement" rev="targetpage.php">Load content</a></p> <p id="targetelement">Target element</p>
Loads content from a remote file into an element. This happens when the page is loaded.
class Requiredpreloader'.rel Required<p class="preloader" rel="targetpage.php">Load content</p>
Loads content from a remote file into an element and displays that element if it is set as invisible. This happens when the link is clicked. Used in conjunction with Hider.
class Requiredtoggleloader'.rel Requiredid attribute of the element to be filled.rev Required<p><a href="#" class="toggleloader" rel="targetelement" rev="targetpage.php">Load content</a></p> <p id="targetelement" class="hider">Target element</p>
Resizes an element. This happens when the link is clicked.
class Requiredsizer'.rel Requiredid attribute of the element to be resized.rev Required<ul> <li><a href="#" class="sizer" rel="targetelement" rev="20">Make the box 20px longer</a></li> <li><a href="#" class="sizer" rel="targetelement" rev="-20,">Make the box 20px shorter</a></li> <li><a href="#" class="sizer" rel="targetelement" rev=",20">Make the box 20px wider</a></li> <li><a href="#" class="sizer" rel="targetelement" rev=",-20">Make the box 20px thinner</a></li> <li><a href="#" class="sizer" rel="targetelement" rev="50,50">Make the box 50px bigger</a></li> <li><a href="#" class="sizer" rel="targetelement" rev="-50,-50">Make the box 50px smaller</a></li> </ul> <p class="box" id="targetelement">This is the target element</p>
Focusses the cursor on an element. This happens when the page is loaded. This works best with form fields.
class Requiredfocusser'.<p><input type="text" id="field" class="focusser" value="This field will be focussed when the page is loaded"</p>
Switches the visibility of multiple elements within a group. This happens when the link is clicked.
class Requiredfocusser'.rel Requiredid attribute of the tab group. A tab group MUST have an id attribute.rev Requiredid attribute of the target tab. Each tab element within a tab group MUST have an id attribute, and MUST also have a class attribute set to 'tab'. This is so Performer can decide what is a tab and what isn't. As in the example below, the Hider function can be used to hide all tabs except the one that you want to be shown by default.<ul>
<li><a href="#" class="tabber" rel="tabgroup1" rev="tab1">Show tab 1</a></li>
<li><a href="#" class="tabber" rel="tabgroup1" rev="tab2">Show tab 2</a></li>
<li><a href="#" class="tabber" rel="tabgroup1" rev="tab3">Show tab 3</a></li>
</ul>
<div id="tabgroup1">
<p id="tab1" class="tab">This is the text inside tab 1.</p>
<p id="tab2" class="tab hider">This is the text inside tab 2.</p>
<p id="tab3" class="tab hider">This is the text inside tab 3.</p>
</div>
Send the value of a select element to a remote page and loads the response into a target element. This happens when the select option is changed. Note: because of the limitations of valid attributes for select elements the parameters for this function are set in the class attribute. The value of the select element is passed to the remote page as a querystring parameter called 'selection'.
class Requiredselector'.class Requiredclass name to 'targetEl-' then the id attribute of the target element. For example targetEl-targetelement.class Requiredclass name to 'targetPage-' then the URI of the remote file. For example targetPage-selection.php. Please note this MUST be on the same domain as the requesting file due to JavaScript security restrictions.<p>
<select name="list" id="list" class="selector targetEl-targetelement targetPage-selection.php">
<option value="List item 1">List item 1</option>
<option value="List item 2">List item 2</option>
<option value="List item 3">List item 3</option>
</select>
</p>
<p id="targetelement">Target element</p>
Limit the amount of text that can be entered in a textarea or input box. This happens when a key is pressed. A separate element initially shows the total number of characters that can be entered, and the text of this element changes as more characters are used.
class Requiredlimiter'.class Requiredclass name to 'targetEl-' then the id attribute of the element to show how many characters are left. For example targetEl-notifier.class Requiredclass name to 'lengthLimit-' then the maximum characters that is allowed to be entered in the field. For example lengthLimit-24.<p> <input type="text" name="text" id="text" class="limiter targetEl-notifier lengthLimit-24" /> </p> <p id="notifier"></p>
Opens a popup window with the settings you require. This happens when the link is clicked. The focus is set to the new window when it is opened. The href attribute of the link is used as the target URL for the popup window.
class Requiredpopper'.href Requiredrel Requiredrev Required<p> <a href="http://www.google.com" rel="searchbox" rev="width=400,height=300,location=no,menubar=no,status=no,toolbar=no">Search the web using Google</a> </p>
Changes an element into a single-line text input box in a form, so you can edit text in place. A single click or keypress on an element will turn it into a text input box.
Please note: this function does not use the rev and rel attributes so it can be used on a wide variety of textual elements (H1, H2, blockquote etc).
The value of the edited text is sent to the target page with a name equal to the id attribute you give to the original element. So if you give the editable text an id of 'editabletext' you can access it in your target page using <?php print $_POST["editabletext"]; ?> (in PHP).
A class of "performer-editor" is applied to the editor form. You can use this to set the display properties of the form.
class Requirededitor'.class RequiredtargetPage- then the location of the page that will receive the sent form, for example targetPage-savetext.php. This target page could be relative (as in this example, or absolute like http://www.mysite.com/savetext.php.<p id="editabletext" class="editor targetPage-savetext.php">This is the text I will edit</p>
Adds a piece of text to an input text box or textarea element that prompts users to type in the correct data. When the element has focus (the cursor is in the box) then the message disappears, when the elelment loses focus (the user moves to another element on the page( the message returns if nothing has been typed in.
This function will only work on input type="text" and textarea elements.
A class of "performer-prompter" is applied to the textarea when the prompt is being shown. You can use this to set the text colour of the prompt to one of your choosing. In the example the prompt colour is set to grey.
class Requiredprompter'.title Required<p><input id="fullname" name="fullname" class="prompter" title="Please enter your full name" /></p>
Checks the strength of a password as it is typed into a text box, showing a message about the strength of the password in a separate notification element. The strength is determined like this:
For full details see the Performer source code.
This function will only work on input type="text" elements.
Several CSS classes are applied to the notification element depending on the strength of the password. These classes are:
password-failpassword-weakpassword-okpassword-strongclass Requiredpasswordchecker'.class RequirednotifyEl- then the ID of the element that will display the message, for example notifyEl-passnotify.name Required<p><input type="password" id="pass" name="pass" class="passwordchecker notifyEl-passnotify" /><br /><span id="passnotify"></span></p>;
Checks the values of two text boxes and displays a message saying whether they match in a notification element.
This function will only work with two input type="text" elements.
class Requiredmatcher'.class RequiredmatchEl- then the ID of the element that you want to be compared to this element, for example matchEl-pass2.class RequirednotifyEl- then the ID of the element that will display the message, for example notifyEl-passmatch.<p><input type="password" id="pass1" name="pass1" /></p>
<p><input type="password" id="pass2" name="pass2" class="matcher notifyEl-passnotify matchEl-pass1" /><br /><span id="passnotify" class="error hider">Your passwords do not match</span></p>