SitePoint Sponsor

User Tag List

Results 1 to 3 of 3
  1. #1
    SitePoint Zealot
    Join Date
    Aug 2002
    Posts
    168
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    object.removeChild() - Unexpected results??

    Hi

    I have a form that is being generated using AJAX. It has any given number of checkboxes as possible selections. The point of the script is to submit selected checkboxes, then display them as checked where relevant. Here's an example...

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    <title>Dynamic Checkbox</title>
     
    <script type="text/javascript">
    var aOptions = Array(123, 223, 323, 423, 523, 623, 723, 832, 932);
    var aSelected = new Array;
    <?php
     
    if (count($_POST) == 0)
    {
    $aSelected = array(323, 523, 723);
    for ($i = 0; $i < count($aSelected); $i++)
    {
    echo "aSelected[". $aSelected[$i] ."] = ". $i .";\n";
    }
    }
    else
    {
    foreach ($_POST['selected_checkbox'] as $var => $val)
    {
    echo "aSelected[". $val ."] = ". $val .";\n";
    }
    }
    ?>
     
    var oInputClone;
     
    function init()
    {
    oInputClone = document.getElementById('inputClone');
    var oTable = document.getElementById('optionsTable');
     
    for (var i = 0; i < aOptions.length; i++)
    {
    	var oRow = oTable.insertRow(-1);
    	var oCell_01 = oRow.insertCell(0);
     
    	if (aSelected[aOptions[i]] >= 0)
    	{
    	 oCell_01.innerHTML = '<input type="checkbox" value="'+ aOptions[i] +'" onclick="toggleFormValues(this, '+ aOptions[i] +')" checked>';
     
    	 addInputElement(aOptions[i]);
    	}
    	else oCell_01.innerHTML = '<input type="checkbox" value="'+ aOptions[i] +'" onclick="toggleFormValues(this, '+ aOptions[i] +')">';
     
    	var oCell_02 = oRow.insertCell(1);
    	oCell_02.setAttribute('width', '100%');
    	oCell_02.innerHTML = aOptions[i];
    }
    }
    function toggleFormValues(oCheckbox, iOptionId)
    {
    if (oCheckbox)
    {
    	if (oCheckbox.checked == true)
    	{
    	 addInputElement(iOptionId);
    	}
    	else
    	{
    	 removeInputElement(iOptionId);
    	}
    }
    }
    function addInputElement(iOptionId)
    {
    // Create Input Element 
    oAddedElement = oInputClone.cloneNode(false);
    oAddedElement.name = 'selected_checkbox['+ iOptionId +']';
    oAddedElement.id = 'selected_checkbox['+ iOptionId +']';
    oAddedElement.value = iOptionId;
    oInputClone.parentNode.insertBefore(oAddedElement, oInputClone);
    }
    function removeInputElement(iOptionId)
    {
    // Remove Input Element 
    oElementToRemove = document.getElementById('selected_checkbox['+ iOptionId +']');
    oElementToRemove.parentNode.removeChild(oElementToRemove);
    }
    function removeAll()
    {
    // Uncheck all the checkbo elements
    var oForm = document.getElementById('myForm');
     
    for (var i = 0; i < oForm.length; i++)
    {
    	if (oForm.elements[i].type == 'checkbox')
    	{
    	 oForm.elements[i].checked = false;
    	}
    }
     
    // Remove all checkbox values
    var oSelectedValues = document.getElementById('selectedValues');
    var children = oSelectedValues.childNodes;
     
    for (var i = 0; i < children.length; i++)
    {
    	if (children[i].id != 'inputClone')
    	{
    	 oSelectedValues.removeChild(children[i]);
    	}
    }
    }
    </script>
    </head>
    <body onload="init()">
    <?php
     
    if (count($_POST) != 0)
    {
    echo '<pre>';
    print_r($_POST);
    echo '</pre>';
    }
    ?>
    <form id="myForm" method="post" action="">
    <div id="selectedValues">
    <input type="hidden" name="inputClone" id="inputClone" value="null">
    </div>
    <table id="optionsTable" cellspacing="1" cellpadding="2" border="1" width="75%" align="center">
    </table>
    <table icellspacing="1" cellpadding="2" border="1" width="75%" align="center">
    <tr>
    <td><a href="javascript:removeAll()">Remove Checked</a></td>
    <td align="right"><input type="submit" name="submit" value="Submit"></td>
    </tr>
    </table>
    </form>
    </body>
    </html>
    1. The array (aOptions) here is some values to build up the list of checkboxes, it actually comes from server side generated XML.

    2. The PHP array prints a list of selected items in the javascript.

    3. The init() function is called onload, to populate the table with checkboxes. Depending if the form has been submitted or not, this will mark a checkbox as checked or not.

    4. The next two functions add/remove input elements to the form with the value of the checked/unchecked checkbox. This, of course, is necessary because the elements don't actually exist in the form without doing this.

    5. The removeAll() function should come through and uncheck all checkboxes and remove all input elements for the checkboxes.

    PROBLEM - This script does not behave as expected. If you click "Remove Checked" then submit the form you'll see that it doesn't actually remove all elements. It leaves every second checked element behind??

    Have I missed something really stupid? Does it do it for you? If so, how do you fix it? I've checked it in IE and FF only.

    Thanks!
    Last edited by grahowler; Nov 4, 2006 at 00:54.

  2. #2
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It sounds like this is happening:
    - loop through child nodes
    - remove child[i]

    So, first we remove child[0], and then child[1] and so on. The problem is that when we remove child[0], child[1] is the new child[0].

    2 ways around this
    - loop through the children backwards, removing say child[9] then child[8] etc
    - keep removing child[0] until there are no more children.

  3. #3
    SitePoint Zealot
    Join Date
    Aug 2002
    Posts
    168
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    jimfraser, thanks...

    Sometimes the most obvious things allude us, you're right.

    I tried both these methods and could only get the loop through backwards method to work. I think this must be because children.length constantly changes as you remove elements, but by looping backwards the next element to remove is always still there.

    Anyway, problem solved, appreciate your input.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •