Div onclick inner content not clickable? - html

When I click on div-two I want to show div-2. I'm using Jquery index and it works but when I put other content/html inside the on-click div it always shows div-1 regardless of what button is clicked. On the following fiddle example if you click the green inner div you'll see the results.
I'm assuming this is an index or propagation issue, can this be corrected or am I pushing the limits of the function?
https://jsfiddle.net/1e230w8s/
// Matches and shows Butts to index order.
let $games = $('.game');
$('.butts').on('click', e => {
let $target = $games.eq($(e.target).index()).show();
$games.not($target).hide();
});
// Finds all Butts and calls `sumBoxes` onclick
const boxes = document.getElementsByClassName("butts");
for (let butts of boxes){ butts.addEventListener("click", sumBoxes); }
// sumBox Calculates each visible Box
function sumBoxes(event) {
var total = 0;
$('.box:visible').each(function() {
total += parseInt($(this).text());
});
$('.sum').html("Total : " + total); // Replaces contents of `.sum`
}
body {background: #eeeeee;}
.game {display:none;}
.box {float: left;font: bold 17px arial;text-align: center;margin: 10px 10px 20px 0;padding: 10px 25.54px;background: #fff;color: blue}
.butts {cursor:pointer; width:200px;height:40px;background:#fff; margin-bottom:10px; margin-right:10px; float:left;border:1px solid blue;}
.sum {clear:both;margin-top:40px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" style="float: left;width: 100%;">
<div class="butts">1 <div style="float:right;width:40px;height:20px;background:lightgreen;">1</div></div>
<div class="butts">2 <div style="float:right;width:40px;height:20px;background:lightgreen;">2</div></div>
<div class="butts">3 <div style="float:right;width:40px;height:20px;background:lightgreen;">3</div></div>
</div>
<div class="container">
<div class="game">
<div class="box">1 Box</div>
</div>
<div class="game">
<div class="box">2 Box</div>
</div>
<div class="game">
<div class="box">3 Box</div>
</div>
</div>
<div class="sum"></div>

In your current code you have use e.target so when you click on children div current target will be inner div tag and according to your code its value will be 0 that's why only first one is showing .Instead you can check if the e.target has butts class or not depending on this change your selector.
Demo Code :
// Matches and shows Butts to index order.
let $games = $('.game');
$('.butts').on('click', e => {
//check is target has class .butts
var target = $(e.target).hasClass("butts") ? $(e.target) : $(e.target).closest(".butts")
let $target = $games.eq(target.index()).show();
$games.not($target).hide();
});
body {
background: #eeeeee;
}
.game {
display: none;
}
.box {
float: left;
font: bold 17px arial;
text-align: center;
margin: 10px 10px 20px 0;
padding: 10px 25.54px;
background: #fff;
color: blue
}
.butts {
cursor: pointer;
width: 200px;
height: 40px;
background: #fff;
margin-bottom: 10px;
margin-right: 10px;
float: left;
border: 1px solid blue;
}
.sum {
clear: both;
margin-top: 40px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" style="float: left;width: 100%;">
<div class="butts">1
<div style="float:right;width:40px;height:20px;background:lightgreen;">1</div>
</div>
<div class="butts">2
<div style="float:right;width:40px;height:20px;background:lightgreen;">2</div>
</div>
<div class="butts">3
<div style="float:right;width:40px;height:20px;background:lightgreen;">3</div>
</div>
</div>
<div class="container">
<div class="game">
<div class="box">1 Box</div>
</div>
<div class="game">
<div class="box">2 Box</div>
</div>
<div class="game">
<div class="box">3 Box</div>
</div>
</div>
<div class="sum"></div>

Related

How to make my button only show the div on its group when I click it

Currently when I click the 1st button both hidden divs are showing. My goal is when I click the 1st button it only shows the hidden div on its group. And if I click the 2nd button it only shows the hidden div on its group.
Can anyone help me with how to achieve it?
$(document).ready(function () {
$(".btn").on("click", function () {
$(".hidden").addClass("active");
});
$(".closed").on("click", function (){
$(".hidden").removeClass("active")
})
})
.btn {
background: blue;
color: #ffffff;
font-weight: 600;
padding: 20px;
}
.hidden {
width: 100px;
height: 100px;
background: yellow;
display: none;
}
.hidden.active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="con">
<div class="btn">Show</div>
<div class="hidden">
<div class="closed">Click to hide</div>
</div>
</div>
</div>
<br>
<div class="container">
<div class="con">
<div class="btn">Show</div>
<div class="hidden">
<div class="closed">Click to hide</div>
</div>
</div>
</div>
Your code
$(".hidden").addClass("active");
selects all .hidden elements (hence your issue).
Within the click event you need to use this to refer to the element being clicked and then use relative DOM navigation to find the element you do want.
In your case it's the next sibling, so .next() will suffice for show, but hide/close will need to find its parent .hidden
$(document).ready(function () {
$(".show").on("click", function () {
$(this).next().addClass("active");
});
$(".close").on("click", function (){
$(this).closest(".hidden").removeClass("active")
})
})
.show {
background: blue;
color: #ffffff;
font-weight: 600;
padding: 20px;
}
.hidden {
width: 100px;
height: 100px;
background: yellow;
display: none;
}
.hidden.active {
display: block;
}
.close { background-color:#ccc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="con">
<div class="show">Show</div>
<div class="hidden">
<div class="close">Click to hide</div>
</div>
</div>
</div>
<br>
<div class="container">
<div class="con">
<div class="show">Show</div>
<div class="hidden">
<div class="close">Click to hide</div>
</div>
</div>
</div>

Move 2 toggles switches at same time

I have 2 pricing plan boxes with toggles for monthly and annual pricing. When i click Pay monthly on the Core box, all the numbers change correctly, but what i would like to do is to click either core or pro, and then both move. At the moment, only the Core toggle moves. See the code below, and link to the demo on my staging site.
jQuery
$(document).ready(function() {
var checkBoxes = $("input[name='toggle']");
toggle();
$("#toggle").click(function() {
toggle();
});
function toggle() {
if (checkBoxes.prop("checked")) {
$('#coreMonthlyText,#coreMonthlyPrice,#proMonthlyText,#proMonthlyPrice').show();
$('#coreAnnuallyText,#coreAnnuallyPrice,#proAnnuallyText,#proAnnuallyPrice').hide();
} else {
$('#coreMonthlyText,#coreMonthlyPrice,#proMonthlyText,#proMonthlyPrice').hide();
$('#coreAnnuallyText,#coreAnnuallyPrice,#proAnnuallyText,#proAnnuallyPrice').show();
}
}
});
HTML
<div class="pricing-box" id="core-box">
<div class="row">
<div class="column">
<div class="core">
<h2>Core Plan</h2>
</div>
</div>
<div class="column">
<div id="coreAnnuallyPrice" class="coreAnnuallyPrice">
<h2>$2,399/yr</h2> Normally $3,588/yr
</div>
<div id="coreMonthlyPrice" class="coreMonthlyPrice">
<h2>$99/pm</h2> first 2 months free
</div>
</div>
</div><div class="center_text">
<label for="toggle" class="toggle-switch"><input class="toggle-button" id="toggle" type="checkbox" name="toggle" data-checked="coreAnnuallyPrice,coreAnnuallyText" data-not-checked="coreMonthlyPrice,coreMonthlyText"><span>Pay annually</span><span>Pay monthly</span>
</label>
</div></div>
<div class="pricing-box" id="pro-box">
<div class="row">
<div class="column">
<div class="pro">
<h2>Pro Plan</h2>
</div>
</div>
<div class="column">
<div id="proAnnuallyPrice" class="proAnnuallyPrice">
<h2>$4,199/yr</h2> Normally $5,988/yr
</div>
<div id="proMonthlyPrice" class="proMonthlyPrice">
<h2>$299/pm</h2> first 2 months free
</div>
</div>
</div><div class="center_text">
<label for="toggle" class="toggle-switch"><input class="toggle-button" id="toggle" type="checkbox" name="toggle" data-checked="proAnnuallyPrice,proAnnuallyText" data-not-checked="proMonthlyPrice,proMonthlyText"><span>Pay annually</span>.
<span>Pay monthly</span>
</label>
</div>
</div>
CSS
.toggle-switch {
cursor: pointer;
background-color: #F8F8F9;
display: inline-block;
border: 0;
padding-left: 0;
padding-right: 0;
}
.toggle-switch input {
display: none;
}
.toggle-switch,
.toggle-switch span {
border-radius: 35px;
border-style: solid;
border-color: transparent;
padding-top: 20px;
padding-bottom: 20px;
}
.toggle-switch span {
border-width: 2px;
padding-left: 20px;
padding-right: 20px;
}
.toggle-switch input:checked+span+span,
.toggle-switch input+span {
border: 1px solid #00AEEF !important;
background-color: white !important;
}
.toggle-switch input+span+span,
.toggle-switch input:checked+span {
background-color: #F8F8F9 !important;
border-color: transparent !important;
}
#coreMonthlyText,
#coreMonthlyPrice,
#coreAnnuallyText,
#coreAnnuallyPrice {
display: none;
}
#proMonthlyText,
#proMonthlyPrice,
#proAnnuallyText,
#proAnnuallyPrice {
display: none;
}
Link to webpage
You have duplicate IDs, which will cause problems. You can have duplicate name="toggle" but you likely need to distinguish them somehow.
The main problem is that the state of the toggle changes automatically and you never set the state of the other. It is important to know which one was clicked.
Hence, to keep them "in sync", you can set both toggles to the state of the one that was clicked:
$(document).ready(function() {
var checkBoxes = $("input[name='toggle']");
toggle(checkBoxes.el(0)); // pass first checkbox for initial state
checkBoxes.click(function(event) {
toggle(event.target);
});
function toggle(target) {
var checked = $(target).prop('checked')
// set all checkboxes to the same state
checkBoxes.prop('checked', checked)
// set other properties based on checked state
$('#coreMonthlyText,#coreMonthlyPrice,#proMonthlyText,#proMonthlyPrice')
.toggle(checked)
$('#coreAnnuallyText,#coreAnnuallyPrice,#proAnnuallyText,#proAnnuallyPrice')
.toggle(!checked)
}
});

Stuck in jQuery down arrow icon

Hey Everyone,
i am trying to change the plus text symbol to arrow icon in jQuery am tried but not
working for me, is there by chance we can change that plus to arrow icon.
I hope anyone could help me this out, i trying to create some jQuery toggle animations.
Thanks
$(document).ready(function() {
$(".accordion_head").click(function() {
if ($('.accordion_body').is(':visible')) {
$(".accordion_body").slideUp(300);
$(".plusminus").text('+');
}
if ($(this).next(".accordion_body").is(':visible')) {
$(this).next(".accordion_body").slideUp(300);
$(this).children(".plusminus").text('+');
} else {
$(this).next(".accordion_body").slideDown(300);
$(this).children(".plusminus").text('-');
}
});
});
.accordion_head {
/* background-color: skyblue; */
color: #1D5AA6;
cursor: pointer;
border-bottom: 1px solid #f3f3f3;
padding: 2rem;
}
.accordion_body {
background: lightgray;
}
.accordion_body p {
padding: 18px 5px;
margin: 0px;
}
.plusminus {
float: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="accordion_container">
<h3 class="accordion_head">
First Accordian Body, it will have Header
<span class="plusminus">+</span></h3>
<div class="accordion_body" style="display: none;">
<p>First Accordian Body, it will have description</p>
</div>
<div class="accordion_head">Second Accordian Head<span class="plusminus">+</span></div>
<div class="accordion_body" style="display: none;">
<p>Second Accordian Body, it will have description</p>
</div>
<div class="accordion_head">Third Accordian Head<span class="plusminus">+</span></div>
<div class="accordion_body" style="display: none;">
<p>Third Accordian Body, it will have description</p>
</div>
</div>
use font awesome icon or material icon or use some other icons to achieve this. Here I used fa icons to achieve this
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
and slightly modified jquery.
use $(".plusminus > i").removeClass('fa-angle-up').addClass('fa-angle-down'); instead of
$(this).children(".plusminus").text('+');
and use $(this).find(".plusminus > i").removeClass('fa-angle-down').addClass('fa-angle-up'); instead of $(this).children(".plusminus").text('-');
$(document).ready(function() {
$(".accordion_head").click(function() {
if ($('.accordion_body').is(':visible')) {
$(".accordion_body").slideUp(300);
$(".plusminus > i").removeClass('fa-angle-up').addClass('fa-angle-down');
}
if ($(this).next(".accordion_body").is(':visible')) {
$(this).next(".accordion_body").slideUp(300);
$(this).find(".plusminus > i").removeClass('fa-angle-up').addClass('fa-angle-down');
} else {
$(this).next(".accordion_body").slideDown(300);
$(this).find(".plusminus > i").removeClass('fa-angle-down').addClass('fa-angle-up');
}
});
});
.accordion_head {
/* background-color: skyblue; */
color: #1D5AA6;
cursor: pointer;
border-bottom: 1px solid #f3f3f3;
padding: 2rem;
}
.accordion_body {
background: lightgray;
}
.accordion_body p {
padding: 18px 5px;
margin: 0px;
}
.plusminus {
float: right;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="accordion_container">
<h3 class="accordion_head">
First Accordian Body, it will have Header
<span class="plusminus"><i class='fa fa-angle-up' style='font-size:36px'></i></span></h3>
<div class="accordion_body" >
<p>First Accordian Body, it will have description</p>
</div>
<div class="accordion_head">Second Accordian Head<span class="plusminus"><i class='fa fa-angle-down' style='font-size:36px'></i></span></div>
<div class="accordion_body" style="display: none;">
<p>Second Accordian Body, it will have description</p>
</div>
<div class="accordion_head">Third Accordian Head<span class="plusminus"><i class='fa fa-angle-down' style='font-size:36px'></i></span></div>
<div class="accordion_body" style="display: none;">
<p>Third Accordian Body, it will have description</p>
</div>
</div>

Center align two divs in the same row

I have a JavaScript script that basically hides a box upon clicking the top two boxes. Upon clicking one of the boxes on top, one of the boxes on the bottom hides. How do I make the two boxes on the bottom stay centered?
Here is the landing page:
I want the divs on the bottom centered, once a box is hidden. I want the SharePoint and Teams boxes centered after the other box is hidden.
Center the bottom two div's after change ^
Code:
.margin-bottom-20 {
margin-bottom: 20px;
}
.collabProjects:hover, .collabFiles:hover, .collabSocially:hover {
box-shadow: 0 0 15px rgba(33,3,3,.2);
}
.decisionTreeBox {
background-color: #4B92DB;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
transition: box-shadow .3s;
}
#decisionTreeOneDrive {
background-color: #094AB2;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
}
#decisionTreeSharePoint {
background-color: #008CE7;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
}
#decisionTreeTeams {
background-color: #4A1EBD;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
}
#innerBoxHeadings {
color: white!important;
text-align: center;
padding-top: 5px;
}
#columnMiddleBorderLeft, #pageTitle {
display:none!important;
}
<div class="outer-container">
<div class="row">
<div class="col-md-6" style="text-align: center;">
<div data-collaborate="shareCollab" class="decisionTreeBox" style="font-size: x-large; float: right;">
Share and Collaborate</div>
</div>
<div class="col-md-6" style="text-align: center;">
<div data-collaborate="shareExternally" class="decisionTreeBox" style="font-size: x-large;">
Share Externally</div>
</div>
</div>
<hr />
<div class="container" style="padding: 0px;">
<div class="row">
<a href="/TrainingResourceCenter/O365Training/Pages/OneDrive.aspx">
<div class="col-md-4 margin-bottom-20" style="text-align: center;">
<div data-decision="shareExternally" id="decisionTreeOneDrive">
<h3 id="innerBoxHeadings"><img src="/TrainingResourceCenter/O365Training/PublishingImages/onedrive-logo.png" style="width: 65px; height: 65px; padding-bottom: 5px; padding-right: 10px; vertical-align: middle;" />OneDrive</h3>
</div>
</div>
</a>
<a href="/TrainingResourceCenter/O365Training/Pages/SharePointOnline.aspx">
<div class="col-md-4 margin-bottom-20" style="text-align: center;">
<div data-decision="shareCollab shareExternally" id="decisionTreeSharePoint">
<h3 id="innerBoxHeadings"><img src="/TrainingResourceCenter/O365Training/PublishingImages/SharePointDecisionTree.png" style="padding-bottom: 5px; padding-right: 10px; vertical-align: middle;" />SharePoint</h3>
</div>
</div>
</a>
<a href="/TrainingResourceCenter/O365Training/Pages/Teams.aspx">
<div class="col-md-4 margin-bottom-20" style="text-align: center;">
<div data-decision="shareCollab" id="decisionTreeTeams">
<h3 id="innerBoxHeadings"><img src="/TrainingResourceCenter/O365Training/PublishingImages/TeamsDecisionTree.png" style="padding-bottom: 5px; padding-right: 10px; vertical-align: middle;" />Teams</h3>
</div>
</div>
</a>
</div>
</div>
</div>
<script>
function projectCollab() {
var divsToCange = document.querySelectorAll('[data-decision]'),
attr = this.getAttribute('data-collaborate');
for (var i = 0; i < divsToCange.length; i++) {
var d = divsToCange[i];
if (d.getAttribute('data-decision').includes(attr)) { /* Had: == attr) { */
d.parentNode.style.display = 'block';
} else {
d.parentNode.style.display = 'none';
}
}
return false;
}
var divButtons = document.querySelectorAll('[data-collaborate]');
for (var i = 0; i < divButtons.length; i++) {
divButtons[i].addEventListener('click', projectCollab);
}
</script>
There's an old technique of centering the content of the parent, then making the children display: inline-block;. You will have to account for the visibility of the white-space " " character — but that is pretty well documented (e.g. Remove Whitespace Between Inline-Block Elements). You'll have to play with margin to restore your spacing, AND remember to change the JS to reflect inline-block instead of block when restoring the elements.
In the interest of selector sanity, I added an example class to the containing row element in the code demo.
HTML
<div class="row centered-buttons">
CSS
.centered-buttons {
text-align: center;
}
.centered-buttons a {
display: inline-block;
vertical-align: middle;
}
.margin-bottom-20 {
margin-bottom: 20px;
}
.collabProjects:hover,
.collabFiles:hover,
.collabSocially:hover {
box-shadow: 0 0 15px rgba(33, 3, 3, .2);
}
.decisionTreeBox {
background-color: #4B92DB;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
transition: box-shadow .3s;
}
#decisionTreeOneDrive {
background-color: #094AB2;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
}
#decisionTreeSharePoint {
background-color: #008CE7;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
}
#decisionTreeTeams {
background-color: #4A1EBD;
color: white;
width: 300px;
height: 140px;
display: flex;
justify-content: center;
align-items: center;
}
#innerBoxHeadings {
color: white!important;
text-align: center;
padding-top: 5px;
}
#columnMiddleBorderLeft,
#pageTitle {
display: none!important;
}
.centered-buttons {
text-align: center;
}
.centered-buttons a {
display: inline-block;
vertical-align: middle;
}
<div class="outer-container">
<div class="row">
<div class="col-md-6" style="text-align: center;">
<div data-collaborate="shareCollab" class="decisionTreeBox" style="font-size: x-large; float: right;">
Share and Collaborate</div>
</div>
<div class="col-md-6" style="text-align: center;">
<div data-collaborate="shareExternally" class="decisionTreeBox" style="font-size: x-large;">
Share Externally</div>
</div>
</div>
<hr />
<div class="container" style="padding: 0px;">
<div class="row centered-buttons">
<a href="/TrainingResourceCenter/O365Training/Pages/OneDrive.aspx">
<div class="col-md-4 margin-bottom-20" style="text-align: center;">
<div data-decision="shareExternally" id="decisionTreeOneDrive">
<h3 id="innerBoxHeadings"><img src="/TrainingResourceCenter/O365Training/PublishingImages/onedrive-logo.png" style="width: 65px; height: 65px; padding-bottom: 5px; padding-right: 10px; vertical-align: middle;" />OneDrive</h3>
</div>
</div>
</a>
<a href="/TrainingResourceCenter/O365Training/Pages/SharePointOnline.aspx">
<div class="col-md-4 margin-bottom-20" style="text-align: center;">
<div data-decision="shareCollab shareExternally" id="decisionTreeSharePoint">
<h3 id="innerBoxHeadings"><img src="/TrainingResourceCenter/O365Training/PublishingImages/SharePointDecisionTree.png" style="padding-bottom: 5px; padding-right: 10px; vertical-align: middle;" />SharePoint</h3>
</div>
</div>
</a>
<a href="/TrainingResourceCenter/O365Training/Pages/Teams.aspx">
<div class="col-md-4 margin-bottom-20" style="text-align: center;">
<div data-decision="shareCollab" id="decisionTreeTeams">
<h3 id="innerBoxHeadings"><img src="/TrainingResourceCenter/O365Training/PublishingImages/TeamsDecisionTree.png" style="padding-bottom: 5px; padding-right: 10px; vertical-align: middle;" />Teams</h3>
</div>
</div>
</a>
</div>
</div>
</div>
<script>
function projectCollab() {
var divsToCange = document.querySelectorAll('[data-decision]'),
attr = this.getAttribute('data-collaborate');
for (var i = 0; i < divsToCange.length; i++) {
var d = divsToCange[i];
if (d.getAttribute('data-decision').includes(attr)) { /* Had: == attr) { */
d.parentNode.style.display = 'block';
} else {
d.parentNode.style.display = 'none';
}
}
return false;
}
var divButtons = document.querySelectorAll('[data-collaborate]');
for (var i = 0; i < divButtons.length; i++) {
divButtons[i].addEventListener('click', projectCollab);
}
</script>
In cases like this, I usually conditionally set the class of the content that changes depending on how many items are present. For example, imagine you're checking an array called items that is either 2 or 3 items long. Here is some pseudocode that shows you what I'm thinking.
let itemsClass;
if (items.length === 2) {
itemsClass = 'col-md-6';
} else {
itemsClass = 'col-md-4';
}
myElement.setClass(itemsClass);
You could set a click handler that would check after you click a button or whatever. In react, that could be part of your component render() method.
I don't know what you're using for JS so I won't try to write your code for you. But the gist of it is, decide the class name on the fly with JS and apply it to your elements.
edit: Sorry, I didn't read your entire code snippet. This is something you could add to the handler you already have. You'd just have to grab the elements and alter the classes at that time.
Add the following CSS to the row class:
<div class="container" style="padding: 0px;">
<div class="row" style="justify-content: center">
Since bootstrap uses flexbox system, this should work for you.
What you are asking for is built into BS. But you've muddied the framework by adding html where it ought not be. specifically wrapping BS cols with an anchor tag which breaks the BS grid system, specifically the rule that states only cols can be children of rows.
I've made your html substantially shorter for simplicity and altered your js somewhat to showcase the hiding part. I hope this a decent example that you can expand upon.
FIXES:
I've moved the anchor tab inside the col. This was breaking the alignment of the BS Grid And is also incorrect markup per the BS grid system.
I altered your JS to hide the col, not the anchor. This allows the BS flex grid to properly do it's alignment
In the javascript, consider adding a attribute to your markup such that you don't have to navigate the right number of parent levels. As it stands, if you add more layers to the col html, your JS will break.
function projectCollab() {
var divsToChange = document.querySelectorAll('[data-decision]'),
attr = this.getAttribute('data-collaborate');
for (var i = 0; i < divsToChange.length; i++) {
var d = divsToChange[i];
d.parentNode.parentNode.hidden = ! d.getAttribute('data-decision').includes(attr);
}
return false;
}
var divButtons = document.querySelectorAll('[data-collaborate]');
for (var i = 0; i < divButtons.length; i++) {
divButtons[i].addEventListener('click', projectCollab);
}
.collabProjects:hover,
.collabFiles:hover,
.collabSocially:hover {
box-shadow: 0 0 15px rgba(33, 3, 3, .2);
}
div[data-decision],
div[data-collaborate]{
color: white;
width: 200px;
height: 100px;
}
.decisionTreeBox {
background-color: #4B92DB;
}
#decisionTreeOneDrive {
background-color: #094AB2;
}
#decisionTreeSharePoint {
background-color: #008CE7;
}
#decisionTreeTeams {
background-color: #4A1EBD;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<div class="outer-container">
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-4">
<div data-collaborate="shareCollab" class="decisionTreeBox">
Share and Collaborate</div>
</div>
<div class="col-4">
<div data-collaborate="shareExternally" class="decisionTreeBox">
Share Externally</div>
</div>
</div>
<hr />
<div class="row justify-content-center">
<div class="col-4">
<a href="#">
<div data-decision="shareExternally" id="decisionTreeOneDrive">
<h3 id="innerBoxHeadings">OneDrive</h3>
</div>
</a>
</div>
<div class="col-4">
<a href="#">
<div data-decision="shareCollab shareExternally" id="decisionTreeSharePoint">
<h3 id="innerBoxHeadings">SharePoint</h3>
</div>
</a>
</div>
<div class="col-4">
<a href="#">
<div data-decision="shareCollab" id="decisionTreeTeams">
<h3 id="innerBoxHeadings">Teams</h3>
</div>
</a>
</div>
</div>
</div>
</div>

