0

I'm trying to replicate jQuery's after() with JavaScript:

var orangeBlock = '<a href="http://clo2015.chineselearnonline.com/">Try out the New Version of CLO</a></div>'
var greyBlock = document.getElementsByClassName('grey-block')

function insertAfter(newNode, referenceNode) {
  console.log(referenceNode.parentNode)
  referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling)
}

insertAfter(orangeBlock, greyBlock)

But I'm getting the following error:

Uncaught TypeError: Cannot call method 'insertBefore' of undefined theme.js:62 insertAfter theme.js:62 (anonymous function)

I find it strange, since console.log(greyBlock) outputs the item:

[item: function]
0: div.grey-block
length: 1
__proto__: NodeList

Live site: http://www.chineselearnonline.com/amember/member.php

alexchenco
  • 47,739
  • 69
  • 219
  • 389

2 Answers2

1

orangeBlock is a string. You need a DOM node to use insertBefore. You can convert it like below.

var orange = document.createElement('div');
orange.innerHTML = orangeBlock;

document.getElementsByClassName get list of nodes. So you need to select one out of them greyBlock[0]

Something like this finally.

var orangeBlock = '<a href="http://clo2015.chineselearnonline.com/">Try out the New Version of CLO</a>';
var orange = document.createElement('div');
orange.innerHTML = orangeBlock;

var greyBlock = document.getElementsByClassName('grey-block');

function insertAfter(newNode, referenceNode) {
  referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

insertAfter(orange, greyBlock[0]);
Dhiraj
  • 31,130
  • 7
  • 57
  • 77
  • Weird, I'm still getting: `Uncaught TypeError: Cannot read property 'parentNode' of undefined` http://www.chineselearnonline.com/amember/member.php – alexchenco Apr 03 '15 at 02:52
  • @alexchenco: I ran it from the console and it seems to be working. Place your `theme.js` before the body ends. Looks like the code is being executed before the dom element is even created. – Dhiraj Apr 03 '15 at 02:56
  • 1
    You're right. Wrapping everything with `window.onload = function()` made it work. Thanks. – alexchenco Apr 03 '15 at 03:02
1

Well, your insertAfter function does expect DOM nodes! Neither orangeBlock (a string) nor greyBlock (a Nodelist) are nodes.

So rather do something like

// create an element using DOM methods
var orangeBlock = document.createElement("a");
orangeBlock.href="http://clo2015.chineselearnonline.com/";
orangeBlock.appendChild(document.createTextNode("Try out the New Version of CLO"));
 // access the first element in the node list
var greyBlock = document.getElementsByClassName('grey-block')[0];

function insertAfter(newNode, referenceNode) {
  console.log(referenceNode.parentNode)
  referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling)
}
if (greyBlock)
    insertAfter(orangeBlock, greyBlock)
else
    alert("could not find an element with the class 'grey-block'");

But actually, you'll want to use the insertAdjacentHTML method:

 document.getElementsByClassName('grey-block')[0].insertAdjacentHTML('afterend', '<a href="http://clo2015.chineselearnonline.com/">Try out the New Version of CLO</a>')
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • Ha, I'm not sure why I'm always getting `undefined`: `Uncaught TypeError: Cannot call method 'insertAdjacentHTML' of undefined` http://www.chineselearnonline.com/amember/member.php – alexchenco Apr 03 '15 at 02:56
  • @alexchenco: Yes, probably [because the element doesn't exists yet](http://stackoverflow.com/q/14028959/1048572) – Bergi Apr 03 '15 at 02:58
  • So how can I solve that? It does get the element with `document.getElementsByClassName('grey-block')` But gets a `NodeList`. – alexchenco Apr 03 '15 at 02:58
  • @alexchenco: It's mentioned there in the first answer of the linked question. Go read it. – Bergi Apr 03 '15 at 02:59