| home / programming / professional / chap6/ 2 | [previous] [next] |
|
|
The reason for accessing a certain element is usually that you want to change, move, clone, or delete the element. The following example script allows the user to add sets of form fields in a CD review form, or to delete them.

Initially there's only enough room for reviewing one CD…

…but when the user clicks the 'Give me more fields!' button, a new set of form fields appears. Attached to the button is a script that copies a template of the set of form fields and adds this copy to the document. The browser immediately reacts by showing it. When the 'Remove review' button is clicked, a script similarly removes the set of form fields from the document.
First of all, let's take a look at the HTML. The form itself is plain and simple. However, there are two extra elements in it.
The set of fields that will contain one CD review is placed in a <div> with id attribute "readroot". This <div> is hidden from view by the display:none CSS declaration. This is our template and it should retain its default values – the user is only allowed to enter data in the clones of this template.
There is one empty <span> near the end of the form. This is a marker: the script will add the new form fields just above this span.
<div id="readroot" style="display:
none">
<p class="hr"> </p>
<input type="button" value="Remove review" style="font-size:
10px"
onClick="this.parentNode.parentNode.removeChild(this.parentNode);"
/>
<br /><br />
<input name="cd_1" value="title" />
<select name="rankingsel_1">
<option>Rating</option>
<option value="excellent">Excellent</option>
<option value="good">Good</option>
<option value="ok">OK</option>
<option value="poor">Poor</option>
<option value="bad">Bad</option>
</select>
<br /><br />
<textarea name="review_1">Short review</textarea>
</div>
<form action="storereviews.pl">
<span id="writeroot"></span>
<input type="button" value="Give me more fields!"
onClick="moreFields()" />
<input type="button" value="Send form" onClick="alert('Fake
submit')" />
</form>
Now for the actual script. We first set a variable counter, which will count the number of clones made. After all, each form field should have a unique name. By appending the value of counter to the default names of the fields, we make sure that each name is unique.
var counter = 0;
Next we have the function that clones the set of form fields and adds the clone to the document. It first checks whether the W3C DOM is supported by seeing if the browser understands getElementById() and insertBefore(). If it doesn't, it ends the function by a return. If it does, then we make a new set of the form fields, so we increase counter by one.
function moreFields()
{
if (!document.getElementById && !document.insertBefore)
{
return;
}
counter++;
We take the element with id attribute "readroot" and clone it using the cloneNode() method. We reset its id value (an id should be unique, after all) and set its display style to block so that it will be visible.
var newFields = document.getElementById('readroot').cloneNode(true);
newFields.id = 'clone' + counter;
newFields.style.display = 'block';
Having cloned the set of form fields, we now make sure that each field has a unique name. We go through all children of the cloned <div>. Every form field has a name, so we see if the current child node has a name attribute. If it has, we remove the last character of its name (the number) and add the current value of counter. Now the form field has a unique name.
var newField = newFields.childNodes;
for (var i=0;i<newField.length;i++)
{
var theName = newField[i].name
if (theName)
{
newField[i].name = theName.substring(0,theName.length-1)
+ counter;
}
}
The set of form fields is now ready to be inserted. We insert it just before the <span> with id attribute "writeroot".
var insertHere = document.getElementById('writeroot');
insertHere.parentNode.insertBefore(newFields,insertHere);
}
In the final part of the script, we call this function once the page has loaded, so that the user will initially see one set of form fields.
window.onload = moreFields;
Remember from the HTML that each set of form fields has its own " Remove review" button:
<input type="button" value="Remove
review" style="font-size: 10px"
onClick="this.parentNode.parentNode.removeChild(this.parentNode);"
/>
When it is clicked, the button's parent node (the <div>) is removed from its own parent node (the <form>). Thus the review disappears completely from the document and cannot be retrieved.
As a summary, here are the W3C DOM methods that help to add and remove nodes:
| Method |
Description |
Example |
| appendChild() |
Append a node to another node as its last child node. If the element is already in the document, it is removed from its previous position. Use insertBefore() to append a node in another position than as the last child. |
x.appendChild(y): |
| cloneNode() |
Clone a node. If an argument of true is passed, its descendants are also cloned. If an argument of false is given, no descendent nodes are cloned. |
var
x = y.cloneNode(true): |
| createElement() |
Create a new element. |
var
x = |
| createTextNode() |
Create a new text node. |
var
x = |
| insertBefore() |
Insert a node into the document tree as a child node, before the existing child node specified. |
x.insertBefore(y,z): |
| removeChild() |
Remove a child node from the node tree. |
x.removeChild(y): |
| replaceChild() |
Replace a child node with another node. |
x.replaceChild(y,z): |
| setAttribute() |
Set the value of an attribute. There are several serious browser-compatibility problems with this method, so don't use it unless there is no other way to set an attribute. In the next table you'll find code to set the most common attributes of an element (id, class, and title). |
x.setAttribute('align','right'): |
| home / programming / professional / chap6/ 2 | [previous] [next] |
Created: March 11, 2003
Revised: March 28, 2003
URL: http://webreference.com/programming/professional/chap6/2