Reputation: 58522
<p id='1'></p>
<p id='1a'><br /></p>
<p id='3success'><b>Match this</b></p>
<p id='3fail'><b>Match this</b> but not now because of this test</p>
I have some logic that needs to skip elements that meet the following conditions
I can easily handle 1/2 but the third I am having trouble with. I know how to assert the children part, $('#3fail').children().length
but I dont know how to determine if there is additional text.
Any suggestions on how to validate 3? I'm processing the element in a simple .each
function
$('p').each(function(){
var element = $(this)
if(matchesCondition(element)){
doLogic(element)
}
});
Note
Someone posted an answer and got a lot of upvotes but it does not work. Here is a fiddle to test out answers.
http://jsfiddle.net/ncapito/k87rc/
I was able to fix @Kolink s answer
http://jsfiddle.net/ncapito/9D3tg/
var getNontextNodes;
//coffeescript generated
getNontextNodes = function (nodes) {
var cnt, n, _i, _len;
cnt = 0;
for (_i = 0, _len = nodes.length; _i < _len; _i++) {
n = nodes[_i];
if (n.textContent.trim()) {
cnt++;
}
}
return cnt;
};
$("p").each(function () {
if (
(this.children.length === this.childNodes.length)
||
(getNontextNodes(this.childNodes) === this.children.length))
$(this).append("<b style='color:green'>Success</b>");
else
$(this).append("<b style='color:red'>Failed</b>");
});
Upvotes: 1
Views: 570
Reputation: 324650
You can check if an element only has element children by checking
if( this.children.length == this.childNodes.length)
, because children[]
only counts element children, while childNodes[]
includes text nodes too.
Once you've cleared this step, you can iterate through the children[]
array and check their tagName
to see if they're in your list.
EDIT: I've just noticed, this will not allow any whitespace, such as newlines, between elements. If you want to allow whitespace but not actual text, try this check instead:
if( !(this.textContent || this.innerText).match(/\S/))
No, that won't work. This will, though:
var filter = [].filter ? [].filter : function(cb) {for( var i=0, l=this.length, ret=[]; i<l; i++) {if(cb(this[i])) ret.push(this[i]);} return ret;};
$("p").each(function(){
if( this.children.length == this.childNodes.length || filter.call(this.childNodes,function(n) {return n.nodeType == 3 && n.nodeValue.match(/\S/);}).length == 0)
$(this).append("<b style='color:green'>Success</b>")
else
$(this).append("<b style='color:red'>Failed</b>")
});
Upvotes: 6