I am having trouble with adding an event listener to each button of the document, using a for ... of
loop.
var buttons = document.getElementsByTagName("button");
for (b of buttons) {
b.addEventListener("click", function() {
var n = document.createElement("span");
n.innerHTML = "new";
b.parentElement.appendChild(n);
b.style.display = "none";
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
</head>
<body>
<header>
<h1>Heading</h1>
</header>
<main>
<dl>
<dt>Title</dt>
<dd>Description</dd>
<dt>Title</dt>
<dd><button>add content</button></dd>
<dt>Title</dt>
<dd>Description</dd>
</dl>
<dl>
<dt>Title</dt>
<dd>Description</dd>
<dt>Title</dt>
<dd><button>add content</button></dd>
<dt>Title</dt>
<dd>Description</dd>
</dl>
</main>
</body>
</html>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
The above example only results in the appendig of n
after the last button
, not the first. Why is that and how can it be fixed? Is a for .. of
loop even the right way to do this?
CodePudding user response:
The problem is that the 'for' in that way doesn't work. You should use it like this:
var buttons = document.getElementsByTagName("button");
for (var i = 0; i < buttons.length; i ) {
b[i].addEventListener("click", function() {
var n = document.createElement("span");
n.innerHTML = "new";
b[i].parentElement.appendChild(n);
b[i].style.display = "none";
});
}
CodePudding user response:
From both of the above comments ...
"nitpicker mode ... does the OP mean the same or rather the selfsame or the very same. For the latter case(s) the OP then needs to provide the event listener as a single reference (maybe a function declaration) and not always another fully implemented anonymous callback function."
"In case the OP does utilize
querySelectorAll
the OP then can access aforEach
which iterates over the returnedNodeList
...document.querySelectorAll("button").forEach(/* ... */);
"
And in addition to the already said, the OP might retrieve the currently click button as currentTarget
of the provided event
object.
function handleContentCreation(evt) {
const button = evt.currentTarget;
const content = document.createElement('span');
content.textContent = 'new';
button.parentElement.appendChild(content);
button.style.display = 'none';
}
document
.querySelectorAll('button')
.forEach(elmNode =>
elmNode.addEventListener('click', handleContentCreation)
);
:not(dd) { margin: 0!important; padding: 0!important }
body { zoom: .9; }
h1 { font-size: 1.2em; }
<header>
<h1>Heading</h1>
</header>
<main>
<dl>
<dt>Title</dt>
<dd>Description</dd>
<dt>Title</dt>
<dd><button>add content</button></dd>
<dt>Title</dt>
<dd>Description</dd>
</dl>
<dl>
<dt>Title</dt>
<dd>Description</dd>
<dt>Title</dt>
<dd><button>add content</button></dd>
<dt>Title</dt>
<dd>Description</dd>
</dl>
</main>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>