0

I browsed the other answers but couldn't find a solution for this problem.

I have this HTML:

<body>
  <h1>Javascript in the Browser</h1>
  <div id="removeReference">
  </div>
  <div>
    <p>This page looks a little sad without any style...</p>
    <button id="styleButton">Apply some style!</button>
  </div>
  <div id="imagePlaceholder">
  </div>
<script src="script.js"></script>
</body>

In the JavaScript file, I have a function stylePage that is triggered by clicking a button and it adds some style, removes the button itself, and creates a new button. At this point, I'd like to add an event to this dynamically created new button so that when clicked the function createImage is triggered.

I know it's be better to use libraries but this is an attempt at self learning JavaScript. I thought that maybe it was possible to return the button from stylePage and add the event listener to the return value but that didn't work. Any suggestion is much appreciated, thanks!

function stylePage(){
  var body = document.getElementsByTagName("body");
  body[0].style.backgroundColor = "rgb(214, 214, 214)";
  body[0].style.color = "#778899";
  body[0].style.fontFamily = "Courier";
  body[0].style.textAlign = "center";
  var remove = document.getElementById("removeReference");
  remove.nextElementSibling.remove();
  var newButton = document.createElement("button");
  var newContent = document.createTextNode("Not enough?");
  newButton.appendChild(newContent);
  document.body.insertBefore(newButton, remove);
};

function createImage(){
  var img = document.createElement("img");
  img.src = "pepsi_dog_by_werelyokoman.jpg";
  document.getElementById("imagePlaceholder").appendChild(img);
}

var button = document.getElementsByTagName("button");
button[0].addEventListener("click", stylePage);
//??? reference to newButton ??? .addEventListener("click", createImage);
HiFi
  • 21
  • 1
  • 7

2 Answers2

0

The easiest way to do this would be to add .addEventListener to the end of your stylePage function:

  var newContent = document.createTextNode("Not enough?");
  newButton.appendChild(newContent);
  document.body.insertBefore(newButton, remove);
  newButton.addEventListener("click", createImage);    
};

JSFiddle demonstrating this.

But say you didn't want to do that for some reason -- maybe you don't have control over the function that's dynamically creating your button. In this case you could use MutationObserver to watch for changes in the DOM.

You'd do this like so:

var target = document.getElementsByTagName('body')[0];
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if(mutation.addedNodes.length > 0 && mutation.addedNodes[0].firstChild.nodeValue == "Not enough?") {
       mutation.addedNodes[0].addEventListener("click", createImage);
    }
  });    
});

var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);

See this JSFiddle.

Christian Ternus
  • 8,406
  • 24
  • 39
-2

You can use event delegation:

document.querySelector('body').on('click', function() {
    //You need to identify the new elements here......
});

I created a jsfiddle: jsfiddle

Zich
  • 53
  • 4
  • This doesn't do at all what the OP asked for -- the whole point of the question is identifying the new elements. – Christian Ternus Aug 20 '16 at 03:32
  • Also, really silly to use `document.querySelector('body')` when `document.body` gets you the body element too. But, this doesn't even solve the problem. – jfriend00 Aug 20 '16 at 03:36
  • The whole point of the question was to ensure a click handler was attached to dynamically created elements. This is exactly what event delegation is meant to handle. – CrayonViolent Aug 21 '16 at 02:41