How to get all CSS classes of an element? - javascript

I have an element with multiple classes and I'd like to get its css classes in an array. How would I do this? Something like this:
var classList = $(this).allTheClasses();

No need to use jQuery for it:
var classList = this.className.split(' ')
If you for some reason want to do it from a jQuery object, those two solutions work, too:
var classList = $(this)[0].className.split(' ')
var classList = $(this).prop('className').split(' ')
Of course you could switch to overkill development mode and write a jQuery plugin for it:
$.fn.allTheClasses = function() {
return this[0].className.split(' ');
}
Then $(this).allTheClasses() would give you an array containing the class names.

Note that you can also use myElement.classList as a simple array-like object:
const classList = myElement.classList;
This is supported by all major browsers for a while now, apart IE 9 and below.

This should do the work for you:
var classes = $('div').attr('class').split(" ");
This would be the jQuery solution for other solutions there are other answers !

Check this out:
var classes = $('selector').prop('classList');

element.classList.value
console.log("class")
console.log(document.getElementById('c2').classList.value)
<div id="c2" class="class1 class2"> i am two class</div>
getAttribute
console.log("class")
console.log(document.getElementById('c2').getAttribute('class'))
<div id="c2" class="class1 class2"> i am two class</div>
className
console.log("class")
console.log(document.getElementById('c2').className)
<div id="c2" class="class1 class2"> i am two class</div>
to make an array choose any one of above method
string.split(' ');

function showClasses() {
const div = document.querySelector('div');
const classes = div.className.split(' ');
const p = document.querySelector('p');
p.innerHTML = classes;
}
<div class="foo bar">This div has foo, bar classes</div>
<p class='output'>Above div classes appear here</p>
<button onClick="showClasses();">Show div classes</button>
HTML
<div class="foo bar">This div has foo, bar classes</div>
Vanilla JavaScript. It will return an array of classes.
const div = document.querySelector('div');
const classes = div.className.split(" "); // ['foo', 'bar']

Related

Target multiple elements from the style of element

Lets say i have multiple divs with the same class like
<div class="myDiv">1</div>
<div class="myDiv">2</div>
<div class="myDiv" style="display:none">3</div>
<div class="myDiv">4</div>
And here i want to target the div that has display:none which is the third div <div class="x" style="display:none">3</div>
I tried using this
const elements = document.querySelectorAll('.myDiv');
const element = elements.find(element => element.style.display == "none");
console.log(element)
but i got an error saying
elements.find is not a function
i tried to console.log the style of the elements to check the styles
const elements = document.querySelectorAll('.myDiv');
elements.forEach(element => console.log(element.style.display));
and it outputs this which is correct
""
""
"none"
""
But why doesn't the code that i tried work and why is elements.find not a function?
but i got an error saying
elements.find is not a function
That's because the NodeList returned by querySelectorAll isn't an array, it's a NodeList. You could create an array from it before doing the find:
const elements = document.querySelectorAll('.myDiv');
const element = [...elements].find(element => element.style.display == "none");
// −−−−−−−−−−−−−^^^^−−−−−−−−^
console.log(element);
That works because NodeList instances are iterable, so you can use spread notation to expand them into an array literal. (Other options are Array.from(elements), Array.prototype.slice.call(elements), or just using a for loop.)
You can also narrow your selector from .myDiv to .myDiv[style] so it only matches .myDiv elements that have a style attribute.
Ideally, though, if you can change things so that you don't have that inline style in the first place, I'd do that. For instance, if you use a class to hide the element:
<div class="myDiv">1</div>
<div class="myDiv">2</div>
<div class="myDiv hidden">3</div>
<div class="myDiv">4</div>
where hidden is defined as :
.hidden {
display: none;
}
then you can ask the browser for the specific element you're interested in:
const element = document.querySelector(".myDiv.hidden");
Another way is to use Array.from
like so :
const elements = document.querySelectorAll('.myDiv');
const element = Array.from(elements).find(element => element.style.display == "none");
console.log(element)
Try that it's will diplay none the div number 3, any way you can use id as well to display none
<div class="myDiv">1</div>
<div class="myDiv">2</div>
<div class="myDiv" style="display:none">3</div>
<div class="myDiv">4</div>
JS***
let myDiv = document.getElementsByClassName("myDiv");
myDiv[2].style.display = "none";

JavaScript: querySelector - match also the top element

