Click to See Complete Forum and Search --> : Javascript error when trying to use "removeChild"
mcskiver
04-21-2006, 11:01 AM
Hi, i'm trying to use removeChild to remove a list item from an un-ordered list, and i'm getting the following error on the line where I actually perform the removeChild:
Error: uncaught exception: [Exception... "Could not convert JavaScript argument arg 0 [nsIDOMHTMLUListElement.removeChild]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: file:///V:/prototype/20_04_06_Drag_Drop_Left_And_Right_Dev.htm# :: updateLists :: line 89" data: no]
Here's the offending section of code, though i'm not posting the entire function as it's pretty big. Basically "remove" is an array of id's that I want to remove from the document. The id's themselves are directly on the list items.
for (i=0; i<remove.length; i++) {
stringOfID = 'li' + remove[i]
fromList.removeChild(stringOfID)
}
Any ideas on how I can get past this hurdle would be much appreciated. I'm stumped...
Orc Scorcher
04-21-2006, 11:15 AM
The argument for removeChild must be a Node, not an id: fromList.removeChild(document.getElementById(stringOfID))
mcskiver
04-24-2006, 04:01 AM
Cheers. Still learning the ropes with this stuff...
mcskiver
04-24-2006, 04:27 AM
Hi, I still can't get this thing to work... I'm still getting the same error, but here's my updated code:
node = requiredInputs[i].nodeName
chucked = fromList.removeChild(node.parentNode)
Now, as I understand it, I need to use the nodeName property, and then obviously use removeChild on the parent node. So where am I going wrong? chucked is equal to my unordered list, and the node variable is an input field. I want to remove the input and it's parent li....
Orc Scorcher
04-24-2006, 06:33 AM
nodeName is a string again. Assuming that requiredInputs[i] is actually a reference to an input element this should do what you want:var listItem = requiredInputs[i].parentNode
if (listItem && listItem.parentNode) listItem.parentNode.removeChild(listItem)
mcskiver
04-24-2006, 07:27 AM
Thanks for helping out again, but it still isn't working. This is how i'm setting the list to use, and the requiredInputs array:
fromList = document.getElementById(removeFrom)
requiredInputs = fromList.getElementsByTagName('input')
I'm definitely getting hold of my fromList variable, because the other features are working. Is there something wrong with the way i'm setting requiredInputs?
Orc Scorcher
04-24-2006, 08:07 AM
That line looks ok but without seeing the complete code it's just impossible to tell where the problem is. Is the page online?
mcskiver
04-24-2006, 08:09 AM
Hi, thanks for your patience!
It's not on-line, so here's my full function. I pull in two parameters. One is the ID of the list i'm removing options from, and the other is the ID of the list i'm passing the values into :
function updateLists(removeFrom,addTo) {
// <![CDATA[
var requiredInputs = new Array()
var remove = new Array()
// fromList var is the list we're taking options away from
fromList = document.getElementById(removeFrom)
// toList var is the list we're appending options to
toList = document.getElementById(addTo)
// requiredInputs picks up all the input elements within the first list. i.e. all the checkboxes.
if (fromList) {
requiredInputs = fromList.getElementsByTagName('input')
}
if (requiredInputs.length > -1) {
for(i=0; i < requiredInputs.length; i++) {
// Need to find a DOM-based way of performing the following line of code...
isChecked = requiredInputs[i].checked;
listText = requiredInputs[i].getAttribute('value')
listItem = requiredInputs[i].parentNode
if (isChecked == true) {
// Append new list items to toList using the elements of the requiredInputs array
newListItem = document.createElement('li')
newListItemSpan = document.createElement('span')
newListItemText = document.createTextNode(listText)
newInput = document.createElement('input')
newListItem.setAttribute('id',listText)
newListItem.setAttribute('style','position:relative')
newInput.setAttribute('type','checkbox')
newInput.setAttribute('value',listText)
newInput.setAttribute('name','checkBoxItem')
newListItemSpan.setAttribute('class','handler')
// Now append the new checkbox to the list item we've just created, and then append
// the list item itself to the toList var, which is an unordered list.
newListItem.appendChild(newInput)
newListItemSpan.appendChild(newListItemText)
newListItem.appendChild(newListItemSpan)
toList.appendChild(newListItem)
// Now we need to remove the list item from the fromList, as it's just been added
// to the toList.
// fromList.removeChild(listItem)
var listItem = requiredInputs[i].parentNode
if (listItem && listItem.parentNode) listItem.parentNode.removeChild(listItem)
// -------------------------------------------------------------------------------------------
}
}
}
// Now need to instantiate the sortable, draggable and droppable objects from Scriptaculous.
// If we don't do this here then we'll find that list items moved between lists via the
// multi-select method won't be draggable afterwards. Lee McIvor - 21st April 2006
Sortable.create("firstlist",
{dropOnEmpty:true,containment:["firstlist","secondlist"],constraint:false});
Sortable.create("secondlist",
{dropOnEmpty:true,handle:'handle',containment:["firstlist","secondlist"],constraint:false});
// Now make an AJAX call to ensure that updates to the lists are saved to the back-end.....
// ]]>
}
mcskiver
04-24-2006, 08:14 AM
What I have happening now is that if I select multiple elements with the checkboxes in a list, some of those selected aren't transferred to the other list. If I select two items, one is transferred. If I select three, then two are transferred... No errors though.
It looks to me like it must be because the length property of my requiredInputs array is getting recalculated each time I drag items across, but i've no idea how to actually fix that....
Orc Scorcher
04-24-2006, 08:29 AM
Next time, please use code tags, thanks. Ok, the problem here is that the result of getElementsByTagName is dynamic: as soon as you remove one input the list is automatically updated. When you remove the first item in the list, all other elements in the list will shift one position up.
Suggested modifications:
Drop this if clause, it's not necessary:
if (requiredInputs.length > -1) {
and replace this loop
for(i=0; i < requiredInputs.length; i++) {
with
while (requiredInputs.length > 0)
Then replace all instances of
requiredInputs[i]
with
requiredInputs[0]
mcskiver
04-24-2006, 08:36 AM
Sorry about that. I tried the above but now the script actually times out in Firefox.
It seems to me now that if the first checkbox isn't checked, then we're in an infinite loop surely? Only when it finds a checkbox that's checked will it enter the second loop and update the length property.
Orc Scorcher
04-24-2006, 08:44 AM
Oh yeah, you're right, sorry about that. Keep the old for loop and requiredInputs[i] but add i-- after the removeChild call. As an alternative, copy the result of getElementsByTagName into a normal JavaScript array, they are static and easier to predict.
mcskiver
04-24-2006, 08:51 AM
Perfect! Works like a dream.
I really appreciate your patience and help with this. It'd have gone nowhere if i'd had to work through it myself. Many thanks again!