Only the last button's onclick works - javascript

I inserted into .content some buttons with innerHTML, and I used addEventListener to got the onclick event and show a message when each button clicked. The problem is that only the last button's onclick works, What is the problem?
var x = document.getElementById("content");
for(let i = 0; i < 2; i++)
{
x.innerHTML += `
<button type="button" class="click-btn" id="click-btn-id" value="${i}">
click me
</button>
`;
// get last button that was INNER to .content
var btn_option = document.getElementsByClassName("click-btn");
var btn = btn_option[btn_option.length - 1];
btn.addEventListener("click", () => {
console.log('clicked!');
});
}
body {
background: black;
}
button {
margin-top: 30px;
}
<div id="content">
</div>

Using var btn = btn_option[btn_option.length - 1] makes you select the second button as btn-option.length - 1 is 1. Thats means you select the button at index 1. and not both 0 & 1.
Try using
var x = document.getElementById("content");
for(let i = 0; i < 2; i++)
{
x.innerHTML += `
<button type="button" class="click-btn" id="click-btn-id" value="${i}">
click me
</button>
`;
var btn_option = document.getElementsByClassName("click-btn");
btn-option.addEventListener("click", () => {
console.log('clicked!');
});
}

It's because you override the content by setting innerHTML directly. The working way is to append button html to the DOM using insertAdjacentHTML, for example.
var x = document.getElementById("content");
for (let i = 0; i < 2; i++) {
buttonHTML = `
<button type="button" class="click-btn" id="click-btn-id" value="${i}">
click me
</button>
`;
x.insertAdjacentHTML("beforeend", buttonHTML);
// get last button that was INNER to .content
var btn_option = document.getElementsByClassName("click-btn");
var btn = btn_option[btn_option.length - 1];
btn.addEventListener("click", () => {
console.log("clicked!");
});
}
body {
background: black;
}
button {
margin-top: 30px;
}
<div id="content">
</div>

try this code
var wrapper = document.getElementById("content")
wrapper.addEventListener("click", function(ev){
var btn_option = document.getElementsByClassName("click-btn");
Object.keys(btn_option).forEach(function(key){
if(ev.target == btn_option[key]){
console.log("btn "+ btn_option[key].getAttribute("value") +" click")
}
})
})
for(var i = 0; i < 2; i++){
wrapper.innerHTML += `
<button type="button" class="click-btn" value="${i}">
click me
</button>
`;
}
<div id="content">
</div>
body {
background: black;
}
button {
margin-top: 30px;
}

You also can loop your code like this.
var x = document.getElementById("content");
for(let i = 0; i < 2; i++) {
x.innerHTML += `<button type="button" class="click-btn" id="click-btn-id" value="${i}"> click me</button>`;
// get last button that was INNER to .content
var btn_option = document.getElementsByClassName("click-btn");
var len=btn_option.length;
for (let i=0; i<len; i++){
var btn = btn_option[i];
btn.addEventListener("click", () => {
console.log('clicked!'+i);
});
};
}

Related

Unable to remove checkbox with JavaScript

