JavaScript
x
8
1
<div>div-1
2
<span>div-1-span-1
3
<div>div-1-span-1-div</div>
4
<span>div-1-span-1-span</span>
5
</span>
6
7
</div>
8
I am trying to search this DOM. My search criteria is innerText, which is “div-1”. If that innerText is found, then I want to return the value as “div-1-span-1-div” and “div-1-span-1-span” which are again the innerText. How to achieve this using Javascript.
Advertisement
Answer
While I’m unsure of the logic behind the requirements I believe the following code seems to do what you ask:
JavaScript
1
65
65
1
// declaring a named function that takes two arguments:
2
// selector: String, a CSS selector to determine the elements you're trying to search,
3
// needle: String, a string of text that you're searching for to identify a given element:
4
const findElementByText = (selector, needle) => {
5
6
// here we convert the iterable NodeList returned from document.querySelectorAll()
7
// into an Array, using the Array.prototype.from() method:
8
return Array.from(
9
// we pass the 'selector' argument to document.querySelectorAll()
10
// to find all matching elements within the document:
11
document.querySelectorAll(selector)
12
// we then filter the resulting Array, using Array.prototype.filter()
13
// which retains, or discards, Array-elements based on truthy/falsey
14
// results of assessments within:
15
).filter(
16
// using the anonymous Arrow function, we retrieve the childNodes of
17
// each found element-node returned from document.querySelectorAll(),
18
// 'el' is a reference to the current element-node of the Array of
19
// element-nodes over which we're iterating:
20
(el) => {
21
// here we declare a variable, converting the HTMLCollection returned
22
// by Node.childNodes into an Array of nodes in order to use Array-
23
// methods such as Array.prototype.some():
24
let children = Array.from(el.childNodes);
25
26
// we use Array.prototype.some() to test if some of the Array-elements
27
// match the supplied tests; if so the method returns a Boolean true
28
// otherwise, if no Array-element matches, it returns a Boolean false:
29
return children.some(
30
// here we use the anonymous Arrow function, and we check that some
31
// of the childNodes (referenced as 'child' within the function body)
32
// are of nodeType === 3 (a textNode) and that the childNode's nodeValue
33
// once trimmed of leading/trailing whitespace is equal to the
34
// supplied String:
35
(child) => child.nodeType === 3 && child.nodeValue.trim() === needle
36
);
37
// here we use Array.prototype.map() to construct a new Array based on
38
// the Array-elements retained by Array.prototype.filter():
39
}).map(
40
// again, using an anonymous Arrow function, passing a reference to
41
// the current element-node into the function:
42
// first we create an Array from the iterable HTMLCollection of the
43
// current element-node's children:
44
(el) => Array.from(
45
el.children
46
// we then use Array.prototype.map() to create a new Array
47
// based on those childNodes:
48
).map(
49
// here we create another Array from the children of the
50
// previous child (since you seem to explicitly want the
51
// child-elements of the <span> in your posted code:
52
(child) => Array.from(child.children)
53
// we then use Array.prototype.flat() to collapse the Array
54
// to only one-dimension:
55
).flat()
56
// and then again, we use Array.prototype.map() to map the
57
// textContent of each child:
58
.map(
59
(child) => child.textContent.trim()
60
// and finally we flatten the multidimensional Array:
61
).flat()
62
).flat();
63
};
64
65
console.log(findElementByText('div', 'div-1'));
JavaScript
1
25
25
1
*,
2
::before,
3
::after {
4
box-sizing: border-box;
5
font-size: 1rem;
6
line-height: 1.5;
7
margin: 0;
8
padding: 0;
9
}
10
11
div,
12
span {
13
border: 1px solid var(--indicator);
14
display: block;
15
width: 90%;
16
margin: 0.2em auto;
17
}
18
19
div {
20
--indicator: lime;
21
}
22
23
span {
24
--indicator: lightblue;
25
}
JavaScript
1
6
1
<div>div-1
2
<span>div-1-span-1
3
<div>div-1-span-1-div</div>
4
<span>div-1-span-1-span</span>
5
</span>
6
</div>
References: