Count nested divs in JavaScript - javascript

Hey I need to count the nested divs with a given class name. For example:
<div id = "divA">
<div class = "anotherName"></div>
<div class = "toBeCounted"></div>
<div class = "someName"></div>
<div class = "toBeCounted"></div>
<div class = "toBeCounted"></div>
<div class = ""></div>
</div>
<div id = "divB">
<div class = ""></div>
<div class = "toBeCounted"></div>
<div class = ""></div>
<div class = "toBeCounted"></div>
</div>
So if I want to count "toBeCounted" I would get 3 for divA and 2 for divB.

You can use .querySelectorAll() and check the length of the result:
var divAcount = document.querySelectorAll("#divA > .toBeCounted").length;
The > relation insists that the .toBeCounted elements are immediate children of divA. If that's not what you want, and any toBeCounted div within divA should count, you'd just leave out the >.

try this pure javascript code
var countinDivA = document.getElementById("divA").getElementsByClassName("toBeCounted").length;
var countinDivB = document.getElementById("divB").getElementsByClassName("toBeCounted").length;

With Jquery this can be easily achieved by using
var countA = $("#divA .toBeCounted").length;
var countB = $("#divB .toBeCounted").length;

If you don't know the id's of the parents ahead of time, this may prove useful:
var parents = [],
counted = document.getElementsByClassName("toBeCounted");
for (var i=0; i < counted.length; i++ ) {
var id = counted[i].parentNode.id;
if ( !parents[id] ) parents[id] = 1
else parents[id]++;
}
[ divA: 3, divB: 2 ]

Related

Changing content in multiple classes via JS

I want to change the HTML-value of the highlighted span below (class=percent-value):
<div id="verfuegbarstd" class="et_pb_number_counter_4" data-number-value="0" data-number-separator="">
<div class="percent">
<p>**<span class="percent-value">0</span>**<span class="percent-sign"></span></p>
</div>
<h3 class="title">Verfügbare Stunden</h3>
<canvas height="0" width="0"></canvas>
</div>
I tried the following:
var verfuegbareStd = document.getElementsByClassName('et_pb_number_counter_4').getElementsByClassName('percent').getElementsByClassName('percent-value');
var budget = document.getElementsByClassName('et_pb_number_counter_2').getElementsByClassName('percent').getElementsByClassName('percent-value');
var lohnProStd = document.getElementsByClassName('et_pb_number_counter_3').getElementsByClassName('percent').getElementsByClassName('percent-value');
var gebrauchteStd = document.getElementsByClassName('et_pb_number_counter_5').getElementsByClassName('percent').getElementsByClassName('percent-value');
function calcVerfuegbareStd() {
var calc = budget.innerHTML / lohnProStd.innerHTML;
verfuegbareStd.innerHTML = calc;
}
calcVerfuegbareStd();
Does that make any sense?
document.getElementsByClassName returns a collection of all elements in the document with the specified class name, as a NodeList object. So thats why i check the length.
You can use also document.querySelector which gets the first element in the document with the class "xxxx" is returned.
I put both!
You can do it with jquery also but i thought you want pure js.
var elements = document.getElementsByClassName('percent-value'); // List of elements
var spanQuery = document.querySelector('.percent-value'); // The first element in the document with the class "myclass" is returned:
spanQuery.innerHTML = 'Hello!!!';
if (elements.length > 0) {
var span = elements[0];
span.innerHTML = 'Hello!!!';
}
<div id="verfuegbarstd" class="et_pb_number_counter_4" data-number-value="0" data-number-separator="">
<div class="percent">
<p>**<span class="percent-value">0</span>**<span class="percent-sign"></span></p>
</div>
<h3 class="title">Verfügbare Stunden</h3>
<canvas height="0" width="0"></canvas></div>
Try this?:
document.getElementsByClassName("percent-value").innerHTML = "the content you want";
It is simpler to use querySelector(). This will return the first element.
var verfuegbareStd = document.querySelector('.et_pb_number_counter_4 .percent .percent-value');
console.log(verfuegbareStd.innerHTML)
<div id="verfuegbarstd" class="et_pb_number_counter_4" data-number-value="0" data-number-separator="">
<div class="percent">
<p>**<span class="percent-value">0</span>**<span class="percent-sign"></span></p>
</div>
<h3 class="title">Verfügbare Stunden</h3>
<canvas height="0" width="0"></canvas>
</div>

Child appending / DOM ordering JavaScript

