Problem with DOM Scripting

Guys, I’m having issue with DOM scripting and need some help. Here’s what i have:


...

<body>
   <div id="part1">
      ...
   </div>

   <!--  
      I want to insert another div tag here, right underneath the above div tag
      using DOM scripting.  What is the way ?  Thanks.
   -->
</body>

Have a read of https://developer.mozilla.org/en/DOM/element.insertBefore as it explains the .insertBefore() method and how to use the .nextSibling() method along side it to achieve an emulated .insertAfter() method.

Writing the insertAfter function

Although the DOM hasn’t provided a method called insertAfter, it does have all the tools you need to
insert a node after another node. You can use existing DOM methods and properties to create a function
called insertAfter:


function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement) {
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling);
}
}


This function is using quite a few DOM methods and properties:

• parentNode property
• lastChild property
• appendChild method
• insertBefore method
• nextSibling property

This is what the function is doing, step by step:

  1. The function takes two arguments: the new element and the target element the
    new element should be inserted after. These are passed as the variables
    newElement and targetElement:

function insertAfter(newElement,targetElement)

  1. Get the parentNode property of the target element and assign it to the variable
    parent:

var parent = targetElement.parentNode

  1. Find out if the target element happens to be the last child of parent. Compare
    the lastChild property of parent with the target element:

if (parent.lastChild == targetElement)

  1. If this is true, then append the new element to parent using appendChild. The
    new element will be inserted directly after the target element:

parent.appendChild(newElement)

  1. Otherwise, the new element needs to be inserted between the target element and the next child of parent.
    The next node after the target element is the nextSibling property of the target element.
    Use the insertBefore method to place the new element before the target element’s next sibling:

parent.insertBefore(newElement.targetElement.nextSibling)

There is no need to write an insertAfter function.

Why? The nextSibling property returns null if there is no next sibling.
When the insertBefore has null as the referenc element, it automatically appends instead.

For confirmation, this is what the insertBefore documentation page has to say:

[indent]Syntax
var insertedElement = parentElement.insertBefore(newElement, referenceElement);

If referenceElement is null, newElement is inserted at the end of the list of child nodes.[/indent]

So, the following is the only code that you need to properly insert after an element, regardless of whether that element has any siblings after it or not.


targetElement.parentNode.insertBefore(newElement, targetElement.nextSibling);

Wow I never new that, that’s really cool… Learnt something new, thanks :slight_smile:

[RIGHT].[/RIGHT]

Hi Paul, just a point that you mentioned below that the condition for inserting after is if the reference element is evaluated to null

But then after that you mentioned : regardless of whether that element has any siblings after it

Is not the second statement in red, different from the first because if targetElement.nextSibling has another sibling and therefore returns something other than null, it’s not going to append !

  • thanking in advance.

[RIGHT].[/RIGHT]

There are two possible situations that can occur here.

  1. the target element has a next sibling
  2. the target element doesn’t have a next sibling

Case 1 - when the target element has a next sibling, the parent element has the new element inserted before the targets next sibling. That is just after the target element, which is what we expect when inserting after the target element.

Case 2 - when the target element doesn’t have a next sibling, the parent element instead receives null as the reference. In this situation the parent element inserts the new element to the end of its list of child nodes. Before the last child node was our target element, and afterwards the last child node is that new element. Once again, the new element is inserted after the target element.

So in both cases, the new element is inserted after the target element.

Hi Paul - I just realized where I made the mistake, for some reason I was still in the ‘targetElement’ mode instead of ‘targetElement.nextSibling’, but thank you very much for taking the time out to point that out to me :blush: