Changing class of elements - javascript

I want to set up floating elements in a way it would depend of their amount.
<div id="whatever">
<div class="iwantthischangedto3elements">
element 1
element 2
element 3
</div>
<div class="iwantthischangedto2elements">
element 1
element 2
</div>
</div>
I can't really figure how to do this.
I'm guessing javascript is the answer, but can't get it work :
<script type="text/javascript">
function f() {
var list = document.getElementById("whatever");
var nbofelements = whatever.getElementsByTagName("a").length;
return nbofelements ;
whatever.getElementsByTagName("div").className += "elements + nbofelements";
}
</script>
Thanks for helping, I really struggle with javascript...
Edit:
Thanks all for your answers.
Sorry i didn't make myself clear enough, english isn't my first language.
Tambo did get what I meant, code works great.
However there's something I forgot...
An "h1" can be sometimes placed before the "a" list, and should not be counted as an element. Possibly other "h2", "h3", and so on... I want to count only "a" elements...
<div id="whatever">
<div class="iwantthischangedto3elements">
<h1>Do no not count this</h1>
element 1
element 2
element 3
</div>
Any idea how to proceed ?
Cheers
Vincent

You can use the for loop and Element.classList to add class
var whateverChild = document.querySelectorAll("#whatever div");
for(var i = 0; i < whateverChild.length; i++) {
//var anchor = document.querySelectorAll(whateverChild);
if(whateverChild[i].childElementCount == 2){
whateverChild[i].classList.add("two")
}else if(whateverChild[i].childElementCount == 3){
whateverChild[i].classList.add("three")
}
}
.two a{color: green}
.three a{color: red}
<div id="whatever">
<div class="iwantthischangedto3elements">
element 1
element 2
element 3
</div>
<div class="iwantthischangedto2elements">
element 1
element 2
</div>
</div>
If you have a paragraph in it you can use this
var whateverChild = document.querySelectorAll("#whatever div");
for(var i = 0; i < whateverChild.length; i++) {
var anchorLength = whateverChild[i].querySelectorAll("a").length;
if(anchorLength == 2){
whateverChild[i].classList.add("two")
}else if(anchorLength == 3){
whateverChild[i].classList.add("three")
}
}
.two a{color: green}
.three a{color: red}
<div id="whatever">
<div class="iwantthischangedto3elements">
element 1
<p> i am a paragraph </p>
element 2
element 3
</div>
<div class="iwantthischangedto2elements">
element 1
element 2
</div>
</div>
You can reduce the code to this
var numbersArray = ["zero", "one", "two", "three", "four", "five"],
whateverChild = document.querySelectorAll("#whatever div");
for(var i = 0; i < whateverChild.length; i++) {
var anchorLength = whateverChild[i].querySelectorAll("a").length;
whateverChild[i].classList.add(numbersArray[anchorLength])
}
.zero{color: orange}
.one{color: blue}
.two a{color: green}
.three a{color: red}
.four{color: purple}
.five{color: beige;}
<div id="whatever">
<div class="iwantthischangedto3elements">
element 1
<p> i am a paragraph </p>
element 2
element 3
</div>
<div class="iwantthischangedto2elements">
element 1
element 2
</div>
</div>

Related

Jquery append while wrapping every x element

