Articles: 843 | Categories: 148   
   
   
Home Articles Contact Us
 
 
 
 
How Prototype Extends Elements (0 Comments)
Admin: Posted Date: April 4, 2010

In the first article of this series ("Week 1, Beginning with Prototype") I showed you different methods for accessing elements in the DOM, as well as how to create new elements.

How Prototype Extends Elements

Introduction

In the first article of this series ("Week 1, Beginning with Prototype") I showed you different methods for accessing elements in the DOM, as well as how to create new elements. Whenever you select (or create) elements, each element is automatically extended with extra functionality by Prototype. Essentially, this is a number of methods that help you manipulate the behaviour of the element more easily.

In this article I will show you a selection of the most useful methods, including various examples of using (and combining) these methods. While the methods covered here are not exhaustive.

In actual fact, we've already seen some of these methods in the first article. Namely, we have already looked the following methods:

  • update() – Used to update the inner HTML of the target element. We will look at some more examples of this method shortly.
  • select(), up(), down(), previous() and next() – Used to other elements in the DOM relative to the target element.
  • insert() – Used to add a new element to the DOM relative to the target element.
  • remove() – Used to remove the target element (and its children) from the DOM.
  • hide() and show() – Only mentioned in passing so far, these are used to hide an element from the view of the user and to show it again. I will show you some examples of using these methods.

Firstly, I will show you more about how the update() method works, used to modify the content of an element. I will also show you how to then read that content. Additionally, you will learn how to read and write element attributes using JavaScript.

Next, I will show you how to manage the CSS classes of elements, as well as how to manipulate the styles of elements in real-time. Prototype also makes it easy to determine the width and height of elements, which I will also show you.

Following this, you will learn how to show and hide elements in the user's display. I will show you some practical examples of where it is useful to do so.

Reading and Writing an Element's Content

In this section I will show you firstly how to update the inner content of an element using Prototype. There may occasions where you need to read the content rather than write it, so I will also show you how to do that.

After this I will show you how to read and write attributes. Writing attributes is extremely when including a particular attribute in your HTML source will break the page's standards compliance. That is, this technique is most useful for managing non-standard attributes.

Updating the Content of an Element

To update the content of an element, the update() method is called on that element. This method takes either no arguments or exactly one argument. If no arguments are specified, then the content of the element is cleared. Otherwise, the content of the element is updated to be whatever is specified as the first argument.

When calling update(), there are several different types of data you can use as the first argument in order to update the content of the given element. That is, you can pass plain text, a HTML snippet, or you can pass a JavaScript object (this includes elements created by instantiating the Element class, as shown in the first article of this series).

Listing 1 shows a basic example of using update() to clear the contents of an element. In this example, the div begins with some text content but when you view the page this content no longer exists.

Listing 1 Clearing the content of an element using update() (listing-1.html)
<html>
<head>
<title>Clearing the content of an element using update()</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
This content will soon be gone!
</div>
<script type="text/javascript">
$('foo').update();
</script>
</body>
</html>

If you want to change the contents of an element (rather than clearing it), you can pass the new content of the element as the first argument to update(). As discussed above, there are several different types of content you can pass to update.

Listing 2 shows the simplest case of using update(). In this example a plaintext string is used as the new content of the #foo element.

Listing 2 Updating an element to display a string (listing-2.html)
<html>
<head>
<title>Updating an element to display a string</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
You won't see this content
</div>
<script type="text/javascript">
$('foo').update('You will see this content');
</script>
</body>
</html>

Similar to use using a plaintext string, you can use a string that contains HTML tags. Listing 3 shows an example of doing so.

Listing 3 Updating an element with a HTML string (listing-3.html)
<html>
<head>
<title>Updating an element with a HTML string</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
You won't see this content
</div>
<script type="text/javascript">
$('foo').update('You will see this <a href="http://www.example.com">hyperlink</a>');
</script>
</body>
</html>

In the first article of "Eight Weeks of Prototype" I showed you how to create an element by instantiating the Element class. Any element you create in this manner can also be passed to the update() method. This is an alternative method to calling insert() to actually insert the element into the DOM.

Listing 4 shows an example of creating a hyperlink and adding it to the #foo element.

Listing 4 Passing an element to update() (listing-4.html)
<html>
<head>
<title>Passing an element to update()</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
You won't see this content
</div>
<script type="text/javascript">
var link = new Element('a', { href : 'http://www.example.com' });
link.update('This is the link text');
$('foo').update(link);
</script>
</body>
</html>

In fact, Prototype implements the update() method such that any class that has a toString() method can be used as an argument to update(). I will show you exactly how to do this in the sixth article of "Eight Weeks of Prototype".

Reading the Content of an Element

In some situations you will want to read the content of an element rather than update it. This is achieved in Prototype by reading the innerHTML property of an element. This property is simply a HTML string representation of the content inside an element.

Listing 5 shows an example of reading the content of an element that exists in the original HTML source of a page, while Listing 6 shows an example of reading an element that has been dynamically created.

