How I know which button been clicked in class of buttons? - javascript

I have the class of buttons and I want to know which one been clicked using JavaScript
<button class="editors">Edit</button>
<button class="editors">Edit</button>
<button class="editors">Edit</button>
so I want to know which button is clicked

You can pass this to your function and then you have a reference to the clicked button.
[...document.getElementsByClassName('editors')].forEach(x => {
x.addEventListener('click', function() {
myFunction(this);
})
});
function myFunction(el) {
console.log(el);
}
[...document.getElementsByClassName('editors')].forEach(x => {
x.addEventListener('click', function() {
myFunction(this);
})
});
function myFunction(el) {
console.log(el);
}
<button class="editors">1</button>
<button class="editors">2</button>
<button class="editors">3</button>

You can attach event listener to the document or your button's wrapper element/div and then use the event.target property. That way you use only 1 event listener, instead of attaching multiple for each element. This approach is called Event Delegation. You can check the different event properties here.
document.addEventListener('click', function(evt) {
let element = evt.target;
console.log(`Clicked button: ${element.textContent}`);
});
<button class="editors">Edit</button>
<button class="editors">Details</button>
<button class="editors">Delete</button>

Related

EventListeners, which are defined in another EventListeners in JavaScript

I want to define an EventListener after clicking on a button.
I set EventListener in another EventListener and want the child EventListener to be listening to click event only after the parent event was triggered.
Code snippet:
const btn = document.querySelector(".btn")
btn.onclick = function() {
console.log("PARENT")
document.onclick = function() {
console.log("CHILD")
}
}
<button class="btn">Click</button>
Current behavior:
Parent and child events trigger together, even on the first click on the button.
So, even on the first click on the button I see "PARENT" "CHILD" in console, but I want to see only "PARENT".
Desired behavior:
Child EventListener should be listening to click event only after clicking on the button element. Thus, I want to see on the first click on the button only "PARENT" in console and after on subsequent clicks: "PARENT" "CHILD".
Why it works in such way?
Why does the event, defined in child EventListener, trigger with the event, defined in parent EventListener, though child EventListener should only start listening to click event when the parent event is triggered?
The event is handled for the button - where the new listener is assigned, then it bubbles up and handles the newly registered handler.
Anyway, it may be easier and more clear to use event delegation and a data-attribute to save the click state of the button. for example:
document.addEventListener(`click`, handle);
function handle(evt) {
console.clear();
if (evt.target.classList.contains(`btn`)) {
evt.target.dataset.clicked = 1;
return console.log(`.btn clicked`);
}
if (evt.target === document.documentElement) {
if (!document.querySelector(`.btn`).dataset.clicked) {
return true;
}
return console.log(`document clicked`);
}
}
<button class="btn">Click</button>
const btn = document.querySelector(".btn")
btn.onclick = function() {
console.log("PARENT");
setTimeout(() => (
document.onclick = function() {
console.log("CHILD")
}
), 0);
}
<button class="btn">Click</button>
more content:
Why is setTimeout(fn, 0) sometimes useful?

How to pass arguments to the event listener's function so that there would be no duplicate event listeners?

Currently, I use the following solution:
<button onclick="initiate('ok2')" id="btn1">Initiate</button>
<button id="btn2">Send data</button>
function initiate(ok) {
document.getElementById("btn2").addEventListener("click", receiveData);
}
function receiveData(event) {
console.log(event);
}
The benefit of this approach lies in the named function receiveData, which is recognized as the same function and is not added repeatedly.
Steps to reproduce:
Press the 'Initiate' button multiple times
Press 'Send data'
Result: console log is printed only once
I want to utilize the same approach, but add an attribute to the function. I tried the bind approach, but the event listener is added multiple times. As a result, the console log is also printed multiple times.
Example:
function initiate(ok) {
document.getElementById("btn2").addEventListener("click", receiveData.bind(null, ok));
}
function receiveData(event, ok) {
console.log(event);
console.log(ok);
}
Is it possible to pass an argument to a function and not create duplicate event listeners? Ideally, it would be preferred not to delete event listeners, like in the current solution.
Here is my version with the recommended ways of delegating and setting and getting data attribute
A user cannot click what is not visible so no need to initiate the button, just unhide it
document.addEventListener("click", function(e) {
let btn = e.target
if (btn.matches("#btn1")) {
let targetBTN = document.getElementById(btn.dataset.target);
targetBTN.hidden = false;
} else if (btn.matches("#btn2")) {
console.log(btn.dataset.field);
}
});
<button id="btn1" data-target="btn2">Initiate</button>
<button id="btn2" data-field="ok2" hidden>Send data</button>
// when the window loads add a click handler to the button of choice
window.addEventListener('load', (event) => {
console.log('page is now loaded');
document.getElementById("btn2").addEventListener("click", receiveData)
});
function receiveData(event) {
console.log(event);
}
or as suggested in comments, add the click handler inline.
You need to tel it if it is inited or not..
let data = "";
let init = true;
function initiate(ok) {
data = ok
if(init ){
document.getElementById("btn2")
.addEventListener("click", receiveData);
init = false
}
}
function receiveData(event) {
console.log( data );
}
<button onclick="initiate('ok2')" id="btn1">Initiate</button>
<button id="btn2">Send data</button>
It looks like the one goal is to only allow the second button to be able to be used when the first button is clicked.
So, I attached an event listener to the document. Then used data attributes on the buttons to determine if the start button can be used or not. And just for display I used CSS to hide the start button if its not allowed to be used just yet
document.addEventListener("click",function(e){
let btn = e.target
if(btn.matches(".btn-start")){
let targetBTN = document.querySelector(`[data-id='${btn.dataset.target}']`)
targetBTN.setAttribute("data-initiated","true");
}
else if(btn.dataset.initiated == "true"){
console.log(btn.dataset.field);
}
});
[data-initiated="false"]{
display:none
}
[data-initiated="true"]{
display:inline-block
}
<button data-target="send2" class="btn-start">Initiate</button>
<button data-initiated="false" data-field="ok2" data-id="send2" class="btn-send">Send data</button>

