2

I'm trying to apply a class to all elements which contain text or which contain text and other dom elements inside. At least there must be some sort of text inside the element.

This div should get the class:

<div class="theClass">Some text</div>

This div should get the class too:

<div class="theClass">Some text<div class="theClass more">More text</div></div>

But this one should only give the child div the class:

<div class=""><div class="theClass more">More text</div></div>

At the moment i'm using the :hasText selector which i found here finding elements with text using jQuery.

jQuery.expr[':'].hasText = function(element, index) {
// if there is only one child, and it is a text node
if (element.childNodes.length == 1 && element.firstChild.nodeType == 3) {
   return jQuery.trim(element.innerHTML).length > 0;
}
   return false;
};

But it only returns elements which contain text. I like to have elements which contain text and other elements (if there are any).

Thanks!

Community
  • 1
  • 1
Rein
  • 71
  • 5

3 Answers3

0

I don't get it fully but could it be like this:

<div ><div class="more">More text</div></div>

<div >Some text<div class="more">More text</div></div>

jQuery.expr[':'].hasText = function(element, index) {
    // if there is only one child, and it is a text node
    if (element.firstChild != null) {
        if (element.firstChild.nodeType == 3) {
            return jQuery.trim(element.innerHTML).length > 0;
        }
    }
    return false;
};

$('div:hasText').addClass('theClass')

You get:

  <div><div class="more theClass">More text</div></div>

<div class="theClass">Some text<div class="more theClass">More text</div></div>
Nicola Peluchetti
  • 76,206
  • 31
  • 145
  • 192
  • Thanks I tried that myself too but the it errors: element.firstChild is null – Rein Sep 22 '11 at 08:55
  • Ah I see. It's because I like to use: $('*:hasText').addClass('theClass') – Rein Sep 22 '11 at 08:59
  • We are almost there :) I updated to code to show you that a div with an image inside also gets theClass. Because of the whitespace :) See: http://jsfiddle.net/vSXd5/3/ - if you put everything togheter like
    it doesn't get the class.
    – Rein Sep 22 '11 at 09:30
0

i was trying like this.

 // content - children == no.of. text nodes.
    $.fn.islooseTextInside = function(c){
        jq = this;
        jq.each(function(){
            var $th = $(this);
            //no text nodes
            if(($th.contents().length - $th.children().length)  == 0){
                $th.children().islooseTextInside();
            }
            //only text nodes
            if($th.contents().length &&  $th.children().length == 0){
                applyClass($th)
            }
            //both are present
            if(( $th.contents().length - $th.children().length  ) > 0 ){    
                applyClass($th)
                $th.children().islooseTextInside();
            }
        })

        function applyClass(o){
            o.addClass('theClass')
        }
    }
    $("body div").islooseTextInside();

Sample HTML:

<body>
    <div>Some text</div>
    <div>Some text<div>Some text</div></div>
    <div><div>Some text</div></div>
</body>
Rajkamal Subramanian
  • 6,884
  • 4
  • 52
  • 69
0

With some help of Nicola Peluchetti I managed to fix it with the following functions, but it's still not the best!

jQuery.fn.cleanWhitespace = function() {
    textNodes = this.contents().filter(
    function() { return (this.nodeType == 3 && !/\S/.test(this.nodeValue)); })
    .remove();
    return this;
}

jQuery.expr[':'].hasText = function(element, index) {
// if there is only one child, and it is a text node
   $(element).cleanWhitespace();
   if (element.firstChild != null) {
        if (element.firstChild.nodeType == 3) {
            return jQuery.trim(element.innerHTML).length > 0;
        }
   }
   return false;
};

So first clean all the whitespaces because <div> <img src="noimage"></div> would be a text element to if you don't clean it (because of the space).

You should make the function call itself again when the firstChild isn't a nodeType 3.. but i'm working on it. Will post the solution here!

Rein
  • 71
  • 5