JQuery: How to get all bottom-most children in a DOM tree? - javascript

Based on the DOM tree below, I want to get all of the <p> element that are the child of every div with message as its class and put them all in an array. This will create an array of objects.
Note : ul and all of its children in all levels can be added dynamically to the dom at any given time.
How do I do that?
I have tried
var messages = $('.rightP').find('li>.message>p');
$.each(messages,function(){
console.log(this);
});
but no luck
DOM tree
<ul class="rightP">
<li>
<div class="sender">
<p>David</p>
</div>
<div class="message">
<p>Hello</p>
</div>
</li>
<li>
<div class="sender">
<p>Watson</p>
</div>
<div class="message">
<p>yes anything?</p>
</div>
<div class="message">
....
</li>
...
</ul>

You used wrong jQuery selector. Replace $('.rightP').('li>.message>p') with $('.message > p') or you could do it this way.
var messages = jQuery('.message > p');
jQuery.each(messages, function (index, elem) {
var message = jQuery(elem);
console.log(message.text())
});
Here's the working fiddle.

$('.rightP').('li>.message>p');
Wrong statement. You should try
$('.rightP').find('li>.message>p');
etc...

You can get all those like bellow
var messages = $('.rightP').find('li>.message>p');
$.each(messages,function(){
console.log(this);
});

Related

How to get node inside a node

Let's suppose I have a variable called myNode:
myNode = document.getElementsByTagName('li')[0];
Here is what myNode.outerHTML looks like:
<li>
<div class="_4ofi">
<div class="_4ofp">
<div class="_4ofr">
<div class="_2hq-">
<i class="img sp_RGPCxTkOR8i_1_5x sx_20baa4" alt=""></i>
</div>
</div>
<div class="_4ofr">
<div>My div</div>
<div class="_9079">My caption</div>
</div>
</div>
<div class="_4ofr">
<div aria-checked="false" aria-disabled="false"
class="_kx6 _kxa _4ofs" role="checkbox" tabindex="0">
</div>
</div>
</div>
</li>
I need to access the div that starts with <div aria-checked="false"> but as this div has no ID. I suppose I need to iterate through the myNode elements to find it and click on it.
So I tried this:
for (var i=0;i<myNode.length;i++) { console.log(myNode[i]); };
Somehow myNode.length returns undefined.
What am I missing?
If you use document.querySelector, you can select an element by an attribute.
document.querySelector('li div[aria-disabled="false"]')
If the classes are not going to change, you can increase the specificity of the selector. If myNode is a list of li (list items), then you can query from that node at the desired index.
myNode[i].querySelector('._4ofi ._4ofr div[aria-disabled="false"]')
Additionally, you could iterate over the result set to increase readability.
myNodes.forEach(node => myNode.querySelector('div[aria-disabled="false"]'));
Where myNodes is a collection of li elements.
I assume you cannot modify the DOM. Otherwise just set an id to the element you want to access and get it by using
document.getElementById('myId')
If you cannot touch the DOM:
myNode.length returns undefined because the returning value is not an array. It is an object. You access its child nodes by calling
myNode.childNodes
For the specific node that has the "aria-check". You can access directly with:
document.getElementsByTagName('li')[0].childNodes[1].childNodes[3].childNodes[1]
Not sure why someone would like to access a node in that way, but there you go.
var myNode = document.getElementsByTagName('li');
for (var i=0;i<myNode.length;i++) {
console.log(myNode[i].querySelector('._4ofr div[aria-disabled="false"]'));
};
try this it will give you aria-checked="false" div content, fiddle link

Remove the parent div if child div is empty

