I want to make a Javascript function where it reads the class of the selected element and adds the class active. How can I get the class of the HTML element where my function is?
I tried to make an Javascript function with document.getElementsByClassName(class), but that doesn't work.
function menuicon(){
var className = $('div').attr('class');
className.$(className).addClass("active");
}
<section class="menubar">
<div class="menuicon" onclick="classAdd()">
<span></span>
<span></span>
<span></span>
</div>
</section>
<section class="home">
<button class="hbutton" onclick="classAdd()"></button>
</section>
I want that the Javascript function reads out the class of the HTML element where the function is placed in.
You need to pass the element to the function:
onclick="classAdd(this)"
Then in the function, you just use .addClass, you don't need to use className.
function classAdd(element) {
$(element).addClass("active");
}
This code snippet only include 'active' in the classList of the div
var classAdd = function() {
var menuIcon = document.querySelector('div.menuicon');
menuIcon.addEventListener('click',() => {
menuIcon.classList.add('active');
});
}
If encase you want to stick with the div and the menuicon class.
Below code will work fine for you.
function classAdd() {
$("div.menuicon").attr("class", "menuicon active");
}
Related
as I said in title I have problem with HTML elements created with Element.insertAdjacentHTML() method, I'm trying about an hour to solve this but can't. I have button that create new HTML elements, couple of that elements is new buttons with same class or id, it's no matter, that I need to catch in some variable and than again use for event listener, for some reason the class or id for these new created button doesn't exist, is there any way to catch it and use it later, I need Vanila Javascript?
There is over 500 lines of code, this is only for mentioned method
btnClaim.addEventListener("click", () => {
rewardCurrent.style.display = "none";
claimedRewards.push(currentReward);
rewardsList.innerHTML = ``;
claimedRewards.forEach(function (rew, i) {
const html = `
<div class="reward" id="${i}">
<div class="img-text-cont">
<img src="${rew.imgUrl}" alt="">
<div class="text-cont">
<p class="claimed-reward-title">${rew.title}</p>
<p class="claimed-reward-price">$${rew.price}</p>
</div>
</div>
<div class="claimed-rewards-action">
<button id="btn-sell2">Sell</button>
<button id="btn-ship">Ship</button>
</div>
</div>
`;
rewardsList.insertAdjacentHTML("afterbegin", html);
I need that btn-sell2 and btn-ship buttons in variables.
your element is going to be created and doesn't exist at the time page loads, so js addeventlistener will throw an error. to solve you have 2 ways.
1- use parent node that element will be created inside.
addevenlistener to parent and use
parent.addeventlistener( event, function (event){
if(event.target.classList.contains("childClass") {}
}
2- give addeventlistener when creating the element :
function createElement () {
const elem = -craete elemnt-
elem.addeventlistener(event, function);
}
So I am having trouble understanding how to do this and how to approach this issue... I have a scroll animation on my page and I want to hide that div with animation after 3 seconds when it comes into view.
My HTML code for animated element is:
<div class="scroll-animation-wrapper">
<div class="scroll-animation">
<span></span>
<span></span>
<span></span>
</div>
</div>
Code in my Typescript is:
hideAnimatedDiv() {
const animatedDiv = document.getElementsByClassName('scroll-animation');
this.animatedDiv = true;
setTimeout(() => {
console.log('hide');
this.animatedDiv = false;
}, 3000);
}
I keep getting this error:
ERROR in src/app/configurator/configurator.component.ts(577,14): error TS2339: Property 'animatedDiv' does not exist on type 'ConfiguratorComponent'.
src/app/configurator/configurator.component.ts(580,18): error TS2339: Property 'animatedDiv' does not exist on type 'ConfiguratorComponent'.
Your code is trying to find animatedDiv property as global, because you have used this.animatedDiv instead try like this.
HTML
<div class="scroll-animation-wrapper">
<div id="scroll-animation" class="scroll-animation">
<span>a</span>
<span>b</span>
<span>c</span>
</div>
</div>
TS
ngOnInit() {
this.hideAnimatedDiv()
}
hideAnimatedDiv() {
let animatedDiv = document.getElementById('scroll-animation');
animatedDiv.style.display = 'block';
setTimeout(() => {
console.log('hide');
animatedDiv.style.display = 'none';
}, 3000);
}
To hide any element, we need to use style.display property of that element, like shown in the code.
Note: I have used ngOnInit function to make sure that div is hidden after component load only.
If you want to hide div I would suggest you this:
<div class="scroll-animation-wrapper">
<div class="scroll-animation" *ngIf="isDisplayed">
<span></span>
<span></span>
<span></span>
</div>
</div>
As you can see I added " *ngIf="isDisplayed" ". You should add the property "isDisplayed" to the component.
public isDisplayed: boolean = true;
hideAnimatedDiv() {
setTimeout(() => {
this.isDisplayed = false;
}, 3000);
}
If you want to add animation in Angular, the best way is to implement it as Angular Team suggests:
With this specific case I would use ":enter" ":leave" approach: https://angular.io/guide/transition-and-triggers#use-of-ngif-and-ngfor-with-enter-and-leave
I want to change to make it function into my Angular project
the script code
<script>
let btn = document.querySelector("#btn");
let sidebar = document.querySelector(".sidebar");
let searchBtn = document.querySelector(".bx-search");
btn.onclick = function() {
sidebar.classList.toggle("active");
if(btn.classList.contains("bx-menu")) {
btn.classList.replace("bx-menu", "bx-menu-alt-right");
} else {
btn.classList.replace("bx-menu-alt-right", "bx-menu");
}
}
</script>
Angular does all of these actions differently. Instead of querying DOM elements and affecting them from a script, you bind those elements to the scope this.
Much of what you need to accomplish actually happens in the HTML, and there is no need for ID tags on your elements
In your app.component.ts
export class AppComponent {
isBXMenu = false; // this isn't required because its just a boolean used in the HTML but it's good form to have it here
bxMenuAlt = false; // this is now how you switch the class name. When you need it to be bx-menu-alt-right, set this.bxMenuAlt = true
toggleBXMenu():void() {
this.bxMenuAlt = !this.bxMenuAlt
}
}
In your HTML
<!-- here is your button -->
<i class='bx bx-menu' id="btn" (click)="isBXMenu=!isBXMenu"
*ngClass="{'bx-menu-alt-right': bxMenuAlt, 'bx-menu': !bxMenuAlt}" ></i>
Toggle sidebar BX Menu</button>
<!-- this is the new sidebar container -->
<div *ngClass="{'bx-menu':isBXMenu}" class='sidebar'>
<!-- ... -->
</div>
I found this code as the answer of a question:
function getNodeIndex(elm){
return [...elm.parentNode.children].indexOf(elm)
}
I made something so when you click on the document, it logs the target of the click;
If the target is myClass, I want it logs the index of it.
The myClass elements are buttons, that are added when the user clicks on a button.
document.addEventListener("click", function(e) {
if(e.target.classList.value == "myClass") {
console.log(getNodeIndex(e.target))
}
})
But, that's weird:
Even if we click on 1st button, 4th button or 35th button, it will always log 2.
What's the problem there?
Thanks.
Edit:
The full code is here: http://pasted.co/6e55109a
And it is executable on http://zombs.io/
It's due to the structure of your DOM which probably looks something like
<div>
<div>Some Text: <button>Button 1</button></div>
<div>Some Text: <button>Button 2</button></div>
<div>Some Text: <button>Button 3</button></div>
</div>
Each of those buttons is the second child of its parent, i.e. one of the inner divs
Here's how to modify getNodeIndex to get it to work with DOM in this shape. If this still doesn't work, post your DOM.
function getNodeIndex(elm) {
return [...elm.parentNode.parentNode.children].indexOf(elm.parentNode)
}
$('button').on('click', e => {
console.log(getNodeIndex(e.target))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div>Some Text: <button>Button 1</button></div>
<div>Some Text: <button>Button 2</button></div>
<div>Some Text: <button>Button 3</button></div>
</div>
I don't know if your actual code is exactly the same, but the code you posted has 2 errors, you're missing 2 brackets:
/*
Yours:
document.addEventListener("click", function(e) {
if(e.target.classList.value == "myClass") {
console.log(getNodeIndex(e.target)
}
}
*/
// With the brackets
document.addEventListener("click", function(e) {
if(e.target.classList.value == "myClass") {
console.log(getNodeIndex(e.target))
}
})
I've run your code in jsbin and I had no problem, check the brackets and if you´re still having a problem please post your html
You are adding your eventListener to the document. Then you are checking for the classList. The classList may have another class and break your code. You should use classList.contains('some-class') instead.
I would add the click events directly to the 'some-class'-items you want them to be trigger by. This should work as long as you don't add more items to the DOM later. If you do, make sure to add the eventListener too.
// wait for all the html is loaded
window.addEventListener('load', () => {
// get all buttons with the .some-class
const someClassElements = document.querySelectorAll('.some-class');
// iterate over the 'array like' elements
someClassElements.forEach( element => {
// add a click event to the someClassElements
element.addEventListener('click', () => {
// log the nodeIndex
const nodeIndex = getNodeIndex(element);
console.log( nodeIndex );
});
});
}); // end on load
function getNodeIndex(elm){
return [...elm.parentNode.children].indexOf(elm)
}
div{
margin-top: 50px;
}
<div>
<button class='some-class'>some class (0)</button>
<button class='some-class'>some class (1)</button>
<button class='some-class'>some class (2)</button>
<button>no class (3)</button>
<button class='some-class'>some class (4)</button>
<button class='some-class'>some class (5)</button>
<button>no class (6)</button>
<button class='some-class'>some class (7)</button>
</div>
<div>
<button>no class (0)</button>
<button class='some-class'>some class (1)</button>
<button>no class (2)</button>
<button class='some-class'>some class (3)</button>
<button class='some-class'>some class (4)</button>
<button>no class (5)</button>
<button class='some-class'>some class (6)</button>
</div>
The actual answer in your situation:
It seems like you want to know the index of the parent div, not the actual element.
use
console.log(getNodeIndex(e.target.parentNode));
instead of
console.log(getNodeIndex(e.target));
PS: You are always getting 2 as result without your html, you may actually always be clicking the third child of the parent element. I verified that this is the case from your code.
PSII: an extra.. In the code you linked you removed a parent node of an element. Later you try to use that element to make some unsuccessful console.log's, which won't work because you just removed the element.
I want to execute a function when I'm clicking on elements in the dom with a specific class. It just doesn't work, but I'm also receiving any error. This is my
code snippet:
methods: {
initTab: function(){
document.querySelectorAll('.element').onclick = this.nextTab()
}
},
mounted: function () {
this.initTab()
}
I
I want to execute the function every time I click on the element. Would be very thankful if anybody could help me :)
There's very little need (if at all) for document.querySelectorAll() in a Vue app.
In this situation you can take advantage of delegation:
<div #click="onClick">
<!-- Clicks on any element inside this div will be handled -->
</div>
methods: {
onClick(e) {
if (e.target.classList.contains('element')) {
// Handle the click
}
}
}
Add #click="initTab($event)" to the document or template root, that allows you to track every click event on your template, that way you could put your logic to the elements which have only .element class name. If you're using it in a component you could do : <template> <div #click="initTab($event)"> ... </div> </template>
var app = new Vue({
el: '#app',
data() {
return {
}
},
methods: {
nextTab(){
console.log("You clicked on an element with class name =element")
},
initTab(event){
let targetClassNames=event.target.className.split(" ");
targetClassNames.filter(e=>{
if(e==="element"){
this.nextTab();
}
});
}
},
mounted() {
}
})
#app{
height:100px;
display:grid
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<div id="app" #click="initTab($event)">
<button class="element">1</button>
<button class="element btn">2</button>
<button class="btn">3</button>
<button class="element btn-primary">4</button>
<button class="btn elementory">5</button>
</div>
You're trying to use general javascript logic within vue. This is not often a good idea.
What I do in such cases is something like this:
<component-name #click="nextTab(tabName)"></component-name>
However, in a v-for loop you can also do something like this:
<ul v-for="tab in tabs">
<li #click="nextTab(tab)">{{tab}}</li>
</ul>
That way in methods you only need:
methods: {
nextTab: function(tab){
// whatever it is you want to do here
}
},
And you won't need mounted at all.
Conclusion: try to avoid repetition by creating components or elements (like li) that repeat - not by trying to add an event-listener to a class.