<body>
<div class = "order-1-a">
<div class = "order 2-a">
<div class = "order 3-a"></div>
</div>
<div class = "order 2-b"></div>
<div class = "order 2-c"></div>
<div class = "order 2-d"></div>
</div>
<div class = "order-1-b"></div>
</body>
If I want a div to wrap only class "order-2-a" + being the first child of "class-1-a", how should I script the div with JavaScript?
Probably your best bet is to:
Create a new Element with .createElement().
Append 2-a to the new Element with .appendChild().
Insert the new element before 2b with .insertBefore().
var one_a = document.getElementsByClassName("order-1-a")[0];
var two_a = document.getElementsByClassName("order-2-a")[0];
var two_b = document.getElementsByClassName("order-2-b")[0];
var new_node = document.createElement("div");
new_node.appendChild(two_a);
one_a.insertBefore(new_node, two_b);
console.log(one_a.innerHTML);
<body>
<div class="order-1-a">
<div class="order-2-a">
<div class="order-3-a"></div>
</div>
<div class="order-2-b"></div>
<div class="order-2-c"></div>
<div class="order-2-d"></div>
</div>
<div class="order-1-b"></div>
</body>
This provides the structure you're looking for (albeit not displayed well with console.log()).
Also, please be aware that class names cannot start with numbers, and may yield unexpected results. I've updated most of your classes to start with order in my example, as is with your order-1-a class.
Hope this helps!
You can create a general wrapping function based on a selector. It should get the subject node, then its parent and either it's next sibling or null if there isn't one.
Then create an element of the required type, append the subject node and insert it before the next sibling or as the last node if there wasn't one.
PS.
I've modified the class names to be valid, they can't start with a digit.
// Wrap element with selector in element with tagName
function wrapEl(selector, tagName) {
var node = document.querySelector(selector);
// If there is no subject node, return
if (!node) return;
// Get parent and sibling (or null if there isn't one)
var parent = node.parentNode;
var sibling = node.nextSibling;
// Append stuff
var wrapper = document.createElement('tagName');
wrapper.textContent = 'inserted wrapper'; // Just to show it's there
wrapper.appendChild(node);
parent.insertBefore(wrapper, sibling);
}
window.onload = function() {
wrapEl('.order-2-a', 'div');
}
<body>
<div class = "order-1-a">
<div class = "order-2-a">
<div class = "order-3-a"></div>
</div>
<div class = "order-2-b"></div>
<div class = "order 2-c"></div>
<div class = "order 2-d"></div>
</div>
<div class = "order-1-b"></div>
</body>

How can I access classes within arrays and style them using javascript