I was trying to remove the whole parent div if it doesn't have the wc-gallery class on it. What I have in my script is the reverse of what I need. Basically it hide everything that has the wc-gallery on it.
SCRIPT:
// Additional Scripts
$(window).load( function() {
$(".gallery-container2 .gallery-item .wc-gallery").hide();
});
$(".gallery-container2 p").click(function() {
var id = $(this).data('id');
$("[data-id=" + id + "].gallery-item .wc-gallery").toggle()
});
$(function(){
$(".gallery-item").each(function(){
$(this).children('.wc-gallery').parents('.gallery-container2').hide();
});
});
Basically this will work fine if I Hide all the containers and display the child div afterwards though my content won't render due to script conflicts. Only way to solve this without conflict is to load first all of the containers then hide() or remove() them.
SCRIPT: (conflict due to onload content rendering)
$('.gallery-container2').hide();
$(function(){
$(".gallery-item").each(function(){
$(this).children('.wc-gallery').parents('.gallery-container2').show();
});
});
HTML: (1st set is the one should be visible 2nd set is the one that needs to be remove or hide.)
<ul>
<li><div class="gallery-container2">
<p data-id="1723"><strong>some text</strong></p>
<div class="gallery-item" data-id="1723">
<div class="wc-gallery" style="display: none;"></div>
</div>
</div></li>
<li><div class="gallery-container2">
<p data-id="2455"><strong>View before and after</strong></p>
<strong></strong>
<div class="gallery-item" data-id="2455">
<div><div></div></div>
</div>
</div></li>
</ul>
Loop through the '.gallery-container2' element and find out whether it has '.wc-gallery' children. if not hide the element.
$('.gallery-container2').each(function(){
var $this = $(this);
//find element with 'wc-gallery' class
var hasGallery = $this.find('.wc-gallery').length > 0;
if(!hasGallery){
$this.hide();
}
});
Pure JS you might do like this in ES6 terms.
var divsToHide = document.querySelectorAll("div div :not(.wc-gallery)");
for (var div of divsToHide) div.parentElement.parentElement.style.display = "none";
<div class="gallery-container2">
<p data-id="1723"><strong>some text</strong>
</p>
<div class="gallery-item" data-id="1723">
<div class="wc-gallery">first container</div>
</div>
</div>
<div class="gallery-container2">
<p data-id="1724"><strong>some text</strong>
</p>
<div class="gallery-item" data-id="1724">
<div>
<div>second container</div>
</div>
</div>
</div>
Try this. If div has children with class .wc-gallery than it will show the parent otherwise hide the parent.
$(function () {
$(".gallery-item").each(function () {
if($(this).children('.wc-gallery').length > 0)
$(this).parents('.gallery-container2').show();
else
$(this).parents('.gallery-container2').hide();
});
});

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

jquery select parent elements sibling

Ok, lets see if I can explain this clearly enough here.
My HTML looks like
<li>
<div class="info_left" rel="snack">Fries</div>
<div class="info_right">
<span class="info_remove">[Remove]</span>
<span class="info_favorite">[Favorite]</span>
</div>
</li>
<li>
<div class="info_left" rel="lunch">Burger</div>
<div class="info_right">
<span class="info_remove">[Remove]</span>
<span class="info_favorite">[Favorite]</span>
</div>
</li>
<li>
<div class="info_left" rel="4thmeal">Taco</div>
<div class="info_right">
<span class="info_remove">[Remove]</span>
<span class="info_favorite">[Favorite]</span>
</div>
</li>
If you will note you will see a "Remove" and "Favorite" inside a div "info_right". What I need to do when either one of those 2 options is clicked on is get the rel and text values of the same li's "info_left" div. I've tried a few ways but don't think I'm nailing the combo between parent(s), siblings correctly or I dunno. Either way hoping someone can toss me a bone.
It should just be:
$('.info_remove,.info_favorite').on('click', function() {
var $left = $(this).parent().siblings('.info_left');
var rel = $left.attr('rel');
var txt = $left.text();
...
});
jsFiddle example
$(document).ready(function(){
$(".info_right span").click(function(){
$("#msg").html($(this).attr("class")+": "+$(this).parent().prev().attr("rel"));
})
})
try this
$('.info_remove,.info_favorite').click(function() {
var target_elem = $(this).parent().prev();
alert(target_elem.attr('rel'));
alert(target_elem.text());
});
fiddle : http://jsfiddle.net/ss37P/1/

how to get the right class name innerHTML content?

<div class="Name">
<div class="Image"></div>
<ul>
<li><h5><span class"myName">I want this text</span></h5></li>
<li class="description">The description</li>
</ul>
<button class="myButton">My Button</button
</div>
(multiple items with the same structure)
if my structure is constructed this way,
how can I get the class myName to have its content as a variable?
$(".myButton").click(function () {
var itemName = $(this).siblings(".myName").innerHTML ??
}
Ok, so the problem is that you have an error in you HTML. You have
<span class"myName">
instead of
<span class="myName">
and this makes all difference, because your class selector will not work property. Oh, you're also missing the ">" in the closing of button tag.
Here's the fixed HTML:
<div class="Name">
<div class="Image"></div>
<ul>
<li><h5><span class="myName">I want this text</span></h5></li>
<li class="description">The description</li>
</ul>
<button class="myButton">My Button</button>
</div>
And here's the jQuery that works with it:
$(".myButton").click(function() {
var itemName = $(this).parent().find('.myName').html();
alert(itemName);
});
You had missed the closing parenthesis as well...
I created a fiddler so you can test it: http://jsfiddle.net/juj3W/
Here is one way to get it:
$(".myButton").click(function () {
var itemName = $(this).parent().find(".myName").html();
}
var itemName = $(this).prev('ul').find('.myName').html();
try this:
$(".myButton").click(function () {
var itemName = $(".myName", $(this).parent()).text();
//find class in parent
}

Categories

Resources