简体   繁体   中英

Javascript only last event listener works

It's very difficult for me to show you my code, as it's all over the place, but what I'm trying to do is this:

I am injecting html code into the DOM in a function buy using .innerHTML , I wish to add a click event to an icon that is being injected in this step, as at this moment in time I know its id. So after I've injected it I write:

document.getElementById(product.id+"x").addEventListener("click", removeItem);

product.id is created above and this element is a 'X' button, that when clicked will be removed from the screen.

The trouble is, this code is run many times as there are many items to be displayed on the screen. And when finished, only the last even made fires when the 'X' button is pressed.

Any suggestions?

EDIT:

I am unable to use jquery in this project.

Here is my code:

function createHTML(targetID, product) {
    var target = document.getElementById(targetID);
    total = (parseFloat(total) + parseFloat(product.price)).toFixed(2);;
    target.innerHTML += '<article class="item" id="'+product.id+'"><img class="item_img" src="../'+product.image+'" width=100 height=100><h1 class="item_name">'+product.name+'</h1><p class="item_description">'+product.desc+'</p><h1 class="item_quantity">Quantity: '+product.quantity+'</h1><h1 class="item_price">&pound;'+product.price+'</h1><i id="'+product.id+'x" class="fa fa-times"></i></article>';

    document.getElementById(product.id+"x").addEventListener("click", removeItem, true);
}

So you're adding new elements to a container by overwriting the innerHTML or appending to it using += . This is your problem. When you overwrite the innerHTML or append to it, you are destroying and recreating all elements within it and this causes them to lose any bound event handlers (ie your click handler).

This fiddle reproduces your problem. Only the last button has a click handler.

The solution is to build DOM elements using document.createElement() and use appendChild() or similar to append them, instead of creating/appending raw HTML. This way, your previous elements event handlers will remain intact.

This Fiddle uses DOM nodes instead of raw HTML and all buttons have a click handler.

Example fix:

var container = document.getElementById("container");
var elem;

function clicky(){
    alert("clicked");   
}

for(var i=0; i<4; i++){
    elem = document.createElement('button');
    elem.id = "btn_" + i;
    elem.appendChild(document.createTextNode('Click'));
    elem.addEventListener("click", clicky);
    container.appendChild(elem);
}

I quess you do something like that

//Place where you add elements.
var container = document.body;

you create element and add listener to that element( button ):

var button = '<button id="btn1x">Button 1</button>';
container.innerHTML += button;

//product.id = 'btn1';
document.getElementById(product.id+"x").addEventListener("click", removeItem);

and then you add in the same way new elements and add for them event listeners before next element will be generated.

If my quess is right, then your problem is that you replace whole content of container so previous event listens are lost.

stringVariable += 'abc' is the same as stringVariable = stringVariable + 'abc' . Because of that you overwrite html.

You should create elements from functions, not from string as you do now.

var button = document.createElement('button');
button.id = product.id + 'x'; 
button.innerText = 'Button 1'; // Title of button.

//Add button to container.
container.appendChild(button);

//Add event listener to created button.
button.addEventListener('click', myFunc); 

UPDATE:

There are a way to parse your string to element.

First create container where will be set inner html from string, then get from that temp container first element (or more elements, depends from your html string), then add them to container and add to these elements listeners.

DEMO: http://jsfiddle.net/3cD4G/1/

HTML:

<div id="container">

</div>

Javascript:

var container = document.getElementById("container");

function clicky(){
    alert("clicked");   
}
var tempContainer = document.createElement('div');
for(var i=0; i<4; i++){
    //Create your element as string.
    var strElem = "<button type='button' id='btn_" + i + "'>Click</button>";
    //Add that string to temp container (his html will be replaced, not added).
    tempContainer.innerHTML = strElem.trim();//Trim function used to prevent empty textnodes before element.
    //Get element from temp container.
    var button = tempContainer.children[0];
    //Empty tempContainer for better security (But about which security I'm talking in JavaScript in string element generation :) )
    tempContainer.innerHTML = '';

    //Add your button to container.
    container.appendChild(button);

    //Add event listener to button:
    //document.getElementById("btn_" + i).onclick = clicky;
    //Better way to add event listener:
    button.addEventListener('click', clicky);
}

DEMO: http://jsfiddle.net/3cD4G/1/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM