How can I add class to parent if child contains class? - javascript

I am trying to add a class to a parent DIV if it has a child IMG element with class of "testing".
<article>
<div id="on-1" class="box">
<img src="110.jpg">
</div>
<div class="present">
<img class="testing" src="image.jpg">
</div>
</article>
I have set up if statement to check if class "testing" exists. I am having trouble adding class to the parent "article" element though.
if ($("article").find(".testing").length > 0) {
$(.this.parentNode.parentNode).addClass("hasclass");
}

Use parent() to select parent element.
$("article img.testing").parent().addClass('hasclass');
$("article img.testing").parent().addClass('hasclass');
.hasclass {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<article>
<div id="on-1" class="box">
<img src="110.jpg">
</div>
<div class="present">
<img class="testing" src="image.jpg">
</div>
</article>

$('div:has(img.testing)').addClass('hasclass');

Based on your comment on #Tushar's answer, to help elaborate on traversing up many parent nodes, I usually take the following approach:
To add a class to the direct parent div:
$('article img.testing').parent().toggleClass('new-class', true);
And to add the class to the encompassing article parent:
$('article img.testing').parents('article:first').toggleClass('new-class', true);
I also like using toggleClass() as it seems 'cleaner' to avoid any chance of adding the same class twice to an element, although I'm sure jQuery would check for this.
Hope this helps!

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.

jQuery: Select grandparent's h1 tag

I'm working within a really rigid framework (NetSuite) and there's a small section that I have direct control over which is the h3 and p text below. The structure is similar to this:
<div class="grandparent">
<h1>Title Text</h1>
<div class="otherstuff">Some text</div>
<div class="parent">
<h3>Text I have control over</h3>
<p>More text I have control over</p>
</div>
</div>
I want to hide the title text and the contents of '.otherstuff' for this page. There are multiple pages similar to this so I'm looking for a clean way of getting it done.
I've tried giving the h3 tag a class, then the following:
$('h3.myclass').parent().closest('h1').css('display','none);
and variations of that but without any luck. I've looked into the .parentUntil() function but I run into the same problem. I have no problem grabbing ancestor elements but run into trouble when trying to grab elements of those ancestors.
Can anyone help me out?
EDIT: Thank you everyone for your time and effort in answering my question. I really appreciate it!
Use closest() to traverse up to the grandparent
Use find() to select the desired elements
You can use hide() in place of css('display', 'none') as they are equivalent
var grandparent = $('.myclass').closest('.grandparent');
grandparent.find('h1, .otherstuff').hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="grandparent">
<h1>Title Text</h1>
<div class="otherstuff">Some text</div>
<div class="parent">
<h3 class="myclass">Text I have control over</h3>
<p>More text I have control over</p>
</div>
</div>
I can think of two selectors that might work assuming you put .myclass back in.
$('.myclass').closest('.grandparent').find('h1').css('display','none');
or
$('.myclass').parent().siblings('h1').css('display','none');
have direct control over which is the h3
Try utilizing .parent() , .siblings()
$("h3").parent().siblings().hide(); // `$(".parent").siblings().hide();` ?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div class="grandparent">
<h1>Title Text</h1>
<div class="otherstuff">Some text</div>
<div class="parent">
<h3>Text I have control over</h3>
<p>More text I have control over</p>
</div>
</div>
You may use:
$('.myclass').closest('.grandparent').find('>h1,>.otherstuff').hide();
> is for direct descendant element.
closest() selects ancestors, what you want is siblings().
So:
$('.your_h3_class').parent().siblings('h1')
will return an array of h1 siblings of the parent div, and in your case the first item of that array is your h1.
And you can iterate through those and hide them (in case there is ever more than one)
If the title is always immediately before the div with the "otherstuff" class, then you could use this:
$('.otherstuff').prev('h1').css('display', 'none');
Documentation here: https://api.jquery.com/prev/

JQuery closest() help

So I have several containers with this markup on a page:
<div class="box w400">
<div class="box-header">
<span class="expand-collapse">expand/collapse</span>
<h3>Heading</h3>
</div>
<div class="box-content">
<p>Some content here...</p>
</div>
</div>
And I am trying to achieve that after clicking on the .expand-collapse span, the .box-content div will slide up or down (toggle).
Here is the jQuery I'm using, I am trying to achieve this with closest():
$(document).ready(function() {
$('.expand-collapse').click(function() {
$(this).closest('.box-content').slideToggle('slow');
});
});
But it is not working for some reason :(
Try this:
$(document).ready(function() {
$('.expand-collapse').click(function() {
$(this).parent().next('.box-content').slideToggle('slow');
});
});
That selects the next sibling of the parent div, it does not make use of closest.
closest() finds the closes parent element. In your case, the span doesn't have any parent elements with class .box-content. why not just do $('.box-content').slideToggle('slow'); ??
edit: i missed the part where you have several of these on a page. the parent().next should work.

Categories