Mark Boulder
Mark Boulder

Reputation: 14277

jQuery: Checking for `nodeType == 3` in a function

Expanding Using .text() to retrieve only text not nested in child tags -- how do I turn the answer about checking for nodeType == 3 into a function?

function hasText(element) {
    element.contents().filter(function () {
        if (element.contents().nodeType == 3) {
            return true
        }
    });
}

$('p').each(function () {
  if(hasText($(this))) {
    $(this).css('border', '5px solid blue');
  }
});
<!-- Should return true -->
<p>Hello</p>
<p>Hello <a>there</a></p>

<!-- Should return false -->
<p><a>Hello</a></p>
<p><a href="#"><img src="#"></a>

Upvotes: 1

Views: 896

Answers (2)

David Thomas
David Thomas

Reputation: 253318

I'd suggest:

function hasOnlyText(element) {
  // checking if the number of contents of the element is equal to
  // the number of contents that are textNodes:
  return element.contents().length === element.contents().filter(function() {
    return this.nodeType && this.nodeType === 3;
  }).length;
}

function hasOnlyText(element) {
  return element.contents().length === element.contents().filter(function() {
    return this.nodeType && this.nodeType === 3;
  }).length;
}

$('p').each(function() {
  console.log(hasOnlyText($(this)));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Should return true -->
<p>Hello</p>

<!-- Should return false -->
<p><a>Hello</a>
</p>

Alternatively, based on the clarification provided in the comments below:

function hasText(element) {
  return element.contents().filter(function() {
    return this.nodeType && this.nodeType === 3 && this.nodeValue.trim().length > 0;
  }).length;
}

function hasText(element) {
  return element.contents().filter(function() {
    return this.nodeType && this.nodeType === 3 && this.nodeValue.trim().length > 0;
  }).length > 0;
}

$('p').each(function() {
  console.log(hasText($(this)));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Should return true -->
<p>Hello</p>

<!-- Should return false -->
<p><a>Hello</a>
</p>

<!-- Should also return true -->
<p>Paragraph text <a>Link text</a>
</p>

References:

Upvotes: 1

Ry-
Ry-

Reputation: 224904

You need to return a value. Also, Array.prototype.every might be more appropriate than filter.

function hasText(element) {
    return Array.prototype.every.call(element.contents(), function (c) {
        return c.nodeType === 3;
    });
}

$('p').each(function () {
    if (hasText($(this))) {
        $(this).css('border', '5px solid blue');
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- Should return true -->
<p>Hello</p>

<!-- Should return false -->
<p><a>Hello</a></p>

Upvotes: 1

Related Questions