How to trigger a button tap with javascript?

I want to automatically trigger a tap on a button with javascript.
var submitButton = document.getElementsByName('name');
I tried the following and none of them worked.
submitButton.click();
and
const touchEvent = new TouchEvent("touchstart", {
touches: [touch],
view: window,
cancelable: true,
bubbles: true,
});
submitButton.dispatchEvent(touchEvent);
Neither worked.
Document.getElementsByName() returns a NodeList of elements (not a single element).
As far as the event, click should work just fine:
for (const elm of document.getElementsByTagName('button')) {
elm.addEventListener('click', (ev) => console.log(ev.target.textContent));
}
const buttons = document.getElementsByName('name');
for (const button of buttons) {
button.click();
}
<div>
<button name="name">one</button>
<button name="name">two</button>
<button>three</button>
</div>
Add an id to the above button with a onClick function.
Change the
document.getElementsByName('name')
to
document.getElementById('id')
Full Code:
Html:
<button id="btn" onClick="clicked()">
Click me
</button>
JS:
var btn=document.getElementById("btn");
btn.click();
function clicked() {
console.log("Clicked");
}
If you want to trigger multiple buttons with same class:
Html:
<button class="btn" onClick="clicked()">
Click me
</button>
JS:
var btn=document.getElementsByClassName("btn");
btn[0].click();
function clicked() {
console.log("Clicked");
}
For multiple button with same class, the return of the document.getElementsByClassName will return an array of object. In the above example, I have used the first element of that array, but if you want, you can loop through the array and trigger the click event.
document.getElementsByName returns a NodeList Collection of elements with a given name attribute in the document.
So your submitButton will be an array. So you have to dispatch the click event with submitButton[0].click()
var submitButton = document.getElementsByName('name');
submitButton[0].click();
function submitClick() {
console.log('submitClick')
}
<button name="name" onclick="submitClick()">Submit</button>

Remove $obj from DOM without removing bound events listener from that object

Let say I have some jQuery objects with bound events that I am interchanging inside a container
var $obj1 = $('<button type="button">Button 1</button>');
$obj1.click(function() { console.log("Button 1 clicked") });
var $obj2 = $('<button type="button">Button 2</button>');
$obj2.click(function() { console.log("Button 2 clicked") });
$("body").html($obj1);
//here the $obj1 click event listener is removed from $obj1
$("body").html($obj2);
//here nothing happen when I click on the Button 1
$("body").html($obj1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Is there a way I can add/remove jQuery object without having to bind the events listener every time?
You can change the way you select/create your listener
$('body').on('click','button',function(){});
I would suggest adding a class or another way to identify which one you are looking for:
$('body').on('click','button.first-button',function(){});
Can use detach() to remove what you want from dom and listeners will still be available if you re-insert that object
var $obj1 = $('<button type="button">Button 1</button>');
$obj1.click(function() { console.log("Button 1 clicked") });
var $obj2 = $('<button type="button">Button 2</button>');
$obj2.click(function() { console.log("Button 2 clicked") });
$("body").html($obj1);
$obj1.detach()
$("body").html($obj2);
$obj2.detach()
//click working now
$("body").html($obj1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can bind your listeners using .on() as shown below. Then you can add some data attributes/classes to your buttons to be able to differentiate them in your click handler.
$('body').on('click', 'button', function() {
console.log('button clicked');
});
http://devdocs.io/jquery/on
You can make use of event delegation, using on(), an have a handler added to a parent of those buttons, which will catch their clicks.
With event.target you get the button clicked at.
Also added event.target.matches(selector) to show how you can deal with other, existing, elements than the added buttons.
Stack snippet
$('.wrapper').on('click', function(event) {
if( event.target.matches('button') ) {
//do stuff for buttons
console.log('button', event.target.textContent);
}
if( event.target.matches('a') ) {
//do stuff for links
console.log('link', event.target.textContent);
}
});
var $obj1 = $('<button type="button">Button 1</button>');
var $obj2 = $('<button type="button">Button 2</button>');
$(".wrapper").append($obj1);
$(".wrapper").append($obj2);
$($obj1).remove();
$($obj2).remove();
$(".wrapper").append($obj1);
$(".wrapper").append($obj2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
Link 1
Link 2
</div>

JS - Programmatically send element with onclick

<button id="button1">Button</button>
document.getElementById("button1").onclick=function(){ ???.style.display="none" };
As you can see above, how could I change the style to hide it with the onclick?
(and no, I don't want to do <button onclick="x">)
Have a look at this
document.getElementById("button1").onclick=function(e){ e.target.style.display="none" };
<button id="button1">Button</button>
Use srcElement or target. (target is standard and srcElement is alias.)
document.getElementById("button1").addEventListener( "click", e => {
e.srcElement.style.display = "none";
} );
<button id="button1">Button</button>
document.addEventListener("click", function(){
document.getElementById("button1").style.display = "none";
});
<button id="button1">Button</button>
You can use addEventListener and change the style on click.
document.addEventListener("click", function(){
document.getElementById("button1").style.display = "none";
});
<button id="button1">Button</button>
You can use this inside the click handler to refer to the element clicked:
document.getElementById("button1").onclick=function(){
this.style.display="none";
};
<button id="button1">Button</button>
Using this means you could (if you wanted to) use the same handler function on multiple elements. You could also add the event handler with addEventListener as an alternative - this still refers to the element the handler is attached to.

Categories