How to find out which parent contains an attribute? [duplicate] - javascript

This question already has answers here:
What is the pure JavaScript equivalent of jQuery's .parents() method? [duplicate]
(2 answers)
Closed 7 months ago.
A question:
How to find out which parent contains an attribute?
Example:
<div custom-attribute>
<div>
<div>
<div>
<div><p>some text</p></div>
</div>
</div>
</div>
</div>
I can't know exactly where this attribute will be applied and on which element.
I need to iterate through all the parents from the <p> element.
Without jquery

Use a while loop to iterate the parents until you find the parent that has the attribute:
const elem = document.getElementById('elem');
let parent = elem.parentElement;
while (parent && !parent.hasAttribute('custom-attribute')) {
parent = parent.parentElement;
}
if (parent) {
console.log(parent);
}
<div custom-attribute>
<div>
<div>
<div>
<div>
<p id="elem">some text</p>
</div>
</div>
</div>
</div>
</div>

const elem = document.querySelector('#elem');
const list = Array.from(document.querySelectorAll('[custom-attribute]'));
const parent = list.find(item => item.contains(elem));
// ...
If you may have not only one parent that has the custom-attribute, you'd better loop as you mentioned in question.

Related

sort div's through sort(); [duplicate]

This question already has answers here:
Easiest way to sort DOM nodes?
(9 answers)
Closed last month.
I have list and this list must be sort to a => b throught like btn (example click SORT and we have list to a -> b)
<div class = "list">
<div id = "products"> Sugar </div>
<div id = "products"> Banana </div>
<div id = "products"> Apple </div>
</div>
sorted to for button =>
<div class = "list">
<div id = "products"> Apple </div>
<div id = "products"> Banana </div>
<div id = "products"> Sugar </div>
</div>
Idk how did that with like btn :(
I tried something like that =>
// For the HTML //
<button class = 'sortBtn' onclick = 'sort()'>Sort</button>
<script>
const sort = document.quertSelector('.sortBtn');
sort.addEventListenet('click', function sort(a, b){
$parent.sort();
})
</script>
I would be grateful for help :) <3
There's a few issues in your code.
Typo: quertSelector -> querySelector
Typo: addEventListenet -> addEventListener
The repeated id in your HTML are invalid, convert them to class instead.
The function you provide to addEventListener should be anonymous in this case. Giving it a name here serves no purpose other than to waste bytes.
Avoid using inline event handlers, such as onclick, in your HTML code. It's outdated and no longer good practice. Use unobtrusive event handlers instead, such as addEventListener(), which you already use elsewhere in your code.
sort() should compare the a and b arguments and return an integer depending on which way to sort them. In this case, as you're comparing strings you can use localeCompare() on the textContent property of the elements.
After the sort() has completed you need to update the DOM to respect the new order of the elements. To do this you can call append() on the parent element, supplying the children as the argument.
Here's a working example with these issues addressed:
const sortButton = document.querySelector('.sortBtn');
const list = document.querySelector('.list');
const products = list.querySelectorAll('.products');
sortButton.addEventListener('click', () => {
const sortedElements = Array.from(products).sort((a, b) => a.textContent.localeCompare(b.textContent));
list.append(...sortedElements);
})
<div class="list">
<div class="products">Sugar</div>
<div class="products">Banana</div>
<div class="products">Apple</div>
</div>
<button type="button" class="sortBtn">Sort</button>
Convert the children of the parent element to an array. Then you can use the array sort() method to sort it, then append the children back to the parent in that order.
document.querySelector(".sortBtn").addEventListener("click", () => sortDiv(document.querySelector(".list")));
function sortDiv(parent) {
let children = [...parent.children];
children.sort((a, b) => a.innerText.localeCompare(b.innerText));
parent.innerHTML = '';
children.forEach(child => parent.appendChild(child));
}
<div class="list">
<div class="products"> Sugar </div>
<div class="products"> Banana </div>
<div class="products"> Apple </div>
</div>
<button class='sortBtn'>Sort</button>

Elements Removal in javascript [duplicate]

