ninjascorner
ninjascorner

Reputation: 299

How to create an element and move an existing element into it in native Javascript?

My goal is to create an element to serve as a placeholder of an existing element. For styling purposes I need to move the element right after another element (position: absolute is not a good solution) so I can set the position dynamic.

My problem is the markup is generated by javascript and the only option I have is to tweak it via javascript also. It is a third party widget that I need to override.

Current markup:

<li class="...">

  <a class="time" href="...." >
    <time pubdate="" class="...">...</time>
  </a>

  <div class="...">
    ...
  </div>

  <div class="...">
    ...
  </div>

  <div class="bottom-wrapper">
    <span class="stats-container">
      <span class="stats">
        <span class="likes">    
          ...
        </span>
        <span class="favorites">   
          ...
        </span>
      </span>
    </span>
  </div>

I want to move the a.time into a new span after span.likes.

Goal:

<li class="...">

  <div class="...">
    ...
  </div>

  <div class="...">
    ...
  </div>

  <div class="bottom-wrapper">
    <span class="stats-container">
      <span class="stats">
        <span class="likes">    
          ...
        </span>
        <span class="new-span">
          <a class="time" href="...." >
            <time pubdate="" class="...">...</time>
          </a>
        </span>
        <span class="favorites">   
          ...
        </span>
      </span>
    </span>
  </div>
</li>

I need to do it in native javascript (No Jquery) for some reason.

My code:

// Create a new, plain <span> element
var createElem = document.createElement('span');

// Get a reference to the element, before we want to insert the element
var containerElem = document.getElementsByClassName("likes");

// Get a reference to the parent element
var parentDiv = containerElem.parentNode;

// Insert the new element into the DOM after containerElem
parentDiv.insertBefore(createElem, containerElem.nextSibling);

However, the above code throw an error (please see below):

Uncaught TypeError: Cannot call method 'insertBefore' of null 
Uncaught TypeError: Cannot call method 'insertBefore' of undefined 

Any idea how I can do this? Thanks

EDIT: I have multiple LI as well. So I need to traverse all the LI in this script.

Upvotes: 0

Views: 275

Answers (2)

Sushant Sudarshan
Sushant Sudarshan

Reputation: 410

  1. getElementsByClassName is not a safe cross-browser DOM method. It will not work in IE 8 and below. If you need cross-browser support then using a getElementsByTagName('span') and checking the .className property would be a better option. Or better yet, just give the span an id and use getElementById (but I'm sure that thought must have occurred to you already).

  2. Also, as @salexch rightly pointed out, if a DOM method returns a group of elements (HTMLCollection) as getElementsByClassName and getElementsByTagName do, then you must use indices (containerElem[0]) to access the individual elements within the collections.

"I tried your correction above but I get this error Uncaught TypeError: Cannot read property 'parentNode' of undefined"

This means the collection returned by your DOM method is empty. Are you sure that the span with class "likes" exists in the DOM at the time getElementsByClassName is called?

The rest looks fine. Hope you find your solution soon.

Upvotes: 1

salexch
salexch

Reputation: 2704

containerElem is an array :

var parentDiv = containerElem[0].parentNode;

Upvotes: 4

Related Questions