from parent to child without traversing the full path - javascript

My divs are nested like this.
<div id="top">
<div class="child1">
<div class="child-child">
<div class="child-child-child">
</div>
</div>
</div>
<div class="child2">
<div class="child-child">
<div class="child-child-child">
</div>
</div>
</div>
</div>
Right now I'm going from #top to .child-child-child by doing this.
$('#top').children('.child1')
.children('.child-child')
.children('.child-child-child');
Do I have to specify the full path like this? I want to omit the middle divs if there's a syntax that would let me do that. But I probably still need to specify whether I want to go through .child1 or .child2.

You do need to specify which path to take, but you could make it a little shorter:
$('#top > .child1').find('.child-child-child');
This will give you the '.child-child-child' that is a descendant of .child1.
Or you could write it like this, using only selectors:
$('#top > .child1 .child-child-child');
Or this, using only traversal methods:
$('#top').children('child1').find('.child-child-child');

You can just use a descendant selector (a space) to find the child anywhere beneath (as .find() does), like this:
$('#top .child-child-child');
Or, a bit more specific:
$('#top > .child1 .child-child-child');

To simplify this, you can use the selector:
$('#top .child1 .child-child-child');
This selector says "an element with a class of .child-child-child that is inside an element with a class of .child1 that's inside an element with an id of top".

Related

How to get nested DOM

How to get nested DOM.
I want to get the nested DOM by Jquery.
For example.
<div id="red">
<div id="member">A</div>
</div>
<div id="blue">
<div id="member">B</div>
</div>
<div id="yellow">
<div id="member">C</div>
</div>
Is it possible to get the each memver id like, yellow.member
I want to do like this.
$("#yellow.member").removeClass("myclass");
The way you wanted to access the child element of #yellow was real close to be correct.
$("#yellow .member").removeClass("myclass");
Notice the added space. The space means to look for another matching element in the descendant tree of the element matched by the previous selector.
Now it's your markup that is wrong. You just cannot use the same id more than once. The concept of id comes from long before the computer age... An "identification" is unique per definition!
Here is how your markup should look like... in a working example where the interval is just for fun:
$(document).ready(function(){
setInterval(function(){
$("#yellow .member").toggleClass("myclass");
},1000);
});
.myclass{
background-color:yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="red">
<div class="member">A</div>
</div>
<div id="blue">
<div class="member">B</div>
</div>
<div id="yellow">
<div class="member">C</div>
</div>
You can use nested selectors with jQuery:
$('#yellow #member').removeClass('myclass');
Removes .myclass from the #member element inside #yellow.
Also, your HTML isn't valid. You can use an ID only once per document, so change all <div id="member"> ... </div> to <div class="member"> ... </div>. Then the selector passed to jQuery changes to
$('#yellow .member')
What you're after is the .find() method.
$("#yellow").find('#member').removeClass("myclass");
Or children()
$("#yellow").children('#member').removeClass("myclass");
or
$('#yellow>#member'),removeClass("myClass");
EDIT: Also don't have duplicate id's. Use class attribute instead.

using document.querySelector with complex CSS selectors

In JavaScript I want to use document.querySelector to "grab" the last div (<div class="widget-footer">) in below HTML. However after many tries, I still can't figure out the correct CSS selector syntax to use.
The following code does not work:
document.querySelector (".skin-grid-widgets.ui-sortable.gridWidgetTemplatePositie.AgendaStandaard.disablesorting.hoogte-1-knoppen-0.breedte-1.widget-footer")
Here is the HTML I am working with
<div class="skin-grid enkeleKolom" id="Infobalk">
<div class="skin-grid-widgets ui-sortable">
<div class="gridWidgetTemplatePositie AgendaStandaard disablesorting hoogte-1-knoppen-0 breedte-1">
<div class="widget-header">
here comes the header text
</div>
<div class="widget-body">
some body text
</div>
<div class="widget-footer">
here comes the footer text
</div>
</div>
</div>
</div>
I've surfed everywhere to find example of complex CSS selectors used with querySelector, but to no avail. Any help would be really appreciated.
Your issue is you need a space in between each child element you are trying to select. If you do not have spaces in between your class selectors, by CSS specification, it will look for both classes on the same element.
Change your selector to look like the following:
var footer = document.querySelector(".skin-grid-widgets.ui-sortable .gridWidgetTemplatePositie.AgendaStandaard.disablesorting.hoogte-1-knoppen-0.breedte-1 .widget-footer");
footer.classList.add("highlight");
.highlight {
background-color: yellow;
}
<div class="skin-grid enkeleKolom" id="Infobalk">
<div class="skin-grid-widgets ui-sortable">
<div class="gridWidgetTemplatePositie AgendaStandaard disablesorting hoogte-1-knoppen-0 breedte-1">
<div class="widget-header">
here comes the header text
</div>
<div class="widget-body">
some body text
</div>
<div class="widget-footer">
here comes the footer text
</div>
</div>
</div>
</div>
try this:
<script>
document.querySelector (".skin-grid-widgets .gridWidgetTemplatePositie .widget-footer");
</script>
You don't need to add adjacent classes like "skin-grid-widgets ui-sortable" in querySelector, if you do so then query selector assumes that "skin-grid-widgets" is parent of "ui-sortable". Use just one of the classes at one DOM level.
The selector ain't complex, your thoughts are.
Listen to yourself, to the description you provide of what you want to select:
"grab" the last div in below HTML
Not grab the node with the class widget-footer inside of a node that has all these classes: gridWidgetTemplatePositie AgendaStandaard disablesorting hoogte-1-knoppen-0 breedte-1, inside a node ...
//a utility, because DRY.
//and because it's nicer to work with Arrays than with NodeLists or HTMLCollections.
function $$(selector, ctx=document){
return Array.from(ctx.querySelectorAll(selector));
}
//and the last div in this document:
var target = $$('div').pop();
or
"grab" <div class="widget-footer"> in below HTML
var target = document.querySelector("div.widget-footer");
or the combination: grab the last div.widget-footer in the HTML
var target = $$('div.widget-footer').pop();

Get the height of an item inside last container

This should be pretty simple but I can't make it work. I need the height of an item that is inside the last item with a class.
HTML like so:
<div class="tag" >
<div class="left"></div>
<div class="right"></div>
</div>
<div class="tag">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="tag">
<div class="left" id="I need this height !"></div>
<div class="right"></div>
</div>
<div class="footer"></div>
JavaScript poor attempt:
lastLeftHeight = $('.tag').last().$('.left').height();
I know that doesn't work. It's just to show what I'm trying to get .tag items can vary so I can't target a number or an ID.
try this ..
lastLeftHeight=$('.tag:last > .left').height();
you almost had it, but instead of using jquery methods, it can be accomplished with the proper query selector
$(.tag:last .left).height()
this will grab the last .tag element and find every child element with the class .left and return their heights
heres a fiddle demonstrating the selector in action:
http://jsfiddle.net/6e0s4jzj/
I would try some combination of using children(), filter(), and last() to get the height of a particular child div.
http://www.w3schools.com/jquery/jquery_traversing_filtering.asp
This explains a little more about traversing up and down the DOM using jQuery, and with examples that I would think would help.

How to find first parent element in jquery

Conside below html -
<div class="container1">
<div class="container2">
<div class="container3">
<div class="container4">
<div class="element">
...
</div>
</div>
</div>
</div>
if I want to get <div class="element"> element and I have reference to the container1. In jquery what I do is,
$(".container1").find(".element")
instead of -
$(".container1").children().children().children().find(".element")
This is process to find any child element when I have reference to any of the parent element. But instead when I have reference to a child element and want to get parent element then every time I have to go one level up -
$(".element").parent().parent().parent().parent()
and I can't do like this -
$(".element").findParent()
I have not come across any method like findParent() in jquery. Is there which I am not aware of? Or is it not there for some reason?
$(".element").parents();
will give all parents of .element(including html and body)
DEMO
To find any specific parent, suppose container1 then
$('.element').parents('.container1')
DEMO
jQuery .parents() generally find all parents, but if you passed a selector then it will search for that.
just use
$(".element").closest('#container1');
if no ancestor with that id is found then
$(".element").closest('#container1').length will be 0
To get the first parent personally I use the following construction:
var count_parents = $(".element").parents().length;
$(".element").parents().eq(count_parents - 1);
Hope, it will be helpful for someone.

What's the jquery selector for excluding nested descendents?

Per my SO question here, which has turned to jquery to solve this, but which may be worked back into YUI if I get my thinking straight, I need a selector to exclude descendents.
The solution proposed says something like this:
$( '.revealer:not(.revealer > .revealer)' );
To fit more accurately with my situation, because I have multiple HTML chunks to perform the same test on, I have updated it be:
$( '#_revealerEl_0 .handle:not(#_revealerEl_0 .reveal .handle)' );
The HTML its selecting on (image there are numerous copies of this same chunk on a page, each needing to be treated alone - an id attribute is assigned to each 'revealer'):
<div class="revealer" id="#_revealerEl_0">
<div class="hotspot">
<a class="handle" href="javascript:;">A</a>
<div class="reveal">
<p>Content A.</p>
</div>
<div class="reveal">
<p>Content B.</p>
<!-- nested revealer -->
<div class="revealer">
<div class="hotspot">
<a class="handle" href="javascript:;">A</a>
<div class="reveal">
<p>Sub-content A.</p>
</div>
<div class="reveal">
<p>Sub-content B.</p>
</div>
</div>
</div>
</div>
</div>
</div>
In a nutshell: I need to target 'top level' handles within a 'hotspot', per revealer - and no nested descendents with the same class names.
thanks,
d
EDIT:
It's also quite important that I don't start relying on descendant properties like parentNode, childNode[x], nextSibling, etc ... because currently this module is quite flexible in that its 'reveal' and 'handle' elements can reside within other markup and still be targeted - so long as they're found inside a 'hotspot'.
I don't know which is your #_revealerEl_0 element, but if it's your top-level .revealer, can't you just do this?
$('#_revealerEl_0 > .hotspot > .handle')
Or if the top-level .revealer is itself a descendant of #_revealerEl_0, then this works:
$('#_revealerEl_0 > .revealer > .hotspot > .handle')
The basic premise here is that you chain multiple > child combinators.
This works for me using jQuery:
$('.revealer:first > .hotspot > .reveal')
Given the first revealer, find any hotspots that are DIRECT children, and find any DIRECT reveal items within.
So, to assign handlers to your 'handles':
$('.handle').click(function(){
$(this).closest('.hotspot > .reveal').show();
});
The above translates to:
For any given handle, assign a click event function to the element
When a handle is clicked, find its closest parent hotspot
From the hotspot, find any reveal elements that are direct children of the hotspot
Show those elements if they were hidden with display: none.
Try this:
obj = $('.revealer[id*="revealerEl"]');
//this will give you what you are after
result = $("> .hotspot > .handle",obj)
//if you want to see them in red
$("> .hotspot > .handle",obj).css('color','red');
//or assign a click to it
$("> .hotspot > .handle",obj).click(function(){
//blah ....
})

Categories