i am trying to check if a selected element have text inside it , the problem is when i am trying to checking value by innerText
its also returning values from child which is why boolean function is returning true but what i am expecting to do is just verify one element and avoiding child's i hope i have exlpained it correct so what can be a proper way to achive this
const main = document.querySelector(".main")
const first = main.querySelector(".selected")
const second = main.querySelector(".another")
const third = main.querySelector(".another-one")
function hasText(el){
return el.innerText != ""
}
console.log(hasText(first),hasText(second),hasText(third)) // true true true expected result is = [true false,true]
<div >
<div >
i have text inside me
</div>
<div >
<div >i am inside a child</div>
</div>
<div >
i am inside another one
<div >i am inside a child</div>
</div>
</div>
CodePudding user response:
There are several options to achieve your goal. You could just check if el
has children elements and in case .children.length > 0
just consider it as a text container and measure its innerText
length.
But in case those parent elements are also supposed to optionally contain both children elements and text, you should check every single childNode of theirs, verify if that's a text portion and consider that text to be part of parent content.Those nodes will be text portions sparse in between legit children elements.
There's also the textContent
property of Node that could give you an information similar to that returned by my function grabPureTextContent
but there are caveats that I preferred to cut off implementing my own logic.
https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
Here's a demo adding such function to your code and using its logic to determine if a given element has text content or not.
I added a third case (.special) showing what happens when there's mixed content.
const main = document.querySelector(".main")
const first = main.querySelector(".selected")
const second = main.querySelector(".another")
const third = main.querySelector(".special")
/*
Returns the pure text content defined in el
looping through its childNodes and concatenating content,
(if child is text only) before returning the whole string.
There's also the option to use textContent property of Node
https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
But here the algorithm is more clear on what's going on
*/
function grabPureTextContent(el){
let content = '';
for(childText of el.childNodes){
if (childText.constructor.name == 'Text'){
content = childText.nodeValue.trim();
}
}
return content;
}
function hasText(el){
if (grabPureTextContent(el).length > 0)
return true;
return false;
}
console.log(hasText(third)) //=> true
console.log(hasText(second)) //=> false
console.log(hasText(third)) //=> true
.main > div {
border: solid 1px gray;
margin-bottom: 1em;
}
.container {
background: lightgreen;
}
.child {
background: lightpink;
}
<div >
<div >
i have text inside me
</div>
<div >
<div >i am inside a child</div>
</div>
<!-- special case having both children and text -->
<div >
<div >i am inside a child</div>
TEXT HERE after child
</div>
</div>
CodePudding user response:
I would test if some tags inside the string. If not you can use your check if is empty.
const main = document.querySelector(".main")
const first = main.querySelector(".selected")
const second = main.querySelector(".another")
const third = main.querySelector(".another2")
function hasText(el) {
const pattern = /<.*>.*<\/.*>/;
return pattern.test(el.innerHTML) ? false : (el.innerText != "");
}
console.log(hasText(first),hasText(second), hasText(third)) // true true expected result is = [true false true]
<div >
<div >
i have text inside me
</div>
<div >
<div >i am inside a child</div>
</div>
<div >
i am inside a child
</div>
</div>