get dataset from parent - javascript

I have the element inside this structure:
<div data-unit="5" data-id="0" id="unit-0" class="session-unit-container unit-columns">
<h1 class="unit-title">5</h1>
<div class="session-unit">
<div id="element" class="session-card" draggable="false" style="">Item 5</div> // here is the element
</div>
</div>
How can I get the data-unit="5" of the parent element when I select the element?

I don't understand what you mean by saying when I select the element. You mean when you click? When you mouse select the text?
Anyway, the way to access the value is the following:
// Here I select the element I am interested for.
let element = document.getElementById('element');
// Here I just console.log the value of the data-unit
console.log(`Here Is The data-unit Value: ${element.parentNode.parentNode.dataset.unit}`);
<div data-unit="5" data-id="0" id="unit-0" class="session-unit-container unit-columns">
<h1 class="unit-title">5</h1>
<div class="session-unit">
<div id="element" class="session-card" draggable="false" style="">Item 5</div> // here is the element
</div>
</div>

Assuming you have more than one container containing cards you can attach a listener to each container and, if the element you clicked on was a card, log the value of the data attribute.
(Note: if you do have multiple containers of cards don't give each card the same id.)
// Cache the container elements
const containers = document.querySelectorAll('.session-unit-container');
// Add listeners to them
containers.forEach(container => {
container.addEventListener('click', handleClick, false);
});
function handleClick(e) {
// Get the class list from the element that was clicked
const { classList } = e.target;
// If it's a card...
if (classList.contains('session-card')) {
// Locate the container element
const parent = e.target.closest('.session-unit-container');
// And get its unit value from the dataset
const { unit } = parent.dataset;
console.log(unit);
}
}
.session-card:hover { cursor: pointer; color: red; }
<div data-unit="2" data-id="0" id="unit-0" class="session-unit-container unit-columns">
<h3 class="unit-title">2</h3>
<div class="session-unit">
<div class="session-card" draggable="false" style="">Item 2</div>
</div>
</div>
<div data-unit="5" data-id="0" id="unit-0" class="session-unit-container unit-columns">
<h3 class="unit-title">5</h3>
<div class="session-unit">
<div class="session-card" draggable="false" style="">Item 5</div>
</div>
</div>
Additional documentation
Destructuring assignment
closest
classList
addEventListener

Related

Select the direct children of an element and apply the function to them using JavaScript

<div class='parent'>
<div class='child'>
<p>test</p>
</div>
<div class='child'>
<p>test</p>
</div>
<div>
How can I select all direct div children with parent class and execute a function on them using addEventListener?
You can use document.querySelectorAll to get all of the divs, and then add the event listeners inside a loop.
const divs = document.querySelectorAll('.parent > .child')
for (const div of divs) {
div.addEventListener('...', () => {
// ...
})
}
You only need to select the child elements. For example by using querySelectorAll.
const childs = document.querySelectorAll(".parent .child");
childs.forEach(c => c.addEventListener("click", (e) => {
alert();
}))
<p>Click of one of the tests p tags!</p>
<div class='parent'>
<div class='child'>
<p>test</p>
</div>
<div class='child'>
<p>test</p>
</div>
<div>
Use event delegation. Instead of adding listeners to many elements, add one to the parent and let it capture events from its child elements as they "bubble up" the DOM. The handler function can check what child element has been triggered, and then <do something> depending on that outcome.
In this example we're checking that the element that has been clicked on is a p element that is the child of an element with a .child class, and logging its text content.
const parent = document.querySelector('.parent');
parent.addEventListener('click', handleClick, false);
function handleClick(e) {
if (e.target.matches('.child p')) {
console.log(e.target.textContent);
}
}
p:hover { cursor: pointer; color: red; }
<div class="parent">
<div class="child">
<p>Test 1 - will be logged</p>
</div>
<div>
<p>Test 2 - will not be logged</p>
</div>
<div class="child">
<p>Test 3 - will be logged</p>
</div>
<div>
<p>Test 4 - will not be logged</p>
</div>
</div>

How to retrieve the div first child element sibling node using querySelector?

I have the DOM structure like below
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div><!-- want to access this div content -->
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
From the above HTML I want to access the div content of second div with classname table_cell inside first table_row div.
So basically I want to retrieve the content of div with classname table_cell with content chocolate products.
I have tried to do it like below
const element = document.querySelector('.rdt_TableBody');
const element1 = element.querySelectorAll('.rdt_TableRow')[0]
const element2 = element1.querySelectorAll('.rdt_TableCell')[0].innerHTML;
When I log element2 value it gives some strange output and not the text "chocolate products"
Could someone help me how to fix this. Thanks.
You can use:
the :nth-of-type pseudo-selector
combined with the immediate-child selector (>)
Example:
const selectedDiv = document.querySelector('.table_body > div:nth-of-type(1) > div:nth-of-type(2)');
Working Example:
const selectedDiv = document.querySelector('.table_body > div:nth-of-type(1) > div:nth-of-type(2)');
selectedDiv.style.color = 'white';
selectedDiv.style.backgroundColor = 'red';
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div> //want to access this div content
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
In your code
element1.querySelectorAll('.table_cell')[0], this is targeting the first element i.e., <div class="table_cell">first</div>. That's the reason why you are not getting the expected output.
I have made it to element1.querySelectorAll('.table_cell')[1], so that it'll target <div class="table_cell">chocolate products</div>.
const element = document.querySelector('.table_body');
const element1 = element.querySelectorAll('.table_row')[0]
const element2 = element1.querySelectorAll('.table_cell')[1].innerHTML;
console.log(element2);
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div>
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
Since the element that you want to target is the last div with having class table_cell, you can use :last-of-type on table_cell class using document.querySelector. But otherwise you can also use :nth-of-type if there are more than 2 elements and you want to target any element in between first and last.
Below is the example using :last-of-type.
const elem = document.querySelector(".table_row > .table_cell:last-of-type");
console.log(elem?.innerHTML);
<div class="table_body">
<div class="table_row">
<div class="table_cell">first</div>
<div class="table_cell">chocolate products</div> //want to access this div content
</div>
<div class="table_row">
<div class="table_cell">third</div>
<div class="table_cell">fourth</div>
</div>
</div>
For more info you can refer :nth-of-type, :last-of-type and child combinator(>).

How to toggle class on multiple elements with same class name on click

I can not get this code to work. I am trying to create a function that can listen to click on multiple elements with same class name, and then after click, toggle a specific class name on the next element with a specific class name.
I am trying to use a loop that loops through all the "buttons" (class="click-to-expand") and when you click a specific button, it should loop through the specific divs and toggle a class name on the next element with (class="expand").
Any help would be very appreciated!
var expandArray = document.querySelectorAll('.expand');
document.querySelectorAll('.click-to-expand').forEach(function(i) {
i.addEventListener('click', function(e) {
e.target.expandArray[0].classList.toggle("hidden");
})
});
.hidden {display: none}
<div>
<div>
<div class="click-to-expand">+</div>
</div>
</div>
<div class="expand hidden">asd</div>
<br>
<div>
<div>
<div class="click-to-expand">+</div>
</div>
</div>
<div class="expand hidden">asd</div>
<br>
<div>
<div>
<div class="click-to-expand">+</div>
</div>
</div>
<div class="expand hidden">asd</div>
You can try this
var expandArray = document.querySelectorAll('.expand');
var buttonArray = document.querySelectorAll('.click-to-expand');
document.querySelectorAll('.click-to-expand').forEach(function(i) {
i.addEventListener('click', function(e) {
const clickedBtnIndex = [...buttonArray].indexOf(e.target);
expandArray[clickedBtnIndex].classList.toggle("hidden");
})
});
The logic is to find out the index of the button which was clicked and use the same index to find the element in expandArray for which"hidden" should be toggled.

JavaScript: Use a wildcard to select all child elements from a PARENT element

I need to select ALL child elements from <div id="VidContainer"> who's ID's pattern is abc- and then a randomly generated number, followed by -container. Ej, "abc-985224562456540-container"
Because the numbers in the middle are randomly generated, a loop won't work. When the numbers have more than 10 digits, JS's engine enters into an "eternal loop" and the browser crashes.
After selecting the elemnets, I need to delete all <div found, with the matching pattern.
What would be the wildcard JavaScript needs to use to select them?
And what would be the best approach to delete those elements?
Dummy HTML:
<div id="VidContainer">
...some more html...
<div id="abc-13-container">Text 13</div>
...some more html...
<div id="abc-9999-container">Text 10</div>
...some more html...
<div id="abc-21540540640-container">Text 19</div>
...some more html...
</div>
I got most of the code. I just can't find a way to get the child element's ID (wildcard)
//Defind element ID
var elementID = "abc" + wildcard + "-container";
var parent = document.getElementById("VidContainer");
//Selet all elements to be deleted
var elements = document.getElementById(elementID);
// Removes an element from the document
while (elements.length) { parent.parentNode.removeChild(elements[0]); }
You can match both the start and end of an attribute with a CSS selector:
var items = document.querySelectorAll("#VidContainer>[id^=abc-][id$=-container]");
console.log("matching items to delete: ", items.length);
for (let item of items) item.remove();
<div id="VidContainer">
<div id="abc-13-container">Text 13</div>
<div id="abc-9999-container">Text 10</div>
<div id="hithere">Hi There</div>
<div id="abc-21540540640-container">Text 19</div>
<div id="something">Something</div>
</div>
You could use querySelectorAll() with the appropriate CSS selector. Not a wildcard solution, but still:
// arrow function to get all the elements
// that are (still) part of the DOM
const getElements = () => {
return document.querySelectorAll('#VidContainer [id^="abc-"][id$="-container"]')
}
// arrow function to DRY code removal
const remE = e => e.parentNode.removeChild(e)
// adding "self-delete on click" to all appropriate elements
getElements().forEach(e => {
e.addEventListener('click', function(e) {
remE(e.target)
})
})
// adding "delete all appropriate elements on click"
document.getElementById('clearAll').addEventListener('click', function(e) {
getElements().forEach(e => {
remE(e)
})
})
[id^='abc-'][id$='-container'] {
font-weight: 700;
cursor: pointer;
}
<div id="VidContainer">
...some more html...
<div id="abc-13-container">Text 13 - click text to remove item</div>
...some more html...
<div id="abc-9999-container">Text 10 - click text to remove item</div>
...some more html...
<div id="abc-21540540640-container">Text 19 - click text to remove item</div>
...some more html...
</div>
<button id="clearAll">Clear all</button>
This is a solution that has all the functions for correct removal (one-by-one or all at once).

find children while moving upwards in dom

This can be sound little confusing but here it is.
What i want is to find the children(OF CLASS PARENT ) when user clicks on class target.
Important: I am not aware of children class & child inside html structure.Target class can be after 'blah' like in first case OR can be directly after children like in second case.
Information available: class "PARENt" and $(this) [class target]
Find: Children(ID) of class PARENT (you cannot use class .children)
<div class="parent">
<div class="children" id="1">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
<div class="children" id="2">
<div class="target">TARGET</div>
</div>
<div class="children" id="3">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
Example:
Clicking Target 1 would produce: ID = 1
Clicking Target 2 would produce: ID = 2
Clicking Target 3 would produce: ID = 3
If you want to find only ONE ID use:
$('.target').click(function() {
var found = false;
var parent;
var previous;
while(!found) {
if (previous) {
parent = previous.parent();
} else {
parent = $(this).parent();
}
if (parent.hasClass('parent')) {
found = previous;
}
previous = parent;
}
console.log(found.attr('id'));
});
Demo.
To literally answer your question:
$(".parent *") will give you ALL of the children of .parent no matter how many layers deep
To practically answer your question:
Limit possible elements, classes, IDs, etc.
$(".parent div, .parent span, .parent .child ...etc")
You can also grab only the immediate children of an element or set of elements by using the > CSS selector:
$(".parent > *") for example, will give you ALL of the immediate children of .parent
In the context of your problem
$(".target").on("click", function () {
$(this).closest(".parent").children();
// OR
$(this).closest(".parent").find("*");
});
To get the specific ID Given your current DOM structure...
$(".target").on("click", function () {
var id = $(this).closest("[id]").attr("id");
console.log(id);
});
Use .parentsUntil() to get the set of all parents up to (but not including) .parent. Then get the last element of this to get the child of the parent.
$(".target").click(function() {
var child = $(this).parentsUntil(".parent").last();
console.log(child.attr('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="parent">
<div class="children" id="1">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
<div class="children" id="2">
<div class="target">TARGET</div>
</div>
<div class="children" id="3">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
</div>
Another

Categories

Resources