Using CSS, how to modify a child element by its class without impacting another child element with the same class but slightly different parent

Using CSS, how to modify a child element by its class without impacting another child element with the same class but slightly different parent.
For example, in my example below:
<div class="PQR">
<div class="ABC>
<div class = "XYZ"> </div>
</div>
<div class="DEF ABC">
<div class = "XYZ"> </div>
</div>
</div>
My requirement is that I want to reduce the width by 50% of only first XYZ without impacting the other XYZ
The below statement impacts both the sections as both XYZ class have at least one of their parent class as ABC.
.ABC .XYZ{width:50%}
I tried the below 2 options but they did not work:
.ABC .XYZ:not(.DEF > .XYZ) {
width: 50%
}
.ABC .XYZ:not(.DEF .XYZ) {
width: 50%
}
.ABC:not(.DEF) .XYZ {
width: 50%
}
You have syntax error in your html(you missed ") and you can select ABC which doesn't have DEF.
.XYZ {
background-color: blue;
height: 50px;
color: #fff;
text-align: center;
}
.ABC:not(.DEF) .XYZ {
background-color: red;
}
<div class="PQR">
<div class="ABC">
<div class="XYZ">Preant "ABC"</div>
</div>
<div class="DEF ABC">
<div class="XYZ">Preant "DEF ABC"</div>
</div>
</div>
or you can override by using the second parent
.XYZ {
background-color: blue;
height: 50px;
color: #fff;
text-align: center;
}
.DEF .XYZ {
background-color: red;
}
<div class="PQR">
<div class="ABC">
<div class="XYZ">Preant "ABC"</div>
</div>
<div class="DEF ABC">
<div class="XYZ">Preant "DEF ABC"</div>
</div>
</div>