Example 1:
element1.addEventListener("input", function() {
// this function does stuff
});
Example 2:
element1 && element2.addEventListener("input", function() {
// this function does stuff
});
It might not be correct grammatically, but is there a way I can give two elements the same event listener at the same time (same line) instead of having to write them apart?
Well, if you have an array with the elements you could do:
let elementsArray = document.querySelectorAll("whatever");
elementsArray.forEach(function(elem) {
elem.addEventListener("input", function() {
//this function does stuff
});
});
Event Bubbling is the important concept in javascript, so if you can add event on DOM directly, you can save some lines of code, no need for looping :
document.addEventListener('click', function(e){
if(e.target.tagName=="BUTTON"){
alert('BUTTON CLICKED');
}
})
If you don't want to have a separate elementsArray variable defined you could just call forEach from an unnamed array with the two elements.
[ Element1, Element2 ].forEach(function(element) {
element.addEventListener("input", function() {
this function does stuff
});
});
One line
document.querySelectorAll("whatever").forEach(elem => elem.addEventListener("input", fn))
I cannot claim credit for this solution but I found a great solution here.
https://www.kirupa.com/html5/handling_events_for_many_elements.htm
var theParent = document.querySelector("#theDude");
theParent.addEventListener("click", doSomething, false);
function doSomething(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
alert("Hello " + clickedItem);
}
e.stopPropagation();
}
I always recommend delegation - if the inputs are in the same container, then you can do this
window.addEventListener("DOMContentLoaded", function() { // on page load
document.getElementById("inputContainer").addEventListener("input", function(e) { // passing the event
const tgt = e.target;
const id = tgt.id;
console.log("You typed in",id)
});
});
<div id="inputContainer">
<h1>Start typing or paste</h1>
<input id="element1">
<input id="element2">
</div>
Example:
const element1 = document.querySelector("#element1");
const element2 = document.querySelector("#element2");
[element1, element2].map(element => element.addEventListener("click", function() {
/*some expressions :)*/
}))
If you are using Javascript through Electron and you have a list of buttons, you can use this code to add an EventListener to each button.
I'm actually using this method because classical Javascript methods (map(), forEach() ...) weren't supported anymore.
let buttons = document.getElementsByClassName('className');
for(let i = 0; i<buttons.length; i++){
buttons[i].addEventListener('click', () => {
/*put your code here*/
});
}
Maybe it will help you
let all_btn = document.querySelectorAll("button");
all_btn.forEach(function(btn) {
btn.addEventListener("click", function() {
console.log(this.innerHTML + " is clicked")
});
});
// one line code
// let all_btn=document.querySelectorAll("button");all_btn.forEach(function(n){n.addEventListener("click",function(){console.log(this.innerHTML+" is clicked")})});
<button>button 1</button>
<button>button 2</button>
<button>button 3</button>
The easiest way so far I've learned.
// Get an array of buttons from the page
var buttons = document.querySelectorAll(".btns");
// Loop through the resulting array
for(var i = 0; i < buttons.length; i++){
buttons[i].addEventListener("click", function() {
console.log("Hello World");
});
}
You can add an event listener to multiple elements using the path key of the click event object.
document.addEventListener('click', function(e){
//e.path[0].id;
//e.path[0].tagName;
//e.path[0].className;
if(e.path[0].className==="my-element"){
console.log("clicked");
}
})
Example for initializing one unique event listener specific to each element.
You can use the slider to show the values in realtime, or check the console.
On the <input> element I have a attr tag called data-whatever. You can use that to customize each event listener further.
sliders = document.querySelectorAll("input");
sliders.forEach(item=> {
item.addEventListener('input', (e) => {
console.log(`${item.getAttribute("data-whatever")} is this value: ${e.target.value}`);
item.nextElementSibling.textContent = e.target.value;
});
})
.wrapper {
display: flex;
}
span {
padding-right: 30px;
margin-left: 5px;
}
* {
font-size: 12px
}
<div class="wrapper">
<input type="range" min="1" data-whatever="size" max="800" value="50" id="sliderSize">
<em>50</em>
<span>Size</span>
<br>
<input type="range" min="1" data-whatever="OriginY" max="800" value="50" id="sliderOriginY">
<em>50</em>
<span>OriginY</span>
<br>
<input type="range" min="1" data-whatever="OriginX" max="800" value="50" id="sliderOriginX">
<em>50</em>
<span>OriginX</span>
</div>
If you have a DOM Collection, I suggest you to use the for ... of
In this MDN web doc you can see the details, but, for example, if you have:
HTMLCollection(6) [a.example, a.example, a.example, a.example, a.example, a.example]
You can:
let arrayElements = document.getElementsByClassName('example');
for (let element of arrayElements) {
element.addEventListener("click", function() {
console.log('Whoa! You clicked me')
});
And ta-dah! ;)
Here's what I used to set a click evenhandler on every span in my HTML (each span contains an emoji). When you click it, it will alert the emoji in the sample code.
Array.from(document.querySelectorAll("span")).map(element => element.addEventListener("click", function() {
alert(element.innerHTML);
}));
div{background: whitesmoke;}
span{ont-size:x-large;
cursor:pointer;}
<div>
<span>😀</span>
<span>😁</span>
<span>😂</span>
<span>😃</span>
<span>😄</span>
<span>😅</span>
<span>😆</span>
<span>😇</span>
<span>😈</span>
<span>😉</span>
<span>😊</span>
<span>😋</span>
</div>
First include jQuery then after you have included, add this script below.
Html code:
<script>
$('.greadingButton').on('click', function () {
$('.greadingButton').removeClass('selected');
$(this).addClass('selected');
});
</script>
Related
I want to be able to click on an element and then depending on whether it has a specific class name, do something.
Here is what I have so far:
<div class="my-class" onclick="myFunction()"/>
function myFunction() {
if (element.classList.contains("my-class")) {
//do something
}
}
where am I going wrong?
You need to pass the click event then get the target element which in this case is the clicked element.
function myFunction(event) {
if (event.target.classList.contains("my-class")) {
alert("I Do things becuase i have (my-class)")
}
}
<button class="my-class" onclick="myFunction(event)">Click me</button>
<br/>
<br/>
<br/>
<br/>
<button onclick="myFunction(event)">I Do nothing</button>
As #collapsar mentioned in comment, element is't set. I recommand you to use addEventListener and event.target.
document.getElementById("your-element").addEventListener("click", () =>{
if (event.target.classList.contains("my-class")) {
console.log("your-element has \"my-class\" class")
}
})
<div id="your-element" class="my-class">Click</div>
When the HTML element rendered statically you should consider two things:
Wait for the DOM ready event in order to make modifications on the element.
Attach the event dynamically, making sure that you bind the event handler to new elements after adding them to the DOM.
HTML
<div class="my-class" />
Javascript
function myFunction(event) {
var element = event.target;
if (element.classList.contains("my-class")) {
//do something
}
}
document.addEventListener("DOMContentLoaded", function(event) {
// DOM is ready
const elements = document.getElementsByClassName("my-class");
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', myFunction);
}
});
$(document).ready(function() {
$(".inputWithLimit").each(() => {
var inp = this;
inp.addEventListener("input",
function (event){
console.log($(inp).val().length);
});
});
})
I've also tried "keyup" and "change" as event handlers, and in both other cases, jquery is doing a strange thing with assigning these listeners. Thanks.
If you are using jQuery then there is no need to loop through each element and add an event listener. An example which logs the value of each input when you input something.
$(document).ready(function() {
$(".inputWithLimit").on('input',function() {
console.log(this.value);
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="inputWithLimit">
<input class="inputWithLimit">
The problem is your arrow function. When using arrow function, then you can't use `this'
$(".inputWithLimit").on("input", function() {
console.log($(this).val().length);
});
I've also made your code shorter.
Demo
$(document).ready(function() {
$(".inputWithLimit").on("input", function() {
console.log($(this).val().length);
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="inputWithLimit" />
I am trying to add a click event on an element which i create dynamically in Vanilla JS. With jquery its super simple all i would do is
$(document).on('click','.el', function() {
//somecode
})
However with Vanilla JS (because i'm using react) i can't do the same thing.
I've tried adding the dynamic element as an argument just like i would in jquery but no money.
I'm sure it can be done just not the way i'm thinking. Any ideas?
I tried
let div = document.createElement('DIV')
div.classList.add('el')
document.addEventListener('click','.el', function() {
//some code
})
I also tried
document.addEventListener('click',div, function() {
//some code
})
None of these methods worked
let div = document.createElement('DIV');
div.classList.add(".whatever");
div.addEventListener('click', function() {
console.log('dynamic elements')
});
document.body.appendChild(div);
https://jsfiddle.net/yu1kchLf/
You could simply use and onclick function and just call it as variable from your dynamically added elements.
Live Demo
//Create function
let button = document.createElement('button');
button.classList.add("myBtn");
button.innerText = 'Click Me';
button.onclick = myFunction //assign a function as onclick attr
document.body.appendChild(button);
//Call function
function myFunction() {
console.log('I am being called from dynamically created button')
}
i think what you are missing is appending the element you created to your DOM.
have a look at this:
var createDiv = function() {
let div = document.createElement('DIV');
div.id = 'el';
div.innerHTML = '<b>hey</b>';
div.classList.add('styles');
document.body.appendChild(div);
div.addEventListener('click', function() {
alert('Look here');
})
};
here's a fiddle so you can playaround: https://jsfiddle.net/khushboo097/e6wrLnj9/32/
You can do something like the following:
const d=document.getElementById("container");
document.addEventListener('click', function(ev) {
if (ev.target?.classList.contains('el')) {
console.log("My .el element was clicked!");
ev.target.classList.contains("segundo") &&
(d.innerHTML+='<p class="el">another clickable paragraph</>');
}
})
<div id="container"><h2>Something unclickable</h2>
<p class="el primero">A clickable paragraph!</p>
<p class="otro primero">something unclickable again ...</p>
<button class="el segundo">add clickable element</button>
</div>
The event handler is attached to the document itself but will only fire the console.log() if the ev.target, i. e. the clicked element, is of class "el".
I have built a pretty complex slider and now have to build it so it can be removed and re-added to the page based on a selection. I have a simple click event listener for the pagination to call all my animations and timers that looks like this
let $slideItems = $slideShow.querySelector('.slideshow-items'),
$slideshowNav = $slideShow.querySelector('.slideshow-nav'),
$slideshowNavButton = $slideshowNav.getElementsByTagName('button');
forEach($slideshowNavButton, (index, el) => {
el.addEventListener('click', function() {
let isActive = this.classList.contains('active');
if (!isActive) {
clearTimeout(timer);
slideshowClick($slideShow, this);
slideshowAnimations($slideShow, index);
slideTimer();
}
});
});
I use the forEach function as a for loop to go through all the elements I need, like having multiple $slideShow's on the page, and return them as an indexed array. The issue I am having is that I need to add a functionality in which the $slideshowNav and all the $slideshowNavButtons get removed and rebuilt from a function outside of the $slideshow function and can't figure out how to rebind the click event without repeating all of the code. Is there a way to bind this event to the $slideshow object, similar to the way jQuery's .on function works or rebind the click event to the new $slideshowNavButton's after they are created? I am not able to use jQuery so I can't use the .on function.
its hard to give you correct answer since you motion too many classes without visual placement but hope this helps:
var btnWraper = document.querySelectorAll('.btnWraper > button');
btnWraper.forEach(function(e){
e.onclick = buttonClicking;;
})
let remake = document.getElementById('reMakeMe');
remake.addEventListener('click', function(){
var btnWraper = document.querySelectorAll('.btnWraper > button');
//if deleted
if(!btnWraper.length)
{
createButtons('Btn1');
createButtons('Btn2');
createButtons('Btn3');
createButtons('Btn4');
}
},false)
let rest = document.getElementById('resetMe');
rest.addEventListener('click', function(){
var btnWraper = document.querySelectorAll('.btnWraper > button');
btnWraper.forEach(function(e){
e.remove();
})
},false) ;
function buttonClicking (){
alert(this.innerHTML);
}
function createButtons(value){
var btn = document.createElement("button");
btn.innerHTML = value;
btn.onclick = buttonClicking;
var parentElement = document.getElementsByClassName("btnWraper")[0];
parentElement.appendChild(btn);
}
<div class="btnWraper">
<button>Btn1</button>
<button>Btn2</button>
<button>Btn3</button>
<button>Btn4</button>
</div>
<div>
<button id="resetMe">Reset All</button>
<button id="reMakeMe">ReMake All</button>
</div>
You know how there are times when you want to use one eventlistener for multiple elements? Like this:
divWithManyLinks.addEventListener("click", function(event) {
console.log(event.target.textContent);
}
//--> text content of the clicked link
And you know how there are times when you want to use bind with an eventlistener to change the scope of the eventhandler? For instance, you might need to reference 'this' and point to something specific.
What if you want to have one eventlistener for multiple elements and use bind at the same time, is that possible?
In my case, I want to be able to go from one method (Example.prototype.methodA) to one of two other methods in the same object (Example.prototype.methodB or Example.prototype.methodC) based on what button is clicked. Because the eventlistener is placed inside of methodA the other methods will be referenced with this.methodB and this.methodC. I could possibly implement two eventlisteners with bind separately, but is it possible to have just one eventlistener?
Example.prototype.methodA = function() {
// addEventListener that listens on both buttons and executes either this.methodB or this.methodC based on what button is clicked.
}
Example.prototype.methodB = function() {
// do stuff
}
Example.prototype.methodC = function() {
// do stuff
}
If this is bad practise or if there is a better way to do it, please let me know.
You can do that, yes. Here's an example:
Example.prototype.methodA = function() {
someContainerElement.addEventListener("click", function() {
if (/* `event.target` is a match for the first button*/) {
this.methodB();
} else {
this.methodC();
}
}.bind(this), false);
};
Of course, it doesn't have to be an if, could be a switch or a map lookup or...
Live Example:
function Example(element, name) {
this.name = name;
this.element = element;
this.output = element.querySelector(".output");
}
Example.prototype.methodA = function() {
this.element.addEventListener("click", function() {
if (event.target.name == "B") {
this.methodB();
} else {
this.methodC();
}
}.bind(this), false);
}
Example.prototype.methodB = function() {
this.output.innerHTML =
prep(this.name).toLowerCase();
};
Example.prototype.methodC = function() {
this.output.innerHTML =
prep(this.name).toUpperCase();
};
function prep(text) {
return text.replace(/&/g, "&").replace(/</g, "<");
}
new Example(document.getElementById("one"), "one").methodA();
new Example(document.getElementById("two"), "two").methodA();
<div id="one">
The "one" element:
<br>
<input type="button" name="B" value="Lower">
<input type="button" name="C" value="Upper">
<span class="output"></span>
</div>
<div id="two">
The "two" element:
<br>
<input type="button" name="B" value="Lower">
<input type="button" name="C" value="Upper">
<span class="output"></span>
</div>