I'm trying to create HTML like this:
<div class="container">
<div class="wrap">
<div class="el"></div>
<div class="el"></div>
<div class="el"></div>
</div>
<div class="wrap">
<div class="el"></div>
<div class="el"></div>
<div class="el"></div>
</div>
<div class="wrap">
<div class="el"></div>
<div class="el"></div>
<div class="el"></div>
</div>
</div>
The component used to add el element:
<input type="text" name="elements" />
el elements will appended to the container based on what number is added in the input. Every 3 elements should be wrapped in wrap div.
What I have so far:
$("input[name=elements]").on("keydown keyup", function() {
var amount = parseInt($(this).val());
for(i = 0; i < amount; i++) {
$(".container").append('<div class="el"></div>');
}
});
It adds the el divs but I'm not sure how to simultaneously wrap every 3 in wrap. Also is it possible to also remove el divs? If say I first type 8 in the input then I type 3, 11 divs will be added instead having just 3. In other words, the number of el divs in the HTML should alway be equal to the number in the input value. Would it make sense just to clear out the HTML first every time on input type?
You could first create an array of elements based on number of input value, append it to container and then wrap every nth element into wrap element.
const container = $('.container')
$("input").on('keyup', function() {
const val = parseInt($(this).val()) || 0;
const html = Array.from(Array(val), () => (
$("<div>", {
'class': 'el',
'text': 'element'
})
))
container.html(html)
for (let i = 0; i < val; i += 3) {
container
.find('.el')
.slice(i, i + 3)
.wrapAll("<div class='wrap'></div>");
}
})
.wrap {
border: 1px solid green;
margin: 10px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text">
<div class="container"></div>

How to change attributes of only first child divs within a div

I have this function that that will reset the display attributes of all divs within a div to none then sets the selected one to block.
function Test(id)
{
var allFiles = document.getElementById("FileContainer").getElementsByTagName("div");
for(i=0; i< allFiles.length; i++)
allFiles[i].style.display="none";
var selected = document.getElementById(id);
selected.style.display="block";
}
Problem is though that this also sets the display to none for the child divs of the child div as well. How can I make it only apply to the first child level?
<div id="FileContainer">
<div id="test-1"> //Set display to none
<div id="test1.1"> //Do not set display to none
</div>
<div id="test-2"> //Set display to none
<div id="test1.1"> //Do not set display to none
</div>
</div>
Expanding the solution given here, you can either assign the variable allFiles to all direct child divs using the CSS Child Combinator selector ">" like this:
/* JavaScript */
var allFiles = document.querySelectorAll("#FileContainer > div");
var btn = document.querySelector("button");
var val = document.getElementById("val");
function func() {
allFiles.forEach(div => {
if (div.id == val.value) {
div.style.display = "none";
}
});
}
btn.addEventListener("click", func);
/* CSS */
#FileContainer {color: white;}
#test-1 {background-color: green;}
#test-2 {background-color: green;}
#test3 {background-color: red;}
#test4 {background-color: red;}
<!--HTML-->
<div id="FileContainer">
<div id="test-1">Direct Child 1<div id="test3">Not Direct Child 1</div></div>
<div id="test-2">Direct Child 2<div id="test4">Not Direct Child 2</div></div>
</div>
<hr>
<input type="text" id="val" />
<button>Check ID</button>
<hr>
jsFiddle using the CSS Child Combinator selector ">": http://jsfiddle.net/AndrewL64/5nuedztx/20/
Or if you are sure there are no other elements directly under your #FileContainer div that you want to target, you can use the .children property like this:
/* JavaScript */
var allFiles = document.querySelector("#FileContainer").children;
var btn = document.querySelector("button");
var val = document.getElementById("val");
function func(){
[].forEach.call(allFiles, (div => {
if (div.id == val.value) {
div.style.display = "none";
}
}))
}
btn.addEventListener("click", func);
/* CSS */
#FileContainer {color: white;}
#test-1 {background-color: green;}
#test-2 {background-color: green;}
#test3 {background-color: red;}
#test4 {background-color: red;}
<!-- HTML -->
<div id="FileContainer">
<div id="test-1">Direct Child 1<div id="test3">Not Direct Child 1</div></div>
<div id="test-2">Direct Child 2<div id="test4">Not Direct Child 2</div></div>
</div>
<hr>
<input type="text" id="val" />
<button>Check ID</button>
<hr>
jsFiddle using .children : http://jsfiddle.net/AndrewL64/zkgjxhfc/30/
Check this
<div id="FileContainer">
<div id="test-1"> //Set display to none
<div id="test1-1">
</div> //Do not set display to none
</div>
<div id="test-2"> //Set display to none
<div id="test1-1"> //Do not set display to none
</div>
</div>
</div>
<button onclick="Test('test-2')">Click</button>
<script>
function Test(id){
var el = document.querySelectorAll("div#FileContainer > div");
for (var i = 0; i < el.length; i++){
//if id != requested id then hide it
if(el[i].id != id){
el[i].style.display = "none";
}
}
}
</script>

Javascript only addEventListener to parent style both parent and child differently

Currently have a div that controls the width of an element as well as the background color. That div has a child div which has the content which is semi-transparent. Which is why I need the first div. So the background is solid.
Now, I added an event listener to the parent which expands the width of one and decreases the width of the other 2 so they all fit. However, when I click on the parent div I would like the child of that specific div to add a class and remove a class from the other 2. Which I can't seem to figure out. Here's the code. Sorry if my formatting is poor, first time posting on stack overflow and I've googled and searched everything for an answer and can't seem to find one.
var purchaseStepCont = document.querySelectorAll(".step-container");
var purchaseStep = document.querySelectorAll(".step");
for (var i = 0; i < purchaseStepCont.length; i++) {
purchaseStepCont[i].addEventListener("click", function() {
for (var i = 0; i < purchaseStepCont.length; i++) {
purchaseStepCont[i].classList.remove("stepContActive");
purchaseStepCont[i].classList.add("stepContDeactive");
this.classList.add("stepContActive");
this.classList.remove("stepContDeactive");
}
});
}
<div class="step-container">
<div class="step">
<h1>01.</h1>
<h3>words</h3>
<p>wods</p>
</div>
</div>
<div class="step-container">
<div class="step">
<h1>01.</h1>
<h3>words</h3>
<p>wods</p>
</div>
</div>
<div class="step-container">
<div class="step">
<h1>01.</h1>
<h3>words</h3>
<p>wods</p>
</div>
</div>
You're very close. But if you want to add the class to the .step, you need this.firstElementChild.classList.add(...) rather than this.classList.add(...) (since this will be the .step-container, not the .step; but the .step is its first element child). Or for more markup flexibility, you could use this.querySelector(".step").
You can also use just a single event handler function rather than recreating it in the loop:
var purchaseStepCont = document.querySelectorAll(".step-container");
var purchaseStep = document.querySelectorAll(".step");
function clickHandler() {
var thisStep = this.firstElementChild; // Or this.querySelector(".step") would be more flexible
for (var i = 0; i < purchaseStep.length; i++) {
if (purchaseStep[i] === thisStep) {
purchaseStep[i].classList.add("stepContActive");
purchaseStep[i].classList.remove("stepContDeactive");
} else {
purchaseStep[i].classList.remove("stepContActive");
purchaseStep[i].classList.add("stepContDeactive");
}
}
}
for (var i = 0; i < purchaseStepCont.length; i++) {
purchaseStepCont[i].addEventListener("click", clickHandler);
}
.stepContActive {
color: blue;
}
.stepContDeactive {
color: #ddd;
}
<div class="step-container">
<div class="step">
<h1>01.</h1>
<h3>words</h3>
<p>wods</p>
</div>
</div>
<div class="step-container">
<div class="step">
<h1>01.</h1>
<h3>words</h3>
<p>wods</p>
</div>
</div>
<div class="step-container">
<div class="step">
<h1>01.</h1>
<h3>words</h3>
<p>wods</p>
</div>
</div>
clickHandler could be a bit shorter if you don't need to support IE11:
function clickHandler() {
var thisStep = this.firstElementChild; // Or this.querySelector(".step") would be more flexible
for (var i = 0; i < purchaseStep.length; i++) {
purchaseStep[i].classList.toggle("stepContActive", purchaseStep[i] === thisStep);
purchaseStep[i].classList.toggle("stepContDeactive", purchaseStep[i] !== thisStep);
}
}
But IE11 doesn't support the second argument to classList.toggle.

Javascript: Changing the class of the first element in a div

i'm trying to change the class of the first div.
e.g.
var div1 = element.getElementsByClassName("parent")
div1.children[0].setAttribute("class", "1 2");
<div class="parent">
<div class="1">Test</div>
<div class="1">test</div>
<div class="1">test</div>
</div>
But class doesnt change. Any idea why?
thanks :)
Change it to:
div1.children[0].className = "1 2";
Or
div1.children[0].classList.add('1');
div1.children[0].classList.add('2');
You should pick better class names btw!
Edit:
var div1 = document.getElementsByClassName("parent")[0];
div1.children[0].classList.add('1');
div1.children[0].classList.add('2');
Jquery way:
$(".parent > div:first").addClass("1 2");
// getElementsByClassName return an array (it is a collection)
var allDivs = document.getElementsByClassName("root");
// in the array i need the first
var myFirstElement = allDivs[0];
// i want first child
var myFirstChild = myFirstElement.children[0];
myFirstChild.className = 'b' ;
.a{ border : solid 1px red }
.b{ border : solid 1px blue }
<div class="root">
<div class="a">Test</div>
<div class="a">test</div>
<div class="a">test</div>
</div>

