getElementsByClassName
Search all children of targetElement for all elements with classNames
by rustyjeans
HTML
<div id="target">
<div class="a b c">
<div class="b c">1</div>
<div class="c a">2</div>
<div class="a b">3</div>
</div>
<div class="d e f">
<div class="b c">4</div>
<div class="c a">
<div class="b c">5</div>
<div class="c a">6</div>
<div class="a b">7</div>
</div>
<div class="a b">8</div>
</div>
</div>
CSS
div {
border: 1px solid #000;
margin: 10px;
padding: 20px;
}
TypeScript
/**
* Search all children of targetElement for all elements with classNames
* @param {HTMLElement} targetElement
* @param {string} classNames - Class names seperated by spaces
*/
const getElementsByClassName = (targetElement, classNames) => {
// check that the traget element is an HTMLElement
if (!targetElement instanceof HTMLElement) {
throw new Error("target element not an instance of HTMLElement");
}
// validate that className is a string
if (typeof classNames !== 'string') {
throw new Error('classNames must be a string')
}
// store class names in an array by spliting classNames by space
const classNamesArr = classNames.trim().split(/\s+/);
const _recursiveGetElementsByClassName = (targetElement, classNamesArr) => {
let returnElements = [];
// check each child to see if it has the class names provided
targetElement.childNodes.forEach(childNode => {
// if node type is an element
if (childNode.nodeType === Node.ELEMENT_NODE) {
let matched = true;
// store child class name is hash for faster access
let childClass = childNode.className.trim().split(/\s+/).reduce((hash, value) => {
hash[value] = true;
return hash;
}, {});
// compare all input classNames to see if they have all of them
for (let i = 0; i < classNamesArr.length; i++) {
if (!childClass[classNamesArr[i]]) {
matched = false;
break;
}
}
if (matched) {
returnElements.push(childNode);
}
// call this function on all child nodes
if (childNode.hasChildNodes()) {
returnElements = [...returnElements, ..._recursiveGetElementsByClassName(childNode, classNamesArr)];
}
}
});
return returnElements;
}
return _recursiveGetElementsByClassName(targetElement, classNamesArr);
};
console.log("a b", getElementsByClassName(document.getElementById("target"), "a...