Actually, I want to remove a specific checkbox div from at any time.
As trying to give a functionality that a user can add or remove a checkbox perfectly.
I wrote the code I try to add or rest the check box but when I try to remove the checkbox it does not work and I am not figuring out what is the problem.
Can someone fix it?
function uncheckAll2() {
var inputs = document.querySelectorAll('input[name="todo[]"]');
for (var i = 0; i < inputs.length; i++) {
inputs[i].checked = false;
}
}
function removeElement(elementId) {
// Removes an element from the document
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
function addItem() {
var ul = document.getElementById('ul'); //ul
var li = document.createElement('li');
var div = document.createElement('div'); //li
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.value = 1;
checkbox.name = "todo[]";
checkbox.className = "textt";
div.appendChild(checkbox);
var text = document.getElementById('texto');
div.appendChild(document.createTextNode(text.value));
li.appendChild(div);
ul.appendChild(li);
}
function addElement(elementId, html) {
// Adds an element to the document
newElement.setAttribute('id', elementId);
newElement.innerHTML = html;
}
var checkId = 0;
function addcheck() {
checkId++; // increment fileId to get a unique ID for the new element
var html = 'Remove';
addElement( checkId, html);
}
var button = document.getElementById('btn');
button.onclick = addItem , addcheck() ;
<body>
<h1>Add or remove element</h1>
<hr>
<br>
<ul id="ul">
</ul>
</div>
<button type="button" id="btn" onclick="addItems , addFile() ">Add More</button>
<input type="text" id="texto">
<input type="button" onclick="uncheckAll2()" class="btn btn-link" value="Reset">
here is the working code ok Eddie ?
function uncheckAll2() {
var inputs = document.querySelectorAll('input[name="todo[]"]');
for (var i = 0; i < inputs.length; i++) {
inputs[i].checked = false;
}
}
function removeElement(linkElement) {
// Removes an element from the document
var element = linkElement.parentNode.parentNode;//to get to the li element
element.parentNode.removeChild(element);
}
function addItem() {
var ul = document.getElementById('ul'); //ul
var li = document.createElement('li');
var div = document.createElement('div'); //li
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.value = 1;
checkbox.name = "todo[]";
checkbox.className = "textt";
div.appendChild(checkbox);
var text = document.getElementById('texto');
div.appendChild(document.createTextNode(text.value));
addcheck(div)
li.appendChild(div);
ul.appendChild(li);
}
function addElement(div,elementId, html) {
// Adds an element to the document
div.setAttribute('id', elementId);
div.innerHTML += html;
}
var checkId = 0;
function addcheck(div) {
checkId++; // increment fileId to get a unique ID for the new element
var html = '<a class="link" href="" onclick="javascript:removeElement( this ); return false;">Remove</a>';
addElement( div, checkId, html);
}
var button = document.getElementById('btn');
button.onclick = addItem ;
add this css for just readability but i think you will add more to the css
<style>
.link{
padding-left: 10px;
}
</style>
There is a way to do it with a single function:
<body>
<h1>Add or remove element</h1>
<hr>
<br>
<div>
<ul id="ul">
</ul>
</div>
<button type="button" id="btn" onclick="addItem()">Add More</button>
<input type="text" id="texto">
<input type="button" onclick="uncheckAll2()" class="btn btn-link" value="Reset">
</body>
</html>
<script type="text/javascript">
function uncheckAll2() {
var inputs = document.querySelectorAll('input[name="todo[]"]');
for (var i = 0; i < inputs.length; i++) {
inputs[i].checked = false;
}
}
var checkId = 0;
function addItem() {
var ul = document.getElementById('ul'); //ul
var li = document.createElement('li');
var div = document.createElement('div'); //li
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.value = 1;
checkbox.name = "todo[]";
checkbox.className = "textt";
li.id = checkId;
removeLink = 'Remove';
checkId++;
div.appendChild(checkbox);
var text = document.getElementById('texto');
div.appendChild(document.createTextNode(text.value));
div.innerHTML+=removeLink;
li.appendChild(div);
ul.appendChild(li);
}
</script>

JS Target Respective Value in an Array

I have a for loop which is responsible for opening a custom modal. The opening button is defined as multiple elements with the class of .col-sm-4
Here are the code:
// Get the modal
var modal = document.getElementById('myModal');
// Get the opening trigger
var btn = document.getElementsByClassName('col-sm-4');
for (var i = 0; i < btn.length; i++) {
// Open modal by clicking the order display
btn[i].onclick = function(event) {
// Check to see if target is the parent element
if(event.target.tagName.toLowerCase() === 'div') {
modal.style.display = 'block';
document.getElementsByClassName('col-sm-4');
var idDIVOrderParent = btn[0].id;
// Having trouble grabbing the correct ID
console.log('The order ID is ' + idDIVOrderParent);
// extract orderId9999 from string like parentOrderId9999
var idDIVOrder = 'o' + idDIVOrderParent.substr(7);
console.log('The modal is currently displaying ' + idDIVOrder);
document.getElementById(idDIVOrder).style.display = 'block';
} else {
// console.log('Child element clicked!');
}
}
}
Where it says var idDIVOrderParent = btn[0].id is where I'm having difficulties. How can I grab the ID of the correct .col-sm-4 which triggered the modal?
This should do the trick.
var modal = document.getElementById('myModal');
var btn = document.getElementsByClassName('col-sm-4');
for (let i = 0; i < btn.length; i++) {
btn[i].onclick = function(event) {
if(event.target.tagName.toLowerCase() === 'div') {
modal.style.display = 'block';
let idDIVOrderParent = btn[i].id;
console.log('The order ID is ' + idDIVOrderParent);
let idDIVOrder = 'o' + idDIVOrderParent.substr(7);
modal.textContent = idDIVOrder;
console.log('The modal is currently displaying ' + idDIVOrder);
}
}
}
#myModal {
width: 200px;
text-align: center;
background: #ccc;
display: none;
}
<div id="parentOrderId9999" class="col-sm-4">btn1</div>
<div id="parentOrderId1111" class="col-sm-4">btn2</div>
<div id="parentOrderId2222" class="col-sm-4">btn3</div>
<div id="parentOrderId3333" class="col-sm-4">btn4</div>
<div id="myModal"></div>

How can fix this code? button on click will give 1 point & another that remove 1

