How to detect classname with onclick event - javascript

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);
}
});

Related

Removing an onclick event from a div with javascript

Basically what the title says this is the code that I've tried but it doesn't work:
<div id="box" onclick="doSmt(var1, bar2)">
if (condition){
box.removeEventListener("click" , doSmt)}
I think it's better if you remove the onclick event instead of that attempt
//onclick function
function doSmt(){
console.log("something");
}
//remove onclick event, this will be inside your if condition
document.getElementById('box').removeAttribute("onclick");
<div id="box" onclick="doSmt()"> div</div>
What what I read at MDN for removeEventListener you can't remove an event listener that is part of the HTML attribute. So there's two options:
Add the event listener on page load
onClickHandler = () => doSmt(var1, var2);
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('box').addEventListener('click', onClickHandler);
});
// and later
if (condition) {
document.getElementById('box').removeEventListener('click', onClickHandler)
Or if you can't modify the HTML you could modify doSMT to watch for a disabled bit.
let disableBox = false;
function doSmt() {
if (disableBox) return;
// ...
}
if (condition) {
disableBox = true;
}
Or
it can be removed by first accessing the element and then setting the attribute to null
<div id="myDiv" onclick="handleClick()">Click me</div>
<script>
function handleClick() {
alert("Div was clicked!");
}
// Remove the onclick event from the div
const div = document.getElementById("myDiv");
div.onclick = null;
</script>

Handling multiple inputs with a single onfocus handler in javascript [duplicate]

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>

how to remove a class with the onclick event with javascript

any way that when I press a button it shows me a class and when I press another it removes the other class from the first button and so on with the other buttons?
Thank you for your help
function myFunction() {
document.getElementById("active1").classList.add('MyClass');
}
function myFunction2() {
document.getElementById("active").classList.add('MyClass');
}
function myFunction3() {
document.getElementById("active2").classList.add('MyClass');
}
.MyClass {
background-color: red;
color: #00ff1f;
}
<html>
<body>
<div id="active1" class="none"><button onclick="myFunction()">Try it</button></div>
<div id="active" class="none"><button onclick="myFunction2()">forobeta</button></div>
<div id="active2" class="none"><button onclick="myFunction3()">femax</button></div>
<button onclick="myFunction4()">forobeta</button>
</body>
</html>
Sorry if I thought your question was a spam attempt. It was not clear you wanted to add a class on a clicked button AND remove that same class on all the other buttons.
So.... Just forget about the inline onclick with multiple functions then. One eventListener can do the job for as many buttons you like.
Just use a data attribute to store the href to open and that event listener will do the rest.
let allBtns = document.querySelectorAll("button")
// For each button, register an event listener
allBtns.forEach(function(elem){
elem.addEventListener("click", function(e){
// On click, remove the MyClass on ALL buttons
allBtns.forEach(function(el){
el.classList.remove("MyClass");
});
// Add the class on clicked one
e.target.classList.add("MyClass");
// Now pass the data-href to your iframe
let theHREFtoOpen = e.target.getAttribute("data-href")
console.log(theHREFtoOpen)
//document.querySelector("#your-iframe").src = theHREFtoOpen
})
})
.MyClass {
background-color: red;
color: #00ff1f;
}
<div><button data-href="some href!!">Try it</button></div>
<div><button data-href="some other href!!">forobeta</button></div>
<div><button data-href="and another href!!">femax</button></div>
<button data-href="as you like and so on.">forobeta</button>
I did not understand everything in the question
but you can use
".classList.toggle('MyClass');" instead of ".classList.add('MyClass');"
to add the class when you press it and remove the same class if you press the same button again as shown in the code but if you want to make one button add class and another button remove the same class if exist
you can use this piece of code ".classList.add('MyClass');" to the button the add the class and ".classList.remove('MyClass');" to the button that remove the class
function myFunction() {
document.getElementById("myFrame").src = "https://www.youtube.com/embed/ElN_4vUvTPs";
document.getElementById("active1").classList.toggle('MyClass');
}
function myFunction2() {
document.getElementById("myFrame").src = "https://www.youtube.com/embed/PfrV_6yWbEg";
document.getElementById("active").classList.toggle('MyClass');
}
function myFunction3() {
document.getElementById("myFrame").src = "https://dood.to/e/pr9xvqpvhjxu";
document.getElementById("active2").classList.toggle('MyClass');
}
function myFunction4() {
document.getElementById("myFrame").src = "https://uqload.com/embed-swysx69drg1h.html";
}
.MyClass {
background-color: red;
color: #00ff1f;
}
<html>
<body>
<div id="active1" class="none"><button onclick="myFunction()">Try it</button></div>
<div id="active" class="none"><button onclick="myFunction2()">forobeta</button></div>
<div id="active2" class="none"><button onclick="myFunction3()">femax</button></div>
<button onclick="myFunction4()">forobeta</button>
<iframe id="myFrame" src="/default.asp" width="100%" height="100%" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen=""></iframe>
</body>
</html>
In order to add a class on a click event to a button, you could do something like this:
const btnAddClass = document.getElementById('btnAddClass');
btnAddClass.addEventListener('click', (e) => {
btnAddClass.classList.add('blue');
});
In order to remove a class, the code is quite similar. Instead of calling the add() method on the classList property of an element, we need to call the remove() function:
btnAddClass.classList.remove('blue');
A live example can be found here:
https://jsfiddle.net/dwome9yz/
If your ultimate goal is to make some sort of 'active' element be the only one with the class enabled from a list of buttons, you could do something along the lines of this, to get rid of all the 'active' elements first:
const removeActiveClass = () => {
const activeElements = document.getElementsByClassName('blue');
for (const activeElement of activeElements) {
activeElement.classList.remove('blue');
}
};
domElement.addEventListener('click', (e) => {
removeActiveClass(); // Call this first to remove the 'blue' class from all other elements
btnAddClass.classList.add('blue');
});
A live example can be found here:
https://jsfiddle.net/dpzLn1tj/
A simplified approach of the code posted above would be to use the same click event handler for all the buttons and only add the class to the button that was clicked using the target property of the event argument (Event.target) that is passed down during the click event and to remove the class for all the other elements:
const removeActiveClass = () => {
const activeElements = document.getElementsByClassName('blue');
for (const activeElement of activeElements) {
activeElement.classList.remove('blue');
}
};
const onClick = (e) => {
removeActiveClass();
e.target.classList.add('blue');
};
document.getElementById('btnAddClass').addEventListener('click', onClick);
document.getElementById('btnRemoveClass').addEventListener('click', onClick);
Live examples can be found here:
https://jsfiddle.net/dpzLn1tj/1/
https://jsfiddle.net/27c1n0wL/

jQuery alternative for replacing html without breaking Event Listeners

At a certain point of my code, I need to pick up an html string coming from an AJAX request and replace a certain container with it.
I have this but, as stated in several references across the web, it is garbage collected and unbinds the event listeners
this.rightPanel.innerHTML = content;
This however, doesn't happen with jQuery .html() function, which keeps the event listeners working, so doing
$(this.rightPanel).html(content);
works without flaw.
I didn't want to use jQuery for DOM manipulation, even so when browsers support it natively. What's the best alternative I have to reproduce the same behavior as jQuery .html()?
Thank you
This however, doesn't happen with jQuery .html() function...
Yes, it does.
...which keeps the event listeners working...
No, it doesn't. :-)
Like-for-like, they do the same thing to the event listeners:
// DOM
document.getElementById("btn1").addEventListener("click", function() {
console.log("Button 1");
});
// jQuery
$("#btn2").on("click", function() {
console.log("Button 2");
});
// Replace 'em
$("#btnRep").on("click", function() {
var wrap1 = document.getElementById("wrap1");
wrap1.innerHTML = wrap1.innerHTML + " (replaced)";
var wrap2 = $("#wrap2");
wrap2.html(wrap2.html() + " (replaced)");
});
<p>Click Button 1, then Button 2, Then Replace, then Buttons 1 and 2 again -- you'll see *neither* of them has a handler anymore after being replaced.</p>
<div id="wrap1">
<input type="button" id="btn1" value="Button 1">
</div>
<div id="wrap2">
<input type="button" id="btn2" value="Button 2">
</div>
<input type="button" id="btnRep" value="Replace">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
What you've probably seen is that jQuery makes event delegation really, really easy: That's where you actually hook the event on an ancestor element (perhaps even body), but you ask jQuery to only trigger your handler if it passed through an element during bubbling. That way, you can replace the descendant elements, because the event listener isn't on them, it's on the container/ancestor.
You can do that without jQuery as well, it's just a bit more work:
function addDelegated(element, eventName, selector, handler) {
element.addEventListener(eventName, function(e) {
// Start with the target element, and go through its parents
// until we reach the element we hooked the event on (`this`)
var element = e.target;
while (element && element !== this) {
// `matches` test the element against a CSS selector
if (element.matches(selector)) {
// Yes, trigger the handler
return handler.call(element, e);
}
element = element.parentNode;
}
});
}
// Hook the event on wrap1
addDelegated(document.getElementById("wrap1"), "click", "#btn1", function() {
console.log("Button 1");
});
// Replace
document.getElementById("btnRep").addEventListener("click", function() {
var wrap1 = document.getElementById("wrap1");
wrap1.innerHTML = wrap1.innerHTML + " (replaced)";
});
<p>Click Button 1, then Replace, then Button 1 again.</p>
<div id="wrap1">
<input type="button" id="btn1" value="Button 1">
</div>
<input type="button" id="btnRep" value="Replace">

AddEventListener for multiple elements doesn't work with "focus" event

I'm guessing I have a basic error in thinking but I just can't get around it.
I have a couple of text fields which I want to add an EventListener to.
I put them all in one class and added the EventListener to this class.
Everyhing works perfect when event of choice is "click". But when I change it to "focus" nothing happens. Why is that?
this works:
document.getElementById('parent').addEventListener('click', emptyField, false);
this doesn not:
document.getElementById('parent').addEventListener('focus', emptyField, false);
text fields:
function emptyField(e){
var clicked = e.target;
if (clicked.value == clicked.name) {
clicked.value='';
if (clicked.id=='password') {
clicked.type='password';
}
}
}
<class id="parent">
<input type="text" name="USERNAME" id="username" value="USERNAME"><br>
<input type="text" name="PASSWORD" id="password" value="PASSWORD" ><br>
</class>
The click event bubbles up to ancestor elements.
The focus event does not, and it is the <input> that is being focussed, not the outer element.
I think you have to use querySelectorAll() that will return all the inputs :
var fields = document.querySelectorAll('#parent input');
And use loop to attach focus event to every field :
for (var i = 0; i < fields.length; i++) {
fields[i].addEventListener('focus', emptyField, false);
}
Hope this helps.
If you want to attach an event to several elements without an explicit loop, you can use a helper function:
function attachEvents(elementList, eventName, handlerFunction) {
if(typeof elementList == "string")
elementList = document.querySelectorAll(elementList);
for(var i = 0; i < elementList.length; i++)
elementList[i].addEventListener(eventName, handlerFunction);
}
You call it like this:
attachEvents("#area button", "click", function(event) {
this.style.backgroundColor = "red";
});
Or like this:
attachEvents(document.getElementById("area").getElementsByTagName("button"), "click", function(event) {
this.style.backgroundColor = "red";
});
You don't always want document.querySelectorAll - doing it yourself means you also do things like some_element.querySelectorAll which is really nice when working with things that aren't yet part of the document, or have no unique selector.
But regardless, putting the loop in a helper function gives you that jquery-esque one-liner without a huge library, it is just a few lines of simple code.

Categories

Resources