Javascript loop for every 2 classes

Hi I've got a small issue but not sure how to solve it by javascript/jquery. Essentially ive got several div classes but what i want to do is to create a loop to add a class on certain divs, without having to add an id on them manually but to add a id or class through the javascript code.
Heres an idea of what i mean:
<div></div><div></div>
<div></div><div></div>
<div></div><div></div>
<div></div><div></div>
This is what i currently have so lets say two divs will be a row. I want it so a a class is added in a certain way to make it like this:
<div class="green"></div> <div></div>
<div></div> <div class="green"></div>
<div class="green"></div> <div></div>
<div></div> <div class="green"></div>
So i am guessing it will be some sort of loop for every 2 divs then it will repeat in reverse.
using jquery
Use this loop to add class after 2 div
DEMO
$('div').each(function(i){
if((i%3) === 0){
$(this).addClass('green')
}
});
using :odd and :even selector
DEMO
$( "div:odd" ).addClass( "green" );
for even
$( "div:even" ).addClass( "green" );
Basically you want Zig-Zag.
There is no need of loops. You can use :nth-child selector as follow:
$('div:nth-child(4n+1)').addClass('green'); // Selects 1, 5, 9, 13, ...
$('div:nth-child(4n)').addClass('green'); // Selects 4, 8, 12, 16, ...
Demo
Here is the pure CSS Demo.
body {
width: 120px;
}
div {
height: 50px;
width: 50px;
background: red;
margin: 5px;
float: left;
}
div:nth-child(4n+1) {
background: green;
}
div:nth-child(4n) {
background: green;
}
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
HTML:
<div class="wrapper">
<div class="element">1</div>
<div class="element">2</div>
<div class="element">3</div>
<div class="element">4</div>
<div class="element">5</div>
<div class="element">6</div>
</div>
Pure Javascript:
var parents = document.getElementsByClassName("wrapper");
for (var i = 0, ii = parents.length; i < ii; i++) {
var parent = parents[i],
children = parent.children;
for (var j = 0, jj = children.length; j < jj; j++) {
var elem = children[j];
if (j % 2 === 0) {
elem.classList.add("highlight");
}
}
}
Demo
OR
jQuery:
$(".element:odd").addClass("highlight");
Demo
If just for show different background, you may use css nth-child(even) or nth-child(odd), as should sample in the table:
tr:nth-child(even) {background: #CCC}
tr:nth-child(odd) {background: #FFF}
You can grab your divs with a for loop using childNodes () javascript function. If the index is odd then you can apply manually your class.
something like this:
var nodes = parentElement.childNodes();
for (var i = 0; i < nodes.length; i++) {
if (i % 2 == 0) continue;
nodes[i].className = "green";
}

Categories

Resources