I have used
<button onclick="addPoint()>
var p = document.getElementById("p");
var total = 0;
function addPoint() {
total++
}
function minusPoint() {
total--;
}
p.innerHTML = total;
You need to update element value p.innerHTML = total; inside the click handler as below
var p = document.getElementById("p"); var total = 0;
function addPoint() {
total++;
p.innerHTML = total;
}
function minusPoint() {
total--;
p.innerHTML = total;
}
<button class="button" onclick="addPoint()">add a point</button> <button class="button" onclick="minusPoint()">remove a point</button> <p id="p">Points:</p>
Using innerHTML to update the total every time the buttons are clicked.
var p = document.getElementById("p");
var total = 0;
function addPoint() {
total++;
p.innerHTML = total;
}
function minusPoint() {
total--;
p.innerHTML = total;
}

get index of child with event.currentTarget

How to get rid of jQuery's ".index()" here? All I am looking for is a native way to get the index of the button clicked, see source code below (works perfectly but I really couldn't find any Vanilla-JS solution for this and I don't want to use jQuery for such a small task). Thanks.
function navButtonClick(ev) {
var buttonIndex = $(ev.currentTarget).index(); /* How to get rid of jQuery? */
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i=0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
The HTML part looks like this:
<nav id="navigation" role="navigation">
<button type="button"> <em>Navi tab 1</em> </button>
<button type="button"> Navi tab 2 </button>
<button type="button"> Navi tab 3 </button>
<button type="button"> Navi tab 4 </button>
</nav>
<div id="output"></div>
You can do it like this:
function navButtonClick(ev) {
var buttonIndex = Array.prototype.indexOf.call(this.parentElement.children, this);
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i=0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
Check the snippet below:
function navButtonClick(ev) {
var buttonIndex = Array.prototype.indexOf.call(this.parentElement.children, this);
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i = 0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
<nav id="navigation" role="navigation">
<button type="button"> <em>Navi tab 1</em>
</button>
<button type="button">Navi tab 2</button>
<button type="button">Navi tab 3</button>
<button type="button">Navi tab 4</button>
</nav>
<div id="output"></div>
You can do this in two different ways. First, pass the index of the buttons to the corresponding function while adding the event listeners:
function navButtonClick(buttonIndex) {
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i = 0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick.bind(null, i));
}
}
startTemplate();
JSFiddle
Second, create a function which will dynamically check the index of the element:
function navButtonClick() {
document.getElementById("output").innerHTML = getIndex(this);
}
function getIndex(elm) {
var parent = elm.parentElement;
for (var i = 0; i < parent.children.length; i++) {
if (parent.children[i].isEqualNode(elm)) {
return i;
}
}
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i = 0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
startTemplate();
JSFiddle
<script>
function navButtonClick(index) {
return function (ev) {
document.getElementById("output").innerHTML = index;
}
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i=0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick(i));
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
</script>
Hope, it works :)
Anyway, only for buttons (I need closest in chrome even for them).
document.addEventListener('click', function (event) {
var target = event.target, nodes, i;
if (target.closest) {
target = target.closest('button');
}
if (target && target.tagName === 'BUTTON') {
nodes = target.parentElement.children;
for (i=0; nodes[i]!==target; ++i);
document.querySelector("output").textContent = i;
}
})
<nav id="navigation" role="navigation">
<button type="button"> <em>Navi tab 1</em> </button>
<button type="button"> Navi tab 2 </button>
<button type="button"> Navi tab 3 </button>
<button type="button"> Navi tab 4 </button>
</nav>
<output></output>
ES6-style answer:
const indexOf = element => Array.from(element.parentNode.children).indexOf(element)
const buttonIndex = indexOf(event.currentTarget)

addEventListener does not work on dynamically created button

I'm creating 3 buttons dynamically. Now I need to add an onclick event. How can I make the onclick work?
var btns='';
var category = ["fur_", "fts_", "fas_"];
for(i = 1; i < category.length; i++){
btns +='<button type="button" class='+category[i]+' id= "myBtn'+i+'">Button</button>';
}
document.getElementById('div').innerHTML = btns;
var button = document.getElementById('myBtn1');
button.addEventListener('click', function () {
alert('Clicked');
}, false);
You can get all the button elements and add the click event handler using a loop
var btns = '';
var category = ["fur_", "fts_", "fas_"];
for (i = 1; i < category.length; i++) {
btns += '<button type="button" class=' + category[i] + ' id= "myBtn' + i + '">.....</button>';
}
var div = document.getElementById('div');
div.innerHTML = btns;
var handler = function () {
alert('Clicked');
};
var buttons = div.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', handler, false);
}
Demo: Fiddle
Another approach is to create a button element in the loop
var div = document.getElementById('div');
var btn;
var category = ["fur_", "fts_", "fas_"];
var handler = function () {
alert('Clicked');
};
for (var i = 1; i < category.length; i++) {
btn = document.createElement('button');
btn.cassName = category[i];
btn.cassName = 'myBtn' + i;
btn.innerHTML = '....';
btn.addEventListener('click', handler, false);
div.appendChild(btn);
}
Demo: Fiddle

Categories