Add new class to children container in HTML/CSS with Javascript - javascript

I'm a beginner in javascript with HTML and CSS. I want to try is there a way to access child container class via parent container class. or can I add a new class("second_new") to "second" class via "first" class.
/* CSS */
.first {
background-color: red;
}
.first_new {
background-color: pink;
}
.second {
background-color: blue;
}
.second_new {
background-color: purple;
}
<!-- HTML -->
<div class="row">
<div class="first">
<h1>This is first class</h1>
<div class="second"> <!-- I want to change this -->
<h2>This is Second class</h2>
</div>
</div>
<div class="first">
<h1>This is first class</h1>
<div class="second"> <!-- I want to change this -->
<h2>This is Second class</h2>
</div>
</div>
</div>
<!-- JAVASCRIPT -->
<script>
var firstClass = document.getElementsByClassName("first");
function Mousein() {
this.classList.add("first_new");
};
function Mouseout() {
this.classList.remove("first_new");
};
for (var i = 0; i < firstClass.length; i++) {
firstClass[i].addEventListener('mouseover', Mousein);
firstClass[i].addEventListener('mouseout', Mouseout);
}
</script>

yes you can
Method 1
document.querySelector('.first .second');
Medthod 2
let parent = document.querySelector('.first');
parent.querySelector('.second');

Thanks Guys I found the answer this
/* CSS */
.first {
background-color: red;
}
.first_new {
background-color: pink;
}
.second {
background-color: blue;
}
.second_new {
background-color: purple;
}
<!-- HTML -->
<div class="row">
<div class="first">
<h1>This is first class</h1>
<div class="second"> <!-- I want to change this -->
<h2>This is Second class</h2>
</div>
</div>
<div class="first">
<h1>This is first class</h1>
<div class="second"> <!-- I want to change this -->
<h2>This is Second class</h2>
</div>
</div>
</div>
<!-- JAVASCRIPT -->
<script>
var firstClass = document.getElementsByClassName("first");
var child;
function Mousein() {
this.classList.add("first_new");
child = this.querySelector(".second");
child.classList.add("second_new")
};
function Mouseout() {
this.classList.remove("first_new");
child.classList.remove("second_new")
};
for (var i = 0; i < firstClass.length; i++) {
firstClass[i].addEventListener('mouseover', Mousein);
firstClass[i].addEventListener('mouseout', Mouseout);
}
</script>

Yes you can access bey selector. document.querySelector('parent child') . In your case would be: const childEl = document.querySelector('.first .second');

You can use getElementsByTagName() on any type of element.
This would be
var parents = document.getElementsByClassName('parent');
var child = [];
for (let i = 0; i < parents.length; i++) {
var child = parents.getElementsByTagName('div')[0];
children.push(child);
}
Or, Even Simpler:
var parents = document.querySelectorAll('.parent');
var children = document.querySelectorAll('.parent > div');
Note: Elements selected by querySelectorAll() are like arrays and array methods can be applied.
Note: To select one element use querySelector() method.

Related

Javascript - Automate duplicating tags from parent div to child div based on class snippet