So let's say I have 3 different classes: one, two, and three. Each class has 3 div's like this:
<div class="one"></div>
<div class="one"></div>
<div class="one"></div>
<div class="two"></div>
<div class="two"></div>
<div class="two"></div>
<div class="three"></div>
<div class="three"></div>
<div class="three"></div>
Then I give each class a variable:
var _1 = document.getElementsByClassName("one");
var _2 = document.getElementsByClassName("two");
var _3 = document.getElementsByClassName("three);
Then I put them all in an array call nums:
var nums = [_1,_2,_3];
If I wanted to then go through and change the text color of every single div in the classes: one, two, and three. How would I go about doing that without doing something like this:
function textColor() {
var i;
for (i = 0; i < _1.length; i++) {
_1[i].style.color = "red";
}
for (i = 0; i < _2.length; i++) {
_2[i].style.color = "red";
}
for (i = 0; i < _3.length; i++) {
_3[i].style.color = "red";
}
}
I would really like to only have one for loop that goes through and gets all the items in the array nums, and then goes through and gets every div from every item in nums and changes the text color.
Use concat when putting them in nums (and convert the NodeLists to arrays)
var nums = Array.from(_1).concat(Array.from(_2)).concat(Array.from(_3));
Or use the spread operator
var nums = [..._1,..._2,..._3];
Then you can do
function textColor() {
nums.forEach(node => node.style.color = 'red');
}
You can flatten your nums array like this:
var flatNums = [].concat.apply([],nums)
and then go through it:
for (i = 0; i < flatNums.length; i++) {
flatNums[i].style.color = "red";
}
I would just do something like this:
$(".one, .two, .three").prop("style","color: red;");
Or add a second class for all nine div:s.
If you will apply same style to all divs, you can simplify things even more:
divs=document.querySelectorAll('.one, .two, .three');
divs.forEach(function(el) {
el.style.color='red';
})
divs=document.querySelectorAll('.one, .two, .three');
divs.forEach(function(el) {
el.style.color='red';
})
<div class="one">1</div>
<div class="one">2</div>
<div class="one">3</div>
<div class="6">
skip
</div>
<div class="two">4</div>
<div class="two">5</div>
<div class="two">6</div>
<div class="three">7</div>
<div class="three">8</div>
<div class="three">9</div>

Count sibling elements that all have same unknown class name

I need help working with a large list of sibling elements with different class names.
Getting the amount of elements with the same class name and putting them in an array
Finding first element in that class group (this can be number or name).
Statement that runs a function: if element = first element of group do console.log("first element");
Here's an example of the first 3 classes but this will go from groupA to Groupz
<div class = 'slider'>
<div class = 'item1 groupA'> <!-- Start Group A -->
<img src='xyz' />
</div>
<div class = 'item1 groupA'>
<img src='xyz' />
</div>
<div class = 'item1 groupA'>
<img src='xyz' />
</div>
<div class = 'item1 groupA'>
<img src='xyz' />
</div>
<div class = 'item1 groupB'> <!-- Start Group B -->
<img src='xyz' />
</div>
<div class = 'item1 groupB'>
<img src='xyz' />
</div>
<div class = 'item1 groupB'>
<img src='xyz' />
</div>
<div class = 'item1 groupC'> <!-- Start Group C -->
<img src='xyz' />
</div>
<div class = 'item1 groupC'>
<img src='xyz' />
</div> <!-- All the way to group Z -->
</div>
Edit: Your requirement is very specific. Below is just a sample to just loop thru all childrens and store the count and first element in the matching count. Let me
$(function () {
$.fn.benton = function () {
//just the immediate childrens
var $chds = $(this).children();
var lc = {
firstEl: {},
classCount: {}
};
$.each ($chds, function (idx, el) {
if (el.className) {
var tokens = el.className.split(' ');
for (var i = 0; i < tokens.length; i++) {
if (lc.classCount.hasOwnProperty(tokens[i])) {
lc.classCount[tokens[i]] += 1;
} else {
lc.classCount[tokens[i]] = 1;
lc.firstEl[tokens[i]] = $(el);
}
}
}
});
return lc;
};
var stats = $('.slider').benton();
console.log(stats.classCount['groupA']);
stats.firstEl['item1'].css({border: '1px solid red', width: 100, height: 10});
});
DEMO: http://jsfiddle.net/LhwQ4/1/
I think what you need is to use context of slider to get the child elements.. see below,
var $slider = $('.slider')
Now using the $slider context,
$('.groupA', $slider)
//Returns Array of jQuery object with elements has class `groupA`
$('.groupA:first', $slider)
//Returns first element in collection of element with class `groupA`
To get all elements with the same class name, you would only have to use a simple jQuery selector. The returned value is an array containing all matching elements.
var groupA = $(".groupA");
To get the number of items you need only access the length parameter of the array.
var groupALength = groupA.length;
If you want to extract only the first element of any matched elements, you can use jQuery's :first selector.
var firstElement = $(".groupA:first");
var groups = {};
$(".slider").children().each(function(i, el) {
var classes = el.className.split(/\s+/);
for (var i=0; i<classes.length; i++)
if (classes[i] in groups)
groups[classes[i]].push(el);
else
groups[classes[i]] = [el];
});
Now, you can access all elements of a group via groups["groupA"] etc (jQuery collection: $(groups["groupB"])) and the first one via groups["groupC"][0]. The amount of elements in a group is just the length of the array.
Notice that this puts all elements in the group "item1" - I don't know what you need that class for.
Ok, so this solution is quite sensitive. I'm making a few assumptions about your HTML.
In your example you gave each item a class of item1. I am assuming that this is just an issue of copying and pasting the element. Each "item" should have the same class so that you can retrieve all the items with one selector. For my example, I'm assuming a class of item.
There should be only this item class plus an additional "group" class. Any other class given to the item will render this solution invalid.
// fetch ALL items
var allItems = $(".item");
// initialize groups array
var groups = {};
$.each(allItems,function(index,elem){
var item = $(this);
var itemClass = item.attr('class');
// remove the "item" class and any leftover whitespace
itemClass = $.trim(itemClass.replace('item','')); // should now be groupA/groupB...
// add item to array at the index of the group
if (groups[itemClass] == undefined){
groups[itemClass] = [];
}
groups[itemClass].push(item);
});
You should now be left with an array of arrays containing all the items. To see this in action, you can check out this jsFiddle.

How to get the count of the DIVs with almost the same ID property?

I have many DIVs on my page with the same ID
eg:
<div id="myDiv1">
...
</div>
<div id="myDiv2">
...
</div>
<div id="myDiv3">
...
</div>
...
<div id="myDiv20">
...
</div>
...
As You see, the ID property looks almost the same - the only diffrence is that there is a number in each ID.
How to get the count of that DIVs? I thought I can do something like that:
var myDivs= document.getElementById('myDiv');
but returns null
You can do this using jQuery like this:
$('div[id^=myDiv]')
If you can't use jQuery, you'll need to call getElementsByTagName and loop through the values checking the ID property.
var divs = document.getElementsByTagName('div');
var counter = 0;
for(var i in divs) {
if(divs[i].id.indexOf('myDiv') === 0) {
counter++;
}
}
or just
document.querySelectorAll('[id^=myDiv]').length
you can use jquery
//this will give you all divs start with myDiv in the id
var divs = $("div[id^='myDiv']");
From this site:
function getElementsByRegExpId(p_regexp, p_element, p_tagName) {
p_element = p_element === undefined ? document : p_element;
p_tagName = p_tagName === undefined ? '*' : p_tagName;
var v_return = [];
var v_inc = 0;
for(var v_i = 0, v_il = p_element.getElementsByTagName(p_tagName).length; v_i < v_il; v_i++) {
if(p_element.getElementsByTagName(p_tagName).item(v_i).id && p_element.getElementsByTagName(p_tagName).item(v_i).id.match(p_regexp)) {
v_return[v_inc] = p_element.getElementsByTagName(p_tagName).item(v_i);
v_inc++;
}
}
return v_return;
}
Usage:
var v_array = getElementsByRegExpId(/^myDiv[0-9]{1,2}/);

Categories