This question already has answers here:
removeChild() method is breaking for loop
(4 answers)
JavaScript DOM remove element
(4 answers)
Closed 2 years ago.
i want to remove specific child elements from my div element using javascript but i can't able to do that.
this is the format of element
<div class="div1">
<span class="spanp">span1<span class="spanc">spanchild1</span></span>
<span class="spanc">spanc</span>
<span class="spanp">span2<span class="spanc">spanchild2</span></span>
<span class="spanc">spanc</span>
<span class="spanp">span3<span class="spanc">spanchild3</span></span>
<span class="spanc">spanc</span>
</div>
i want to delete span elements of class="spanc" only.
how i can do it using javascript only
var list=document.getElementsByClassName("spanc");
for(var i=0;i<list.length;i++){
list[i].parentNode.removeChild(list[i]);
}
when i run this i'am able to delete only main spanc class elements and subelements of class spanp elements on odd indexs only.even index spanp class subelements are strill in list
I suppose this could do the trick:
const spanc = document.querySelectorAll('.div1 .spanc');
spanc.forEach(node => node.remove());
So part of the issue is the spans you are trying to remove have different parent elements; sometimes it's a span otherwise it's a div.
const itemsToRemove = document.getElementsByClassName('spanc');
const parents = document.getElementsByClassName('spanp');
[...parents].forEach(span => {
const itemsToRemove = span.getElementsByClassName('spanc');
[...itemsToRemove].forEach(item => span.removeChild(item));
});
const outerParent = document.getElementsByClassName('div1')[0];
const upperItemsToRemove = outerParent.getElementsByClassName('spanc');
[...upperItemsToRemove].forEach(item => outerParent.removeChild(item));
<div class="div1">
<span class="spanp">span1<span class="spanc">spanchild1</span></span>
<span class="spanc">spanc</span>
<span class="spanp">span2<span class="spanc">spanchild1</span></span>
<span class="spanc">spanc</span>
<span class="spanp">span2<span class="spanc">spanchild1</span></span>
<span class="spanc">spanc</span>
</div>
Thank you for the help i got the answer by using while loop instead of forloop
while(list.length>0){
let i=0;
list[i].parentNode.removeChild(list[i]);
}

How to add to all cloned elements an eventlistener?

I have this template:
<template id="a">
<div class="b">
<h1 class="placeholder1"></h1>
<div class="info hide">
<p class="p1"></p>
</div>
</div>
I am cloning it with:
fetch("json/countries.json").then(res => res.json()).then(list => show(list));
function show(list) {
list.forEach(function (list) {
const clone = template.cloneNode(true);
clone.querySelector(".placeholder1").textContent = list.country;
})}
I am trying to add an event listener to each cloned object, but the result is that it only adds it to the first cloned element, not the rest.
clone.querySelector(".placeholder1").addEventListener('click', fx_button1);
function fx_button1(){
document.querySelector(".info").classList.toggle("hide");
}
querySelector MDN only selects the first match found from the given selector. You need to use querySelectorAll MDN and then iterate the results.
var cloneSet = clone.querySelectorAll(".placeholder1");
for(var i = 0; i < cloneSet.length; i++){
cloneSet[i].addEventListener('click', fx_button1);
}

Get concatenated text of elements using JavaScript

I tried it with getElementById and it worked. But now I want the same with multiple div's so I have to use classes. So I changed the method to getElementsByClassName and now it says undefined.
(The function is called when a option in a select changes. This works correctly)
HTML:
<div class="item_content">
<h3 class="filmnaam">22 jump street</h3>
</div>
<div class="item_content">
<h3 class="filmnaam">rio 2</h3>
</div>
Javascript:
function sorting(sortingway) {
alert(sortingway.value);
var titelfilms = document.getElementsByClassName("filmnaam");
var titels = titelfilms.innerHTML;
console.log(titels[0]);
}
Is there a way to do this without jQuery?
getElementsByClassName returns a collection, so loop that!
var titelfilms = document.getElementsByClassName("filmnaam");
for (var i = 0; i < titelfilms.length; i++) {
var titels = titelfilms[i].innerHTML;
console.log(titels);
}
titelfilms is a node list, you can't get the innerHTML of a node list as a whole, it contains multiple references to elements which each have their own individual property.
You could loop through and concatenate each innerHTML onto a variable, or you could map() the innerHTML of your returned elements to an array and then join() them up:
function sorting(sortingway) {
var titelfilms = document.getElementsByClassName("filmnaam");
var titels = Array.prototype.map.call(titelfilms, function (el) {
return el.innerHTML;
}).join(' ');
console.log(titels);
}
sorting();
<div class="item_content">
<h3 class="filmnaam">22 jump street</h3>
</div>
<div class="item_content">
<h3 class="filmnaam">rio 2</h3>
</div>

iterate over all classes within a given class

<div class="contain_questions">
<div class="question">
<div class="question_text">First question</div>
<div class="question_mandatory">1</div>
<div class="options">
<div class="option"><div class="option_name">a</div><div class="option_value">1</div></div>
<div class="option"><div class="option_name">b</div><div class="option_value">2</div></div>
<div class="option"><div class="option_name">c</div><div class="option_value">3</div></div>
</div>
add_another_option
</div>
.
. // many more div.question ...
.
<input type="button" value="submit_questions" />
</div>
How do you use .each() for each div.option within an outer .each() for each question?
I have the outer .each() working fine, which iterates over all div.question and pushes the question_text etc into an array, however I cant seem to target the options container within each question in order to also push all of the options for each question into the array.
Also, is it possible to target a subset of the DOM with the .each() function, or is there some other way to iterate over all classes within a given class?
Thanks guys..
Just as simple as that:
$(".question").each(function() {
...
$(this).find(".option").each(function() {
...
});
});
So your code might look like the following:
var questions = [];
$(".question").each(function() {
var obj = {
name : $(this).find(".question_text").text(),
options : []
};
$(this).find(".option").each(function() {
obj.options.push({
name : $(this).find(".option_name").text(),
value : $(this).find(".option_value").text()
});
});
questions.push(obj);
});
console.log(questions);

Categories

Resources