Is it possible for querySelector to somehow match also the top element? So for example:
Element:
<div class="container">
<div>Something</div>
</div>
JavaScript:
const container = element.querySelector('.container');
This won't match anything, because "container" is the top element. Is there an elegant way of querying element, that would test not only its children, but also the top element? I'm talking pure JavaScript.
You can test whether the selector refers to the top-level, and use a conditional expression:
const container = element.matches(".container") ? element : element.querySelector(".container");
For querySelectorAll you can do:
const containers = [...(element.matches(".container") ? [element] : []), ...element.querySelectorAll(".container")];
This returns an array instead of a NodeList, but for most purposes that difference shouldn't matter.
Not really elegant, but this would work.
If we resort to element.parentNode we would not guarantee targeting only the element.
//dummy up
const element = document.querySelector('.container');
const container = element.querySelector('.container');
const container2 = element.querySelector('.container')||(element.classList.contains('container')) ? element : null;
console.log(container);
console.log(container2);
<div class="container">
<div>Something</div>
</div>
const container = element.querySelector('.container');

JavaScript tag system: show only the divs that have all the classes listed in an array, else hide

Please explain how to do this!
I want to be able to hide/show a div based on its classes and an array.
If something is in an array, then it will only show divs which have the something class.
If nothing is in an array, every div will be shown.
If something and johnskeet are in the array, then it will only show divs which have both the something and johnskeet classes.
At a high level, one option would to have all of the divs hidden by default and then use document.querySelectorAll() to apply an 'unhidden' style to each div that is in the array.
Here is a question that should help with selecting divs with multiple classes that should help as well.
queryselectorAll - find an element with more than one matching class
I would recommend you to dynamically generate appropriate selector from the array, show all the matching elements and hide all other elements by default:
JavaScript
const classes = ['foo', 'bar', 'baz']
,selector = classes.map(x => '.' + x).join('')
$(selector).show()
CSS
div {
display: none;
}
See demo on JS Fiddle.
Alternatively, if you work on a high amount of elements, it would be better to generate appropriate style sheet in JavaScript:
const classes = ['foo', 'bar', 'baz']
,selector = classes.map(x => '.' + x).join('')
,$style = $(`<style>div {display: none;} div${selector} {display: block;}</style>`)
$('head').append($style)
To revert that, simply remove the <style> element by calling $style.remove().
See demo on JS Fiddle.
Assuming the elements are initially shown, you only need to hide the undesired ones. You can insert a stylesheet with
var rule = array.map(c => 'div:not(.' + CSS.escape(c) + ')').join()
+ '{display:none}';
sheet.insertRule(rule, 0);
var array = ["something", "johnskeet"];
var rule = array.map(c => 'div:not(.' + CSS.escape(c) + ')').join() + '{display:none}';
var style = document.createElement('style');
document.head.appendChild(style);
var sheet = style.sheet;
sheet.insertRule(rule, 0);
<div class="foo">foo</div>
<div class="something">something</div>
<div class="something johnskeet">something johnskeet</div>
<div class="something foo bar johnskeet">something johnskeet foo bar</div>
However, if some elements may already be hidden, you will need to set the desired display with higher specificity. The problem is that some elements are by default block-level, and some are inline-level. jQuery's toggle can be helpful to detect that:
$('div').each(function() {
$(this).toggle(array.every(c => this.classList.contains(c)));
});
var array = ["something", "johnskeet"];
$('div').each(function() {
$(this).toggle(array.every(c => this.classList.contains(c)));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">foo</div>
<div class="something">something</div>
<div class="something johnskeet">something johnskeet</div>
<div class="something foo bar johnskeet">something johnskeet foo bar</div>
Another option would be display: revert, but it's not widely supported yet.
You may do as follows with pure JS. Run the code multiple times to see the results for randomly generated classArray.
var classes = ["something","johnskeet"],
classArray = classes.reduce((p,c) => Math.random() > 0.5 ? p.concat(c) : p,[]),
divs = document.querySelectorAll(".something, .johnskeet");
arrayStatus.textContent = "The current classes array is: " + JSON.stringify(classArray);
for (var div of divs) div.style.display = classArray.length === div.classList.length ? classArray.every(c => [...div.classList].includes(c)) ? "" : "none"
: !classArray.length ? "" : "none";
.something {background-color: paleGreen}
.johnskeet {background-color: tomato}
.something.johnskeet {background-color: thistle}
<p id="arrayStatus"></p>
<div class="something johnskeet">SJ</div>
<div class="johnskeet">J</div>
<div class="johnskeet">J</div>
<div class="something">S</div>
<div class="something">S</div>
<div class="johnskeet">J</div>
<div class="something johnskeet">SJ</div>
<div class="johnskeet">J</div>
<div class="something johnskeet">SJ</div>
No need to do anything fancy.
var array = ["something", "foo"];
Need to convert your array in such way that creates needed selector.
$('div').not("."+array.join(".")).hide();
Show element which has at-least once class from array.
$('div').not("."+array.join(",.")).hide();
If you've large amount of elements, you can use each() also.
var array = ["something", "johnskeet"];
var selector="";
$.each(array, function(key, value){
selector += "."+value;
});
console.log(selector);
$('div').not(selector).hide();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">foo</div>
<div class="something">something</div>
<div class="something johnskeet">something johnskeet</div>
<div class="something foo bar johnskeet">something johnskeet foo bar</div>
<div class="dummy">dummy</div>

Selecting second children of first div children in javascript [duplicate]

This question already has answers here:
querySelector with nested nth-child in Chrome doesn't appear to work
(2 answers)
Closed 3 years ago.
I have an html that look something like this:
<div id="mainDiv"> <-- I have this
<div>
<div></div>
<div></div> <-- I need to get this
</div>
<span></span>
<more stuff />
</div>
i am using:
var mainDiv = document.getElementById('mainDiv');
because I need that div in a var, but i also need to get that second div on the first div inside mainDiv into a variable.
How could I do it in a simple cross-browser way?
Assuming that structure is static you can do this:
var mainDiv = document.getElementById('mainDiv'),
childDiv = mainDiv.getElementsByTagName('div')[0],
requiredDiv = childDiv.getElementsByTagName('div')[1];
Further reading: .getElementsByTagName() (from MDN).
var mainDiv = document.getElementById('mainDiv');
var x = mainDiv.children[0].children[1];
or
var mainDiv = document.getElementById('mainDiv');
var x = mainDiv.getElementsByTagName('div')[0].getElementsByTagName('div')[1];
I would go simply with just one line of vanilla code.
Works for any elements, is not limited to the tag names you have in the structure. But the number of elements and the hierarchy must be preserved.
var requiredDiv = document.getElementById('mainDiv').firstChild.firstChild.nextSibling;
I would pick jQuery and end up with something like this:
var getThis = $('#mainDiv > div:eq(0) > div:eq(1)');
Fiddle
var mainDiv = document.getElementById('mainDiv');
var div = maindiv.getElementsByTagName('div')[2];//third div
http://jsfiddle.net/MGVw8/
You know there is querySelector now ?
console.log(
mainDiv.querySelector(':nth-child(1) > :nth-child(2)'))
<div id="mainDiv">
<div>
<div></div>
<div>come get me</div>
</div>
<!-- more stuff -->
</div>

How to search the children of a HTMLDivElement?

I have an HTMLDivElement, and my goal is to find a div nested beneath this.
Ideally I'd want something like getElementById, but that function doesn't work for HTMLDivElement.
Do I need to manually traverse the graph, or is there an easier way?
Demo: http://jsfiddle.net/ThinkingStiff/y9K9Y/
If the <div> you're searching for has a class, you can use getElementsByClassName():
document.getElementById( 'parentDiv' ).getElementsByClassName( 'childDiv' )[0];
If it doesn't have a class you can use getElementsByTagName():
document.getElementById( 'parentDiv' ).getElementsByTagName( 'div' )[0];
And if it has an id you can, of course, just use getElementById() to find it no matter where it is in the DOM:
document.getElementById( 'childDiv' );
//For immediate children
var children = document.getElementById('id').childNodes;
//or for all descendants
var children = document.getElementById('id').getElementsByTagName('*');
var div = ...
var divChildren = div.getElementsByTagName("div");
var divYouWant = [].filter.call(divChildren, function (el) {
return matchesSomeCondition(el);
});
Ideally, I'd want something like getElementById
And you can use getElementById just do document.getElementById(id) and since ids are unique that will find that single div item you wanted.
You can also use elem.getElementsByClassName to select a descendant of elem by class
You can use .querySelector(). The functions getElementById() and getElementByClassName() work perfectly fine on document, but they do not work on the child records returned by these functions. If you need many children elements, then consider .querySelectorAll()
Full Working Demo:
const topdiv = document.getElementById('top-div');
const seconddiv = topdiv.querySelector('#second-div');
seconddiv.innerHTML = '456';
<div id="top-div">
123
<div id="second-div">
abc
</div>
</div>
Demonstration of getElementById() Failing:
const topdiv = document.getElementById('top-div');
const seconddiv = topdiv.getElementById('second-div');
seconddiv.innerHTML = '456';
<div id="top-div">
123
<div id="second-div">
abc
</div>
</div>
Concise and readable:
document.getElementById('parentDiv').children[0];
Using .childNodes returns lots of extra children, whereas .children returns a smaller array.

Categories