I was experimenting [in jsfiddle] w/a function created to append a newly created TextNode
to the <p>
in the HTML below:
<button onclick="addTextNode('YES! ');">YES!</button>
<button onclick="addTextNode('NO! ');">NO!</button>
<button onclick="addTextNode('WE CAN! ');">WE CAN!</button>
<hr />
<p id="p1">First line of paragraph.</p>
Here is my javascript as well:
function addTextNode(text) {
var newtext = document.createTextNode(text),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
This works fine. However, the crux reveals itself when I attempt to make my javascript 'unobtrusive' by removing the behavior from the markup...
<button>YES!</button>
<button>NO!</button>
<button>WE CAN!</button>
<hr />
<p id="p1">First line of paragraph.</p>
then utilizing a loop to attach addEventListener
to each <button>
element, which in turn uses the child TextNode
to call addTextNode
:
function addTextNode(text) {
var newtext = document.createTextNode(text),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
var btns = document.getElementsByTagName("button");
for(i = 0; i < btns.length; i++){
var button = btns[i];
button.addEventListener("click", addTextNode(button.innerHTML));
}
Two strange things happen with my code:
When [jsfiddle's] Code Wrap is set to 'no wrap - in head', nothing happens.
However, When Code Wrap is set to 'onLoad', 'onDomReady' or 'no wrap - in body' the function runs before the click and I get this.
Could someone tell me what I'm missing?
This symptom is indicative that you've registered the same listener more than once. You must remember to deregister events when your component unloads to prevent his problem.
If you call addEventListener() twice on the same element, the listener will run twice.
If the same event listener function is registered twice on the same node with the same type and useCapture arguments, the second registration is simply ignored. ...
The addEventListener() methodYou can add many event handlers to one element. You can add many event handlers of the same type to one element, i.e two "click" events. You can add event listeners to any DOM object not only HTML elements.
The root of your problem is here:
button.addEventListener("click", addTextNode(button.innerHTML))
You're executing the function rather than passing it to the event listener. Instead, pass the function by reference, then get the innerHTML inside the function.
function addTextNode() {
var newtext = document.createTextNode(this.innerHTML),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
var btns = document.getElementsByTagName("button");
for(i = 0; i < btns.length; i++){
var button = btns[i];
button.addEventListener("click", addTextNode);
}
http://jsfiddle.net/bn85J/
First, your usage of Add Event listener is wrong. add event listener is expecting a function reference in the second parameter not a function call.
The following is a function reference:
var myfunctionreference = addTextNode;
This is a function call and will execute the function
var myfunctioncall = addTextNode();
In your code you are actually calling the function to use as the event handler instead of referencing it. Here is some Reference for .addEventListener()
You should be binding the event like this:
button.addEventListener("click", addTextNode);
Second, the event knows the element and knows the event. Your function call should be created to accept the event and not an arbitrary string. Then utilizing the event or "this" will allow you to get your hands on the text your looking for.
function addTextNode(evt) {
var newtext = document.createTextNode(this.innerHTML),
p1 = document.getElementById("p1");
p1.appendChild(newtext);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With