Listing 5 Reading the inner HTML content of an element (listing-5.html)
<html>
<head>
<title>Reading the inner HTML content of an element</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
<a href="http://www.example">Here is a link!</a>
</div>
<script type="text/javascript">
alert($('foo').innerHTML);
</script>
</body>
</html>

Reading and Writing Element Attributes

An attribute is a part of the element that appears in the opening tag of the element. An element can have any number of attributes, each of which consists of a name and a value. For example, in the HTML snippet <a href="http://www.example.com">My Link</a>, the tag has one attribute, which is called href and has a value of http://www.example.com.

Prototype provides an easy way to read these attributes, as well as allowing you write your own attributes to any element in real-time. We will now look at how to read and write attributes, as well as covering some practical examples of doing so that you may use in the future.

To retrieve the value of an element attribute, the readAttribute() method is called on that element. Listing 7 shows an example reading the target URL of a hyperlink. This example will show just the URL (http://www.example.com) in an alert box.

In the fifth article of "Eight Weeks of Prototype", I'll show you how this can be useful when creating Ajax scripts that are accessible for non-Ajax users.

Note: In this example I have also made use of the down() method covered in the first article of this series.
Listing 7 Reading a hyperlink's URL with readAttribute() (listing-7.html)
<html>
<head>
<title>Reading a hyperlink's URL with readAttribute()</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
<a href="http://www.example.com">This is a link</a>.
</div>
<script type="text/javascript">
var link = $('foo').down('a');
alert(link.readAttribute('href'));
</script>
</body>
</html>

To write new attributes (or to modify existing attributes), you can use the writeAttribute() method. This method takes two arguments, the first of which is the name of the attribute you want to write. The second argument is the new value of the attribute.

Listing 8 shows an example of retrieving a link, then updating its target URL and link text. When you click the link on this page you will be taken to www.phpriot.com, not www.example.com.

Listing 8 Using writeAttribute() to change the URL of a hyperlink (listing-8.html)
<html>
<head>
<title>Using writeAttribute() to change the URL of a hyperlink</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
<a href="http://www.example.com">This is a link</a>.
</div>
<script type="text/javascript">
var link = $('foo').down('a');
link.writeAttribute('href', 'http://www.phpriot.com');
link.update('Visit PhpRiot');
</script>
</body>
</html>

Being able to update an element's attributes is most useful when you want to use non-standard attributes.One such example is the target attribute, used on hyperlinks to force a link to open in a new window. If you use XHTML 1.0 Strict, the target attribute is not allowed. Therefore, by using writeAttribute(), you can add this attribute using JavaScript, thereby still allowing your HTML to validate. This is shown in Listing 9.

Note: Technically, the code below will not validate since the document type and encoding are not specified. I have done so in order to simplify the examples.
Listing 9 Changing a URL's target while not using non-standard attributes (listing-9.html)
<html>
<head>
<title>Changing a URL's target while not using non-standard attributes</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
<a href="http://www.example.com">This is a link</a>.
</div>
<script type="text/javascript">
var link = $('foo').down('a');
link.writeAttribute('target', '_blank');
</script>
</body>
</html>

Another example of using writeAttribute() is to disable the auto-completion feature used by some browsers to provide you with suggestions when filling out forms, based on what you've entered in the past. In some situations you will want to force the browser not to use auto-completion on a particular input.

One way to disable auto-completion is to use autocomplete="off" in your HTML source (that is <input type="text" name="some_name" autocomplete="off" />). The problem with this is that autocomplete is not a standard attribute. Hence, you can use writeAttribute() to disable auto-completion instead, as shown in Listing 10.

Listing 10 Disabling auto-completion by using writeAttribute() (listing-10.html)
<html>
<head>
<title>Disabling auto-completion by using writeAttribute()</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
<input type="text" name="q" />
</div>
<script type="text/javascript">
var input = $('foo').down('input');
input.writeAttribute('autocomplete', 'off');
</script>
</body>
</html>

Managing an Element's Classes in Real-Time

Prototype makes it easy to manage the classes that an element belongs to by providing three useful elements: addClassName(), removeClassName() and hasClassName(). If you were not using Prototype, you would manually have to deal with the className property on elements; however this is no longer necessary. These methods are especially useful when an element has (or can have) multiple classes.

One of the most frequent occurrences of having to manage class names is when handling hover events on elements. Although browsers that correctly implement CSS (such as Firefox) allow you to change the look of an element when you hover over (using the :hover selector), this is not possible in Internet Explorer (aside from hyperlinks).

Listing 11 shows an example of how CSS should work in all browsers (yet does not necessarily). This code will draw a red box, which will turn blue when the mouse hovers over it.

Listing 11 Using CSS to change the hover style of an element (listing-11.html)
<html>
<head>
<title>Using CSS to change the hover style of an element</title>
<style type="text/css">
#foo { background : #f00; color : #fff; }
#foo:hover { background : #00f; }
</style>
</head>
<body>
<div id="foo">
Highlight me!
</div>
</body>
</html>

To make this code work in browsers that don't support this CSS, we can instead use addClassName() and removeClassName(). Each of these methods takes one argument: the class name to add or remove.

Rather than defining a CSS called #foo:hover, I'll instead define one called #foo.hover. This means we can call addClassName('hover') on the #foo element.

Listing 12 shows how this is achieved. Note that in this code I've also used observe(), which is used to observe events in Prototype. Event handling will be covered in detail in the fourth article of this series. For now, all you need to know is that the first argument to observe() is the event name (without on at the beginning) and the second argument is the function to execute when the event is triggered. Additionally, calling this inside the handler function refers to the element on which the event occurred.

Listing 12 Using Prototype to change the hover style of an element (listing-12.html)
<html>
<head>
<title>Using Prototype to change the hover style of an element</title>
<script type="text/javascript" src="/js/prototype.js"></script>
<style type="text/css">
#foo { background : #f00; color : #fff; }
#foo.hover { background : #00f; }
</style>
</head>
<body>
<div id="foo">
Highlight me!
</div>
<script type="text/javascript">
var elt = $('foo');
elt.observe('mouseover', function(e) {
this.addClassName('hover');
});
elt.observe('mouseout', function(e) {
this.removeClassName('hover');
});
</script>
</body>
</html>

Using the hasClassName() method, you can check whether or not an element has a particular class. Listing 13 shows an example of using hasClassName(). It works by checking for the .hover class, then adding it, then checking for it again.

Listing 13 Checking whether an element has a particular class (listing-13.html)
<html>
<head>
<title>Using Prototype to check if an element has a class</title>
<script type="text/javascript" src="/js/prototype.js"></script>
<style type="text/css">
#foo { background : #f00; color : #fff; }
#foo.hover { background : #00f; }
</style>
</head>
<body>
<div id="foo">
Highlight me!
</div>
<script type="text/javascript">
var elt = $('foo');
if (elt.hasClassName('hover')) {
// does not reach this
}
elt.addClassName('hover');
if (elt.hasClassName('hover')) {
// does reach this
}
</script>
</body>
</html>

Managing an Element's Styles in Real-Time

As an alternative to changing an element's classes in real-time, you can also change an element's CSS styles. This is done using the setStyle() method. Similarly, you can retrieve an element's styles using getStyle().

Setting Styles with setStyle()

The setStyle() method is used to change the styles of an element. This method takes a single argument, which is an object of property-pair values. Listing 14 shows an example of how to define this object and apply the specified styles. In this example, the #foo div begins quite plain, then is changed to have a red background, bold text and some padding.

Listing 14 Setting an element's styles with setStyle() (listing-14.html)
<html>
<head>
<title>Setting an element's styles with setStyle()</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
Change this content
</div>
<script type="text/javascript">
var elt = $('foo');
var styles = {
size       : '18px',
fontWeight : 'bold',
background : '#f00',
padding    : '10px'
}
elt.setStyle(styles);
</script>
</body>
</html>
Note: Some CSS properties (such as float) are reserved words, and must therefore be quoted in the style hash. For example, you would use styles = { 'float' : 'left'; }.

Reading Styles with getStyle()

It is possible to read any element's style using getStyle(). This method takes the style property name as its only argument. You must be careful with the return value, since different browsers may behave slightly different with the value that is returned.

Prototype will handle the differences between internal style names and the corresponding CSS name. For example, you can use getStyle('fontSize') or getStyle('font-size').

Note: The same does not apply with setStyle() � You must use the internal name (such as fontSize, fontFamily or backgroundColor) to set the respective style.

Listing 15 shows an example of reading the font family that is being used on an element.

Listing 15 Reading an element's font family with getStyle() (listing-15.html)
<html>
<head>
<title>Reading an element's font family with getStyle()</title>
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="foo">
Change this content
</div>
<script type="text/javascript">
var elt = $('foo');
alert(elt.getStyle('font-family'));
// returns a value such as serif or Times New Roman
elt.setStyle({ 'fontFamily' : 'sans-serif' });
alert(elt.getStyle('font-family'));
// returns sans-serif
</script>
</body>
</html>

Retrieving an Element's Dimensions

Prototype provides methods for reading the dimensions of both the viewable browser window, as well as that of a visible element. This is done using the getDimensions(), getWidth() and getHeight() methods.

To read the dimensions of the viewable browser area, getDimensions() is called on the document.viewport object (that is, by calling document.viewport.getDimensions()). To read the dimensions of an element, you simply call getDimensions() on that element.

The getDimensions() method returns an object with two properties: width and height. These are both integers, corresponding to the number of pixels wide and high of the respective element.

Note: For this method to work correctly, you must specify the correct document type. As you can see in the listing below, I have specified a document type of XHTML 1.0 Strict.

In addition to getDimensions(), you can also call getWidth() and getHeight(), however, since each these methods in turn call getDimensions(), it is more efficient to call getDimensions() directly and read the width and height as needed.

Listing 16 shows an example of using the browser and an element's dimensions to centre that element both horizontally and vertically on a page.

Listing 16 Determining an element's size with getDimensions() (listing-16.html)
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<
					  					  
					  
 
 
Add a Comment:
 
(You must be signed in to comment on an article. Not a member? Click here to register)
   
Title:

Comments: