const dropdownmenu = document.querySelector(".dropdownmenu")
dropdownmenu.forEach(element => {
console.log(element.classname)
});
Question is How can i get classname of element of foreach in Javascript ?
Two issues:
document.querySelector only selects one element - the first element that matches the specified selector. You should use document.querySelectorAll to grab an array of elements.
.classname should be camelcased -> .className
I'm assuming you are trying to grab the elements inside of the dropdown menu. Here's how you'd do that:
<ul class="dropdown-menu">
<li class="item">item1</li>
<li class="item">item2</li>
<li class="item">item3</li>
</ul>
<script>
const menu = document.querySelector('.dropdown-menu')
for (const elem of menu.querySelectorAll('.item')) {
console.log(elem.className);
}
</script>
If you're trying to listen for events on the dropdown menu for all of the items, try putting the event listener right on the parent and using e.target to target the clicked child.
<p>Click the items</p>
<ul class="dropdown-menu">
<li class="item">item1</li>
<li class="item">item2</li>
<li class="item">item3</li>
</ul>
<script>
const menu = document.querySelector('.dropdown-menu');
menu.addEventListener('click', (e) => {
console.log(e.target.textContent);
});
</script>
Related
Let's say my code looks like that
const menu = document.querySelector(".menu");
//now i need to select <a> tags with 'design' and 'development', but using menu element i've already selected.
//const firstLineChilds = menu.querySelector(???);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
Is it even possible to to this the 'clean way'? Or i just need to use menu.parentNode.querySelector(".menu > li > a")
You can chain querySelector and other such methods and it will search children of previous returned node: document.querySelector(".menu").querySelectorAll("a") or menu.querySelectorAll("a")
Converting the hrefs to an Array (in the snippet the spread syntax is used for that) enables you to filter them:
const relevantHrefs = [...document.querySelectorAll(".menu li a")]
.filter(href => ["Design", "Development"].find(h => href.textContent === h));
console.log(relevantHrefs);
// based on comment, this is maybe what OP needs
const menu = [...document.querySelectorAll(".menu > li:nth-child(-n+2) a")];
console.log(menu);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
Yes, you can use :scope in conjunction with child combinators, in menu.querySelectorAll():
const menu = document.querySelector(".menu")
const firstLineChilds = menu.querySelectorAll(":scope > li > a");
console.log(firstLineChilds);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
If you use descendant combinators, you'll still get the nested a elements, which is not what you want. See What does the ">" (greater-than sign) CSS selector mean?
how to remove duplicate li in div using js?
<div id="tags">
<li id="tag">sport</li>
<li id="tag">news</li>
<li id="tag">sport</li>
<li id="tag">sport</li>
<li id="tag">cars</li>
</div>
must become:
sport
news
cars
You can do that in following steps:
Select all the elements and create Set containing all the texts of <li>
Then loop through elements list using forEach
Check if the Set doesn't contain the innerHTML of current element then remove the element
If set contains the text then don't remove the element but remove the text from Set
Note: id of element should be unique in the whole document. Two elements can't have same id
const tags = [...document.querySelectorAll('#tags > li')];
const texts = new Set(tags.map(x => x.innerHTML));
tags.forEach(tag => {
if(texts.has(tag.innerHTML)){
texts.delete(tag.innerHTML);
}
else{
tag.remove()
}
})
<div id="tags">
<li>sport</li>
<li>news</li>
<li>sport</li>
<li>sport</li>
<li>cars</li>
</div>
you can just iterate over the selected node list without much overhead using one loop, like this:
let elements = document.querySelectorAll("li");
textArr = [];
elements.forEach(function(d, i) {
if(textArr.indexOf(d.innerText) > -1) {
d.remove();
}
else {
textArr.push(d.innerText);
}
});
<div id="tags">
<li id="tag">sport</li>
<li id="tag">news</li>
<li id="tag">sport</li>
<li id="tag">sport</li>
<li id="tag">cars</li>
</div>
I want to insert the (ul) tag that comes after the (div) tag in class (copy1).
Then, by clicking on the tag (div) in the class (copy1), insert the (ul) tag after the tag (div) into the class (copy2). The first step is running the code, but I don't know the second step.
$(document).ready(function() {
$('ul ul').hide();
$('ul div').click(function() {
var x = $(this).next().html();
$('.copy1').html(x);
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
<div>01</div>
<ul>
<li>01-01</li>
<li>
<div>01-02</div>
<ul>
<li>01-02-01</li>
<li>01-02-02</li>
<li>01-02-03</li>
</ul>
</li>
<li>01-03</li>
</ul>
</li>
<li>
<div>02</div>
<ul>
<li>02-01</li>
<li>02-02</li>
<li>02-03</li>
</ul>
</li>
</ul>
<hr>
<ul class="copy1"></ul>
<ul class="copy2"></ul>
After clicking on the first div tag, the following values are inserted into the copy1 class.
01-01
01-02
01-03
But by clicking on 01-02 the following values
01-02-01
01-02-02
01-02-03
Those that are in the copy1 class are not copied to the Copy2 class.
Because the elements in .copy1 are created dynamically, you either need to add events after they are created or use event delegation
$(document).on("click", ".copy1 div", function() { ...
as you want copy1->copy2, it needs to be separate from the src->copy1 code (or have additional logic within the click handler).
In the snippet below, I've kept them separate for clarity. I've also added some css to show which ones can be clicked as it was slightly confusing that 01-01 does nothing as there are no child nodes.
$(document).ready(function() {
$('ul ul').hide();
$('ul div').click(function() {
var x = $(this).next().html();
$('.copy1').html(x);
})
$(document).on("click", ".copy1 div", function() {
var x = $(this).next().html();
$('.copy2').html(x);
});
});
ul div { color: red }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
<div>01</div>
<ul>
<li>01-01</li>
<li>
<div>01-02</div>
<ul>
<li>01-02-01</li>
<li>01-02-02</li>
<li>01-02-03</li>
</ul>
</li>
<li>01-03</li>
</ul>
</li>
<li>
<div>02</div>
<ul>
<li>02-01</li>
<li>02-02</li>
<li>02-03</li>
</ul>
</li>
</ul>
<hr>
<ul class="copy1"></ul>
<ul class="copy2"></ul>
I have a list of <li> tags inside a <ul> , I have a javascript function that add 'active' class to one of them when clicked and remove it from its siblings , I want to implement this to all except the last <li>
<ul class='tabs'>
<li>Home</li>
<li>About</li>
<li>Contact</li>
<li>
<form>
<input type='text'/>
<button></button>
</form>
</li>
</ul>
The JS function:
[].forEach.call(document.querySelectorAll('.tabs li'), function(ele) {
ele.addEventListener('click', function(e) {
if(ele.nextSibling){
document.querySelector(".tabs li.active").classList.remove("active");
ele.classList.add("active");
}
});
});
You can use the slice method.
const listItems = Array.from(document.querySelectorAll('.tabs li'));
const selectableListItems = listItems.slice(0, -1);
selectableListItems.forEach(function(ele) {
ele.addEventListener('click', function(e) {
if(ele.nextSibling){
document.querySelector(".tabs li.active").classList.remove("active");
ele.classList.add("active");
}
});
});
Or adjust your query selector using a pseudo-class in order to select all items except the last one:
document.querySelectorAll('.tabs li:not(:last-child)');
I want add class to clicked li and delete other li class
<ul>
<li onclick="s()"><span>خانه</span></li>
<li onclick="s()"><span>سفارش</span></li>
<li onclick="s()" class="selected"><span>آپلود</span></li>
<li onclick="s()"><span>درباره ما</span></li>
<li onclick="s()"><span>تنظیمات</span></li>
</ul>
I can do it with jquery but now i want do this with javascript?
Don't use inline click handlers. Instead, attach a handler from JavaScript.
<ul id="myUL"> <!-- This is just for example, to make it easier to select -->
<li><span>خانه</span></li>
<li><span>سفارش</span></li>
<li class="selected"><span>آپلود</span></li>
<li><span>درباره ما</span></li>
<li><span>تنظیمات</span></li>
</ul>
Then, in JavaScript:
var myUL = document.querySelector('#myUL');
// Attach one event listener on the parent, instead of one for each element.
// It's more performant and will work with dynamically added entries!
myUL.addEventListener('click', function(event) {
// Here, event.target is the actual event clicked.
// Remove class from selected one.
document.querySelector('#myUL .selected').classList.remove('selected');
// And add it to the current one
event.target.classList.add('selected');
});
Working Example
This is a quick fix and this way is not recommended. But in your case, you need to use this way:
function s (which) {
document.querySelectorAll(".clicked")[0].classList.remove("selected");
which.classList.add("selected");
}
And change the call this way:
<ul>
<li onclick="s(this)"><span>خانه</span></li>
<li onclick="s(this)"><span>سفارش</span></li>
<li onclick="s(this)" class="selected"><span>آپلود</span></li>
<li onclick="s(this)"><span>درباره ما</span></li>
<li onclick="s(this)"><span>تنظیمات</span></li>
</ul>
The right way is to use eventListeners and bind the events to an ID.
var list = document.querySelector('#menu');
list.addEventListener('click', function(event) {
list.querySelector('.selected').classList.remove('selected');
event.target.classList.add('selected');
});
And add the ID to the <ul>:
<ul id="menu">
<li>خانه</li>
<li>سفارش</li>
<li class="selected">آپلود</li>
<li>درباره ما</li>
<li>تنظیمات</li>
</ul>