0
votes

I'm trying to create a new div in Javascript with two spans in it, each containing a string of text. They are then meant to be inserted before div.two in div.inner.

The div I'm trying to insert it into only has a class and I cannot target it by any ID, unfortunately.

I have also created a codepen here: https://codepen.io/lisaschumann/pen/BXqJKY

Any help is massively appreciated!

HTML

<html>
  <div class="inner">
    <div class="one"></div>
    <div class="two"></div>
  </div>
</html>

JS

window.onload=function(){
  var infobox = document.createElement("div");
  infobox.classList.add('infobox');

  var spanOne = document.createElement("div");
  var spanOneText = document.createTextNode('Important text 1');

  var spanTwo = document.createElement("div");
  var spanTwoText = document.createTextNode('Important text 2');

  spanOne.appendChild(spanOneText);
  spanTwo.appendChild(spanTwoText);
  infobox.appendChild(spanOne);
  infobox.appendChild(spanTwo);

  var targetDiv = document.getElementsByClassName("inner");
  targetDiv.insertBefore(infobox, targetDiv.childNodes[1]);
}

Errors:

Cannot read property '1' of undefined at window.onload

4
Why not debug your code, step through it and see, which method calls actually return null?Uwe Keim
document.getElementsByClassName("inner") will return a HTMLCollection, not a single element. Try using document.getElementsByClassName("inner")[0] or document.querySelector("inner").Sid Vishnoi

4 Answers

2
votes

The main issue is that getElementsByClassName returns a live collection of nodes rather than one node and so you would need to access the correct node in that list similar to an array: targetDiv[0], perhaps.

The easier method is to use querySelector to grab the element you want using its class, for example:

var parent = document.querySelector(".inner");
var two = document.querySelector(".two");
parent.insertBefore(infobox, two);

But! there's even a shortcut method you can use here that allows you to add an HTML string direct to the DOM which might save you a bit of time, and some code.

// Create the HTML
const html = `
  <div>
    <span>Text alpha</span>
    <span>Text beta</span>
  </div>`;

// Grab the element containing your "two" class
const two = document.querySelector('.inner .two');

// Using insertAdjacentHTML to add the HTML before the two element
two.insertAdjacentHTML('beforebegin', html);
<div class="inner">Inner
  <div class="one">one</div>
  <div class="two">two</div>
</div>
0
votes

This doesn't work because of these lines

var targetDiv = document.getElementsByClassName("inner");
targetDiv.insertBefore(infobox, targetDiv.childNodes[1]);

document.getElementsByClassName returns a NodeList. targetDiv.childNodes is undefined, because childNodes doesn't exist on a NodeList.

You need to either use a list operation like Array.prototype.forEach, change getElementsByClassName to getElementByClassName (note the s) or access the first node in the node list using the array indexer syntax.

I assume you meant to do something like this:

var targetDiv = document.getElementByClassName('inner')
targetDiv.insertBefore(infobox, targetDiv.childNodes[1])

This will insert a node in between the first and second child of the first DOM node with the class inner.

0
votes

Try this out , targetDiv is an array by default due to the getElementsByClassName method , even though it has a single element.Hence you need to specify the index i.e. 0 ( as it's the first element of the array)

var targetDiv = document.getElementsByClassName("inner")[0]; targetDiv.insertBefore(infobox, targetDiv.children[1]); }

-2
votes

Using JQuery

$(document).ready(function(){
    $(`<div>Important text 1<span></span>Important text 2<span></span></div>`).insertBefore( ".inner .two" );
)

I would encourage you to use JQuery and then shift to vanilla javascript later on. You can do simple tasks like this in just few lines of code and it is also easily debuggable because of that