I would like to automate duplicating a class from a parent div to each separate child span based on a word.
As an example:
parent div contains the following classes: grid-item tag-street-style tag-slender tag-classic tag-navy tag-grey tag-white is-loaded
I would like to duplicate any classes within the parent div with the precursor "tag-" and place them into each separate child span. In this case, the parent div contains the classes with the initial "tag-" word: tag-street-style tag-slender tag-classic tag-navy tag-grey tag-white
Some other parent divs will contain other classes that contain the initial word "tag-"
The "tag-" classes can be different in other parent divs but there will always be 5 "tag-" classes. As an example, a different parent div may contain the following classes with the initial "tag-" word: tag-smart-style tag-casual tag-modern tag-red tag-black tag-green
I already have a code snippet but this is locked in to 5 specific "tag-" classes. Here is the code:
let classMap = {
"tag-street-style": ".colour-tag-1",
"tag-slender": ".colour-tag-2",
"tag-navy": ".colour-tag-3",
"tag-grey": ".colour-tag-4",
"tag-white": ".colour-tag-5",
};
I would like the first "tag-" class identified within the parent div to be duplicated into "colour-tag-1" within the first child span.
Then I would like the second "tag-" class identified within the parent div to be duplicated into "colour-tag-2" within the second child span.
Then I would like the third "tag-" class identified within the parent div to be duplicated into "colour-tag-3" within the third child span.
Then I would like the fourth "tag-" class identified within the parent div to be duplicated into "colour-tag-4" within the fourth child span.
Then I would like the fifth "tag-" class identified within the parent div to be duplicated into "colour-tag-5" within the fifth child span.
$(document).ready( function() {
$(".grid-item .grid-meta-wrapper").each(function(e){
$(this).append('<div class="product-view-item-colour-tags"><span class="product-view-item-colour-tag colour-tag-1">tag1</span><span class="product-view-item-colour-tag colour-tag-2">tag2</span><span class="product-view-item-colour-tag colour-tag-3">tag3</span><span class="product-view-item-colour-tag colour-tag-4">tag4</span><span class="product-view-item-colour-tag colour-tag-5">tag5</span></div>');
});
let classMap = {
"tag-street-style": ".colour-tag-1",
"tag-slender": ".colour-tag-2",
"tag-navy": ".colour-tag-3",
"tag-grey": ".colour-tag-4",
"tag-white": ".colour-tag-5",
};
for (let cls in classMap) {
document.querySelector(classMap[cls]).classList.add(cls);
}
});
<style>
.tag-street-style {
background-color: purple;
}
.tag-slender {
background-color: red;
}
.tag-navy {
background-color: blue;
}
.tag-grey {
background-color: grey;
}
.tag-white {
background-color: black;
color: white;
}
.tag-red {
background-color: black;
color: red;
}
.tag-black {
background-color: white;
color: black;
}
.tag-green {
background-color: black;
color: green;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="grid-item tag-street-style tag-slender tag-classic tag-navy tag-grey tag-white is-loaded">
<section class="grid-meta-wrapper">
<div class="grid-main-meta">
<div class="grid-title"> T-Shirt </div>
<div class="grid-prices">
<div class="product-price">
<span>12.99</span>
</div>
</div>
</div>
<div class="grid-meta-status"></div>
</section>
</div>
<br><br><br>
<div class="grid-item tag-smart-style tag-casual tag-modern tag-red tag-black tag-green is-loaded">
<section class="grid-meta-wrapper">
<div class="grid-main-meta">
<div class="grid-title"> T-Shirt </div>
<div class="grid-prices">
<div class="product-price">
<span>12.99</span>
</div>
</div>
</div>
<div class="grid-meta-status"></div>
</section>
</div>
First, here is a testable solution:
$(document).ready( function() {
$(".grid-item .grid-meta-wrapper").each(function(e){
$(this).append('<div class="product-view-item-colour-tags"><span class="product-view-item-colour-tag colour-tag-1">tag1</span><span class="product-view-item-colour-tag colour-tag-2">tag2</span><span class="product-view-item-colour-tag colour-tag-3">tag3</span><span class="product-view-item-colour-tag colour-tag-4">tag4</span><span class="product-view-item-colour-tag colour-tag-5">tag5</span></div>');
});
let classes = [...document.getElementById("tag-specifier").classList].filter(item => item.indexOf("tag-") === 0);
for (let index = 0; index < classes.length; index++) {
let currentItem = document.querySelector(".colour-tag-" + (index + 1));
if (currentItem !== null) {
currentItem.classList.add(classes[index]);
}
}
});
.tag-street-style {
background-color: purple;
}
.tag-slender {
background-color: red;
}
.tag-navy {
background-color: blue;
}
.tag-grey {
background-color: grey;
}
.tag-white {
background-color: black;
color: white;
}
.tag-red {
background-color: black;
color: red;
}
.tag-black {
background-color: white;
color: black;
}
.tag-green {
background-color: black;
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="tag-specifier" class="grid-item tag-street-style tag-slender tag-classic tag-navy tag-grey tag-white is-loaded">
<section class="grid-meta-wrapper">
<div class="grid-main-meta">
<div class="grid-title"> T-Shirt </div>
<div class="grid-prices">
<div class="product-price">
<span>12.99</span>
</div>
</div>
</div>
<div class="grid-meta-status"></div>
</section>
</div>
Now, let's understand it:
I have added the id of tag-specifier to the element which has the classes, so the code will have an easy time finding the classes to work with
document.getElementById("tag-specifier").classList is returning an object of key-value pairs where the keys are indexes (starting from 0) and the values are class names
I convert the result of classList into an array via [...document.getElementById("tag-specifier").classList] because I intend to use the filter() function of the array, alternatively I could have written a loop with similar effect
.filter() is being called for the newly converted array. This function takes a callback (more on that below) that determines which items we are interested about from the array and returns an array that contains only the items that the callback found interesting
a callback is a function that is scheduled to be executed at some future point of time
in our case, the callback of .filter() is a function which will be executed for each elements of the array and will evaluate them whether they are interesting
our callback is item => item.indexOf("tag-") === 0, which is a function (we use the arrow operator => to differentiate the parameter, which is item and the actual function body, which is item.indexOf("tag-") === 0), that is, we are only interested about items whose name starts with tag-
after the call for .filter(), the value assigned to classes is an array of class names that only holds valuable class names from our perspective, that is, class names starting with tag-
we loop classes using a variable we create for this purpose, named index
we search for the element that corresponds to the selector of ".colour-tag-" + (index + 1). The reason for the index + 1 is that Javascript arrays are 0-indexed and your tag indexes start from 1
note that (index + 1) is enclosed into parantheses. The reason for this is that + is an operator that acts both as concatenator and numeric addition and evaluates from left-to-right, that is, without the paranthesis around (index + 1) the result of ".colour-tag-" + index + 1 would be looking like .colour-tag-01 instead of .colour-tag-2
we check whether currentItem exists, so we program defensively, so, if any anomaly occurs, we intend our code to handle it gracefully
if currentItem existed, then we add the current class, which is classes[index]
EDIT
The initial solution I have implemented was assuming that we deal with a single such case, while your problem included multiple similar cases on the same page. To solve this issue, I have added an extra layer to the solution, querying the roots of all relevant subtrees in HTML and using them as the context of their respective problem-spaces.
Here is a snippet that illustrates it (yes, the first 3 tags will be unstyled, but this is not due to the logic of the code, but it is rather due to the styling specification of the structure):
$(document).ready( function() {
$(".grid-item .grid-meta-wrapper").each(function(e){
$(this).append('<div class="product-view-item-colour-tags"><span class="product-view-item-colour-tag colour-tag-1">tag1</span><span class="product-view-item-colour-tag colour-tag-2">tag2</span><span class="product-view-item-colour-tag colour-tag-3">tag3</span><span class="product-view-item-colour-tag colour-tag-4">tag4</span><span class="product-view-item-colour-tag colour-tag-5">tag5</span><span class="product-view-item-colour-tag colour-tag-6">tag6</span></div>');
});
for (let context of $(".list-grid .grid-item")) {
let idDeclaration = context.id;
let classes = [...context.classList].filter(item => item.indexOf("tag-") === 0);
for (let index = 0; index < classes.length; index++) {
let currentItem = context.querySelector(".colour-tag-" + (index + 1));
if (currentItem !== null) {
currentItem.classList.add(classes[index]);
}
}
}
});
.product-view-item-colour-tags .tag-navy {
background-color: blue;
}
.product-view-item-colour-tags .tag-grey {
background-color: grey;
}
.product-view-item-colour-tags .tag-white {
background-color: black;
color: white;
}
.product-view-item-colour-tags .tag-red {
color: red;
}
.product-view-item-colour-tags .tag-black {
background-color: white;
color: black;
}
.product-view-item-colour-tags .tag-green {
color: green;
}
.product-view-item-colour-tags .tag-yellow {
background-color: black;
color: yellow;
}
.product-view-item-colour-tags .tag-orange {
color: orange;
}
.product-view-item-colour-tags .tag-pink {
color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list-grid">
<div id="thumb-product-3-9" class="grid-item tag-street-style tag-slender tag-classic tag-navy tag-grey tag-white is-loaded">
<section class="grid-meta-wrapper">
<div class="grid-main-meta">
<div class="grid-title"> T-Shirt 1</div>
<div class="grid-prices">
<div class="product-price">
<span>9.99</span>
</div>
</div>
</div>
<div class="grid-meta-status"></div>
</section>
</div>
<br>
<div id="thumb-product-3-12" class="grid-item tag-social-style tag-thicker tag-premium tag-green tag-black tag-red is-loaded">
<section class="grid-meta-wrapper">
<div class="grid-main-meta">
<div class="grid-title"> T-Shirt 2</div>
<div class="grid-prices">
<div class="product-price">
<span>12.99</span>
</div>
</div>
</div>
<div class="grid-meta-status"></div>
</section>
</div>
<br>
<div id="thumb-product-3-1" class="grid-item tag-outdoor-style tag-warmer tag-premium tag-pink tag-white tag-orange is-loaded">
<section class="grid-meta-wrapper">
<div class="grid-main-meta">
<div class="grid-title"> T-Shirt 3</div>
<div class="grid-prices">
<div class="product-price">
<span>14.99</span>
</div>
</div>
</div>
<div class="grid-meta-status"></div>
</section>
</div>
<br>
<div id="thumb-product-3-4" class="grid-item tag-street-style tag-slender tag-casual tag-green tag-yellow tag-red is-loaded">
<section class="grid-meta-wrapper">
<div class="grid-main-meta">
<div class="grid-title"> T-Shirt 4</div>
<div class="grid-prices">
<div class="product-price">
<span>15.99</span>
</div>
</div>
</div>
<div class="grid-meta-status"></div>
</section>
</div>
</div>

Javascript : finding a specific previous element on list and adding class

I have a list like this.
Inside each .list item there is a html button :
<div class="list">
<button>.list</button>
</div>
Also, each item can be inside a .bloc element
<div class="list"><button>.list</button></div>
<div class=bloc>
<div class="list"><button>.list</button></div>
</div>
When I click on the button, I would like the previous .list item to have the .active class like so :
Well it’s pretty easy with jquery and i've done that, it’s work pretty well :
$('.list button').on('click', function() {
$(this).closest('.list').prev('.list').addClass('active');
});
BUT i have some specific cases :
Sometimes the list items can be hidden and a list with hidden class can’t have .active class :
Or more complicated. You have to go up on each item one by one and put the active class to the first which does not have the hidden class :
I did the mechanics for items without class hidden, but I'm afraid I'm going in the wrong direction because the number of cases is getting bigger and bigger. Ain't there a smarter way ? :o
$('.list button').on('click', function() {
if ($(this).closest('.list').prev().length === 0) {
if ($(this).closest('.bloc').length) {
$(this).closest('.bloc').prev('.list').addClass('active');
$(this).closest('.bloc').prev('.bloc').find('.list:last-child').addClass('active');
} else {
$(this).closest('.list').next('.list').addClass('active');
}
}
if ($(this).closest('.list').prev('.bloc').length) {
$(this).closest('.list').prev('.bloc').find('.list:last-child').addClass('active');
}
$(this).closest('.list').prev('.list').addClass('active');
}
Rather than use .closest .prev and .next you can use the overload to .index which will give you the index within an existing collection.
var idx = collection.index(element);
select all your .list items into a jquery object/collection
when clicking get the index within that collection
subtract 1 to get the previous .list item within that collection
The basic scenarios are covered with $(".list") :
// collate the list first
var list = $(".list");
// add click handler
list.click(function() {
// confirm there are no duplicates
// comapred with $(this).index() which is the index within the parent
console.log(list.index(this), $(this).index())
$(".active").removeClass("active");
var idx = list.index(this);
if (idx > 0)
list.eq(idx-1).addClass("active");
});
.list { border:1px solid #CCC; height: 20px; }
.bloc { border:1px solid #444; padding: 5px; }
.active { border:1px solid red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrapper'>
<div class='bloc'>
<div class='list'></div>
<div class='list'></div>
</div>
<div class='list'></div>
<div class='list'></div>
</div>
All the other use-cases are then just a case of providing the correct selector up-front, with otherwise exactly the same code
var list = $(".wrapper>.bloc:not(.hidden)>.list:not(.hidden),.wrapper>.list:not(.hidden)");
I've tried to recreate some of your scenarios, but if there's one that's missing, please comment and I'll ensure it fits (within the remit of the question).
Giving:
var list = $(".wrapper>.bloc:not(.hidden)>.list:not(.hidden),.wrapper>.list:not(.hidden)")
list.click(function() {
$(".active").removeClass("active");
var idx = list.index(this);
if (idx > 0)
list.eq(idx-1).addClass("active");
});
.list { border:1px solid #CCC; height: 20px; }
.bloc { border:1px solid #444; padding: 5px; }
.active { border:1px solid red; }
.hidden { background-color: #ccc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrapper'>
<div class='bloc'>
<div class='list'></div>
<div class='list'></div>
</div>
<div class='list hidden'></div>
<div class='bloc'>
<div class='list hidden'></div>
<div class='list hidden'></div>
</div>
<div class='list'></div>
<div class='bloc'>
<div class='list hidden'></div>
<div class='list'></div>
</div>
<div class='list'></div>
<div class='list'></div>
<div class='bloc hidden'>
<div class='list'></div>
<div class='list'></div>
</div>
<div class='list'></div>
<div class='list'></div>
</div>

How to select a row that has been clicked

I want have a list of items in which the color of a selected element turns red when it is selected and all of the other divs turn blue. How can I identify the selected div that would then turn red?
$(document).ready(function() {
$('#table_1 .tableRow div').click(function(event) {
//Set the style for all divs
var myElements = document.querySelectorAll("#table_1 .tableRow div");
for (var i = 0; i < myElements.length; i++) {
myElements[i].className = "blueText";
}
//Set the style for tyhe selected div
//selectedItem.className="selectedText";
});
});
.selectedText {
color: red;
}
.blueText {
color: blue;
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<div id="table_1" class="table">
<div class="tableRow">
<div>
Line 1
</div>
<div>
Line 2
</div>
<div>
Line 3
</div>
</div>
</div>
</body>
</html>
It's enough to change:
//selectedItem.className="selectedText";
to:
event.target.className="selectedText";
The snippet:
$(document).ready(function(){
$('#table_1 .tableRow div').click(function(event) {
//Set the style for all divs
var myElements = document.querySelectorAll("#table_1 .tableRow div");
for (var i = 0; i < myElements.length; i++) {
myElements[i].className="blueText";
}
//Set the style for tyhe selected div
event.target.className="selectedText";
});
});
.selectedText {
color: red;
}
.blueText {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="table_1" class="table">
<div class="tableRow">
<div>
Line 1
</div>
<div >
Line 2
</div>
<div >
Line 3
</div>
</div>
</div>
You can do it with this:
$('#table_1 .tableRow div').click(function() {
$(this).removeClass().addClass('selectedText').siblings().removeClass().addClass('blueText')
})
.selectedText {
color: red;
}
.blueText {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="table_1" class="table">
<div class="tableRow">
<div>
Line 1
</div>
<div>
Line 2
</div>
<div>
Line 3
</div>
</div>
</div>
Pure CSS solution using tabindex and :focus Selector for DIV's.
div:focus {
color: red;
}
div {
color: blue;
}
<div id="table_1" class="table">
<div class="tableRow">
<div tabindex="1">Line 1</div>
<div tabindex="2">Line 2</div>
<div tabindex="3">Line 3</div>
</div>
</div>
You can use the $(this) object to reference the element on which a jQuery handler was made:
$(document).ready(function(){
$('#table_1 .tableRow div').click(function(event) {
//Set the style for all divs
var myElements = document.querySelectorAll("#table_1 .tableRow div");
for (var i = 0; i < myElements.length; i++) {
myElements[i].className="blueText";
}
$(this).addClass('selectedText')
});
});
Also, if you want to use something other than just the CSS class to determine if an element is selected or not (outside of the jQuery callback), you could add a data-* attribute to it 1.

Javascript Multi style set

<div id="newsinsite" >gasdgasdgf</div>
<div id="newsinsite" >hasdgfasd</div>
<div id="newsinsite" >gasdgasd</div>
<div id="newsinsite" >gasdgasd</div>
<script>
document.getElementById('style').style.width = "430px";
</script>
Javascript is give a set style for all div with newsinsite. Please help me :)
Do this:
<div id="newsinsite1" class="newsinsite">gasdgasdgf</div>
<div id="newsinsite2" class="newsinsite">gasdgasdgf</div>
<div id="newsinsite3" class="newsinsite">gasdgasdgf</div>
<div id="newsinsite4" class="newsinsite">gasdgasdgf</div>
<script>
var elem = document.getElementsByClassName("newsinsite");
for (var i=0;i<elem.length;i++) {
elem[i].style.width = "430px";
}
</script>
But if this is a static setting use css instead:
<style>
.newsinsite {
width: "430px";
}
</style>
UPDATE
For IE8 support, use querySelectorAll('.classname') instead of getElementsByClassName
<div class="newsinsite">gasdgasdgf</div>
<div class="newsinsite">hasdgfasd</div>
<div class="newsinsite">gasdgasd</div>
<div class="newsinsite">gasdgasd</div>
<script>
var i = 0, els = document.getElementsByClassName('newsinsite'), len = els.length;
for(;i<len;i++) {
els[i].style.width = '430px';
}
</script>
Or, set it with CSS:
.newsinsite {
width: 430px;
}

Javascript hide/unhide text

I am having trouble figuring this out. After a user clicks Link1 I would like it to close when Link2 has been clicked using Javascript. I have seen an example or two with this working in jquery, but I already have a tone of code written using this method, so I would prefer to to have to start all over.Thanks everyone!
HTML...
<style>
.hidden { display: none; }
.visible { display: block; }
</style>
</head>
<body>
<div id="col2">
Link 1
<div id="contentONE" class="hidden">
<h3>contentONE</h3>
<ul>
<li>Content1.1</li>
<li>Content1.2</li>
</ul>
</div>
</div>
<div id="col2">
Link 2
<div id="contentTWO" class="hidden">
<h3>contentTWO</h3>
<ul>
<li>Content2.1</li>
<li>Content2.2</li>
</ul>
</div>
</div>
<script type="text/javascript">
function unhide(divID) {
var item = document.getElementById(divID);
if (item) {
item.className=(item.className=='hidden')?'unhidden':'hidden';
}
}
</script>
</body>
Try something like this:
var collapsables = document.getElementsByClassName('collapsable');
function unhide(divID) {
// Hide previous
for (var i = 0; i < collapsables.length; i++) {
collapsables[i].className = 'collapsable hidden';
}
// Show new
var item = document.getElementById(divID);
if (item) {
item.className = 'collapsable';
}
}
Demo: http://jsfiddle.net/MLmXa/

Categories