cloneNode() - Cloning Existing Form Objects
- Assigning unique names
for IE5.5+, N7+, and Mozilla 1.1
There are 2 critical aspects to assigning unique names:
1 - the ability of the browser to recognise the new names
2 - the ability of the browser to add the new elements to the form array
Unless the browser can do both of these things, cloning cannot be used with forms.
Text inputs
Let's start with the simplest problem - cloning text inputs and giving them unique names. In the example below, there are three text inputs named LAST_NAME_0, FIRST_NAME_0, and NICKNAME_0. The function addRow() clones the row of inputs, renames them by incrementing the number at the end of each field name, sets the values to the new names, and adds the row to the table.
<script> nameNum = 1; // -- This is the number for the new row names. We start with 1 because we already have row 0 function addRow(){ // -- get the table id="test1" var t = document.getElementById('test1'); // - get the first tbody tag belonging to var t (this is where our inputs are ) var tb = t.getElementsByTagName('tbody')[0]; var tr0 = tb.childNodes[0]; var myClone = tr0.cloneNode(true); // -- get the number of inputs contained in the cloned row var newInpt = myClone.getElementsByTagName('input'); // -- for Mac IE 5, the appendChild statement must be here instead of // -- the end of the function or the row won't be added // -- tb.appendChild(myClone) for (i=0; i < newInpt.length; i++){ // -- get only the non-numeric part of the name using a regular expression; // -- concatinate it with nameNum to create the new name var newName = newInpt[i].name.substring(0,newInpt[i].name.search(/\d/)) + inNo; newInpt[i].setAttribute('name',newName); newInpt[i].setAttribute('value',newName); } nameNum++; tb.appendChild(myClone); } </script>
| WIN | MAC | ||||||
| TEST | Mozilla 1.1 | N7 | N6 | IE5.5+ | Opera 6.05 | N6 | IE5+ |
| function addRow() | Y | Y | Y | Y | N | Y | B |
| Test 1 | Y | Y | N | Y | n/a | N | B |
| Test 2 | Y | Y | N | Y | n/a | N | N |
| Test 3 | Y | Y | Y | Y | n/a | Y | Y |
| Test 4 | Y | Y | Y | N | n/a | Y | N |
| Test 5 | Y | Y | N | Y | n/a | N | N |
| B = buggy | |||||||
As you can see, even with this basic example, we're already running into problems.
Opera 6 is out of the game.
Mac IE 5 behaves so strangely it should probably be disqualified. The appendChild won't work unless it comes before the loop. Even then, every time you append the new row, the table keeps getting mysteriously wider. And unlike the Win version, Test 5 doesn't work.
N6 can't recognise the new objects as part of the forms[i].elements array and
fails to add them to the request string on submit. Oddly, N6 passes Test 4 which uses document.formName.elementName.select().
IE 5.5+, which passes Test 2, fails Test 4. (!???!) Go figure.
All form objects
Using function addRow() as a starting point, we'll create a new function that can handle all form objects. The new function will be addRow2().
<script> nameNum = 1; function addRow2(){ var t = document.getElementById('test2'); var tb = t.getElementsByTagName('tbody')[0]; var tr0 = tb.childNodes[0]; var myClone = tr0.cloneNode(true); var newInpt = myClone.getElementsByTagName('input'); var newSel = newRow.getElementsByTagName('select'); var newTa = newRow.getElementsByTagName('textarea'); // -- for Mac IE 5, the appendChild statement must be here instead of // -- the end of the function or the row won't be added // -- tb.appendChild(myClone) for (i=0; i < newInpt.length; i++){ var newName = newInpt[i].name.substring(0,newInpt[i].name.search(/\d/)) + nameNum; newInpt[i].setAttribute('name',newName); } for (i=0; i<newTa.length; i++){ var newName = newTa[i].name.substring(0,newTa[i].name.search(/\d/)) + nameNum; newTa[i].setAttribute('name',newName); } for (i=0; i<newSel.length; i++){ var newName = newSel[i].name.substring(0,newSel[i].name.search(/\d/)) + nameNum; newSel[i].setAttribute('name',newName); } nameNum++; tb.appendChild(myClone); } </script>
| WIN | MAC | ||||||
| TEST | Mozilla 1.1 | N7 | N6 | IE5.5+ | Opera 6.05 | N6 | IE5+ |
| function addRow() | Y | Y | B | Y | N | B | B |
| Test 1 | Y | Y | N | Y | n/a | N | N |
| Test 2 | Y | Y | N | Y | n/a | N | N |
| Test 3 | Y | Y | Y | Y | n/a | Y | Y |
| Test 4 | Y | Y | Y | Y | n/a | Y | Y |
| Test 5 | Y | Y | Y | Y | n/a | Y | Y |
| Test 6 | Y | Y | B | N | n/a | B | N |
| Test 7 | Y | Y | N | Y | n/a | N | N |
| Radio Buttons function properly | Y | Y | N | N | n/a | N | N |
| Checkboxes function properly | Y | Y | N | Y | n/a | N | N |
| B = buggy | |||||||
There's a lot of buggy behavior when it comes to cloned radios and checkboxes.
Bugs:| Netscape 6 - | Test 6 works for all elements except radios and checkboxes. Cloned radios and checkboxes cannot be checked. Also, N6 clearly has a problem cloning buttons. We'll see more of this in "Retaining Values and Object States". |
| Win IE 5.5+ - | You can only check one radio button out of all original and cloned radios. The browser treats them as if they all have the same name, although the other tests indicate otherwise. |
| Mac IE 5.5+ - | Boy is this buggy - and how! Cloned radios, checkboxes, textareas, and buttons display as text inputs even though Tests 3-5 show it recognizes them. Also, same problems as indicated in the first example. Due to these problems, this tutorial will do no further testing with Mac IE5. |
| Interesting Note - | In Test 2, N7 and Mozilla list functionButton before the cloned elements, not as the last item as you would expect. |
PXL8 2003