Need to add class to div on hover of another div - javascript

I have a list of div with the same class. Each div contains other divs, .header, .body, .footer. When I hover on one of the elements inside one div, for example .header, I need to add/remove a class on the another .footer element inside the same div.
The problem is when I hover one .header - I'm adding class to all .footer elements inside all other div's but I need to add new class only to the .footer inside the current div.
$(document).ready(function() {
$('.header').hover(function() {
$('.footer').addClass('active');
}, function() {
$('.footer').removeClass('active');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list">
<div class="list_item">
<div class="header"></div>
<div class="body"></div>
<div class="footer"></div>
</div>
<div class="list_item">
<div class="header"></div>
<div class="body"></div>
<div class="footer"></div>
</div>
<div class="list_item">
<div class="header"></div>
<div class="body"></div>
<div class="footer"></div>
</div>
</div>

You could use the :hover pseudo in CSS and the general sibling combinator selector ~
.list_item:hover .header:hover ~ .footer {
background: red;
}
<div class="list">
<div class="list_item">
<div class="header">Hover me</div>
<div class="body">B</div>
<div class="footer">F</div>
</div>
<div class="list_item">
<div class="header">Hover me</div>
<div class="body">B</div>
<div class="footer">F</div>
</div>
<div class="list_item">
<div class="header">Hover me</div>
<div class="body">B</div>
<div class="footer">F</div>
</div>
</div>
otherwise, if you cannot rely on .footer being a next sibling - use jQuery
jQuery(function($) {
$('.header').hover(function() {
$(this).closest('.list_item').find('.footer').toggleClass('active');
});
});
.active {
background: red;
}
<div class="list">
<div class="list_item">
<div class="header">Hover me</div>
<div class="body">B</div>
<div class="footer">F</div>
</div>
<div class="list_item">
<div class="header">Hover me</div>
<div class="body">B</div>
<div class="footer">F</div>
</div>
<div class="list_item">
<div class="header">Hover me</div>
<div class="body">B</div>
<div class="footer">F</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

You should be doing it relative to this (which is the current hovered header) and you can use nextAll if that is the only footer in the grouping:
$('.header').hover(function() {
$(this).nextAll('.footer').addClass('active');
},
function() {
$(this).nextAll('.footer').removeClass('active');
});
.active {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list">
<div class="list_item">
<div class="header"> header </div>
<div class="body"> body </div>
<div class="footer"> footer </div>
</div>
<div class="list_item">
<div class="header"> header </div>
<div class="body"> body </div>
<div class="footer"> footer </div>
</div>
<div class="list_item">
<div class="header"> header </div>
<div class="body"> body </div>
<div class="footer"> footer </div>
</div>
</div>

Yes can try below code snippet, I have tested it already.
$(document).ready(function() {
$('.header').hover(function(){
$(this).siblings(".footer").addClass('active');
},
function(){
$(this).siblings(".footer").removeClass('active');
});
});

You need to add different ID property all some div, get $('#footer3') and change it

Related

CSS selector to select first and last element under parent, when html structure is not deterministic

I have following HTML structure. Is it possible to select first and last my-item element under parent element purely by CSS?
row in which my-item element is can be wrapped in other divs and (Angular) component elements. Also component elements can be nested within each other. This is HTML structure is generated based on current page.
In JavaScript I would accomplish this by selecting all my-item elements under parent as a flat list and selecting a first and last of them.
UPDATE:
Update HTML template to more resemble my actual page content.
var parentElement = document.querySelector('.parent');
var myItems = parentElement.querySelectorAll('.my-item');
var firstItem = myItems[0];
var lastItem = myItems[myItems.length-1];
firstItem.classList.add('red-background');
lastItem.classList.add('red-background');
.red-background {
background-color: red;
}
<div class="parent">
<person-component>
<div class="template">
<div class="row">
<component-row-template>
<div class="col">
<div class="my-item">Select me!</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</component-row-template>
<component-row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
</component-row-template>
</div>
<div class="row-separator"></div>
<div class="row">
<component-row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</component-row-template>
</div>
</div>
</person-component>
<div class="row-separator"></div>
<organization-component>
<div class="template">
<div class="row">
<component-row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
</component-row-template>
</div>
<div class="row-separator"></div>
<div class="row">
<component-row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</component-row-template>
</div>
<div class="row-separator"></div>
<person-component>
<div class="template">
<div class="row">
<component-row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</component-row-template>
</div>
<div class="row">
<component-row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</component-row-template>
</div>
</div>
</person-component>
</div>
</organization-component>
<div class="row-separator"></div>
<div class="row">
<row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</row-template>
</div>
<div class="row-separator"></div>
<div class="row">
<row-template>
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Select me!</div>
</div>
</row-template>
</div>
</div>
The below code can work with the assumption that every child div of the parent has the desired ".my-item" and the every ".my-item" is inside a ".col".
It will select the first and the last div from the direct siblings of ".parent" and then will try to find the first and last ".col" and apply the rule to the ".my-item" inside them.
.parent > div:last-of-type .col:last-of-type .my-item,
.parent > div:first-of-type .col:first-of-type .my-item {
background-color: red;
}
If that's not the case and you really don't know anything about the html structure at all, then I am afraid that CSS cannot help you..
Assuming that all .my-items are always wrapped inside a .col that is in turn wrapped inside at least another div (section) and that each section has only one .row (assumption taken from your example), yes it is possible to achieve what you want using a purely CSS approach. The approach is:
Select .parent, as we're only interested only in selecting .my-item inside this element
As all .my-items always have a div container (whether it be a nested container with class section or simply inside a row container), we can specifically determine which wrapper containers are the first and last. These first and last containers, respectively, must be the container in which the first and last my-item are contained.
As all .section container only has one .row, you can easily get the first and last .col of each .section. This means that to get the first .my-item, simply select the first .col and from the first .section wrapper and apply the style to .my-item. Same logic works for your last .my-item.
Here is a minimal working example below:
let firstChild = document.querySelector('.parent > div:first-child .col:first-child .my-item')
let lastChild = document.querySelector('.parent > div:last-child .col:last-child .my-item')
console.log(firstChild, lastChild)
.parent > div:first-child .col:first-child .my-item {
background: #000;
color: #FFF;
}
.parent > div:last-child .col:last-child .my-item {
background: red;
color: #FFF;
}
<div class="parent">
<div class="main-section">
<div class="section-wrapper">
<div class="row">
<div class="col">
<div class="my-item">Select me!</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</div>
</div>
</div>
<div class="section-wrapper">
<div class="row">
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Not me</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="my-item">Not me</div>
</div>
<div class="col">
<div class="my-item">Select me!</div>
</div>
</div>
</div>
As mentioned, this code works if the above assumption is true. One easy example of when this code will break would be when there may be more that two .rows existing in one section-like wrapper.

jQuery Toggle closest info

I have the following html:
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message"></div>
</div>
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message"></div>
</div>
This is my ns.init function:
ns.init = function() {
$(".message").hide();
$(".interrogation").click(function(){
$(".interrogation").closest(".group").parent().find(".message").toggle();
});
}
The current code works but it toggles all the messages on the page when I click one of them. How can I make it toggle only the message that is exactly after the question mark ?
That is because you use $(".interrogation") selector in your function. This selects all elements with that class in the document. Use $(this) to only have the element that you clicked on as reference for your selector.
Here is a working fiddle:
$(function() {
$(".message").hide();
$(".interrogation").click(function(){
$(this).closest(".group").parent().find(".message").toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message">Message1</div>
</div>
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message">Message2</div>
</div>
Here you go with a solution https://jsfiddle.net/denquhL1/1/
$('.interrogation').click(function(){
$(this).closest('div.group').next('div.message').slideToggle();
});
.message{
display: none;
}
.interrogation {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message">Message 1</div>
</div>
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message">Message 2</div>
</div>
Onclick of .interrogation class, it will traverse to closest .group container, then it will look for next .message container.
Instead of toggle, I've used slideToggle with animation.
Hope this will help you.
Something like this?
var ns = {};
ns.init = function() {
$(".message").hide()
$(".interrogation").click(function() {
var commonParent = $(this).closest(".col-md-12");
commonParent.find(".message").toggle();
});
}
ns.init();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message">Msg 1</div>
</div>
<div class="col-md-12">
<div class="group">
<div class="label">
<li class="interrogation">?</li>
</div>
</div>
<div class="message">Msg 2</div>
</div>

Hide Parent Div if nested div is empty

I'm trying to hide the outer div when a nested div is empty (including white-space node). I've found a solution that works if there is NO whitespace:
Hide parent DIV if <li> is Empty
I need it to work when there IS white space present, ie:
<div class="gen-customer">
<div class="wrapper">
<div class="heading">Hidden if working 1</div>
<div class="content">
<div class="product"> </div>
</div>
</div>
</div>
Example fiddle
Working fiddle
You could use the both :empty and :contain() selector :
$("div.product:contains(' '), div.product:empty").closest('div.wrapper').hide();
Hope this helps.
$("div.product:contains(' '), div.product:empty").closest('div.wrapper').hide()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gen-customer">
<div class="wrapper">
<div class="heading">Hidden if working 1</div>
<div class="content">
<div class="product"> </div>
</div>
</div>
</div>
<div class="gen-customer">
<div class="wrapper">
<div class="heading">Visible if working 2</div>
<div class="content">
<div class="product">text</div>
</div>
</div>
</div>
<div class="gen-customer">
<div class="wrapper">
<div class="heading">Hidden if working 3</div>
<div class="content">
<div class="product"></div>
</div>
</div>
</div>
You can iterate over each div.product and trim the text to remove whitespace. If there's anything left, show it, otherwise, hide its wrapper.
$("div.product").each(function() {
if ($(this).text().trim() == '') {
$(this).closest('div.wrapper').hide()
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gen-customer">
<div class="wrapper">
<div class="heading">Hidden if working 1</div>
<div class="content">
<div class="product"></div>
</div>
</div>
</div>
<div class="gen-customer">
<div class="wrapper">
<div class="heading">Visible if working 2</div>
<div class="content">
<div class="product">text</div>
</div>
</div>
</div>
<div class="gen-customer">
<div class="wrapper">
<div class="heading">Hidden if working 3</div>
<div class="content">
<div class="product"></div>
</div>
</div>
</div>
//Try this using Jquery
<script>
//A perfect reference in Jquery...
var element=$('#target_child');
if($(element).html()==''){
$(element).parent().hide()
}else{
//do some work
}
</script>

Applying styles based on jquery conditions

I have a following html as follows:
<div class="outerdiv">
<div class="title">
<div class="innerdiv">
<div class="outerdiv">
<div class="title">
<div class="innerdiv">
<div class="outerdiv">
<div class="innerdiv>
<div class="outerdiv">
<div class="title">
<div class="innerdiv">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I have to apply "border-width:10px" for all divs with class = innerdiv provided that "outerdiv" contains both "title" and "innerdiv"
.
My expected output is:
<div class="outerdiv">
<div class="title">
<div class="innerdiv" style="border-width:10px">
<div class="outerdiv">
<div class="title">
<div class="innerdiv" style="border-width:10px">
<div class="outerdiv">
<div class="innerdiv>
<div class="outerdiv">
<div class="title">
<div class="innerdiv" style="border-width:10px">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I am trying this:
$(element).find(".outerdiv").not("[class="title"]).css("border-width","10px").
Edit: The number of divs are dynamic and not fixed in number
You need to use :has selector along with immediate child selector to target innerdiv element:
$('.outerdiv:has(.innerdiv):has(.title) > ,.title > .innerdiv ').css("border-width","10px");
DEMO SNIPPET :
$(function(){
$('.outerdiv:has(.innerdiv):has(.title) > .title > .innerdiv ').css("border-width","100px").css('border' ,'1px solid grey')
}) ;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="outerdiv">
<div class="title">1
<div class="innerdiv">2
<div class="outerdiv">3
<div class="title">4
<div class="innerdiv">5
<div class="outerdiv">6
<div class="innerdiv">7
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
You can do this with good css hierarchy just apply the styles to
.outerdiv > .title > .innerdiv{
css goes here
}
and they will only affect divs in the hierarchy that you mentioned.
Simply use:
$('.innerdiv').css('border-width','10px');
It will add border-width to all divs with class 'innerdiv'.

How to toggle all but selected elements in jquery

I am trying to do the following:
There are multiple "title" and "text" divs on a page.
Upon loading the page only the first text is visible.
When clicking on any title, its text slides down and all other texts slide up.
So far I came up with the following:
HTML:
<div class="row clearfix">
<div class="title"></div>
<div class="text"></div>
</div>
<div class="row clearfix">
<div class="title"></div>
<div class="text"></div>
</div>
<div class="row clearfix">
<div class="title"></div>
<div class="text"></div>
</div>
<div class="row clearfix">
<div class="title"></div>
<div class="text"></div>
</div>
jQuery:
$('.title').click(function () {
$(this).next().slideToggle();
})
https://jsfiddle.net/e3okos3e/
However, this is very basic.
Can you tell me how to select every text other than the selected title's one?
How to make only the first one visible at loading?
So, if all of the text divs are hidden by default, then do this:
$(document).ready(function(){
$('.title').click(function () {
$('.active').slideToggle().removeClass('active');
$(this).next().slideToggle().addClass('active');
})
});
.title {
width: 100px;
height: 20px;
border: 1px solid #cc0;
}
.text {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row clearfix">
<div class="title"></div>
<div class="text">text1</div>
</div>
<div class="row clearfix">
<div class="title"></div>
<div class="text">text2</div>
</div>
<div class="row clearfix">
<div class="title"></div>
<div class="text">text3</div>
</div>
<div class="row clearfix">
<div class="title"></div>
<div class="text">text4</div>
</div>
Fairly straightforward using not()
var $text = $('.text');// cache elements
$('.title').click(function () {
var $next = $(this).next().slideDown();// or slideToggle()
$text.not($next).slideUp();
});
DEMO

Categories