Tylerbns
Tylerbns

Reputation: 7

How to change element text if contains multiple specific child

I am wanting to manipulate the comment text to show no comment only if it contains the default comment. That default comment is being hidden but adding to a counter. So it's hidden I want the comments to show No Comments, even though the counter may be at 3. Hope this makes sense.

I currently have this jQuery

$("p:contains('Default Comment')").parent().hide(); 

Here is my code example of what I have:

<div id="parent">
   <h4>Comments</h4>
   <ul>
    <li style="display:none;>Default Comment</li>
    <li style="display:none;>Default Comment</li>
    <li style="display:none;>Default Comment</li>
  </ul>
</div>
<div id="parent">
  Comments
  <ul>
    <li>Custom Comment</li>
    <li style="display:none;>Default Comment</li>
    <li>Custom Comment</li>
  </ul>

Here is what I want to have happen

<div id="parent">
 <h4>**No Comments**</h4>
  <ul>
    <li style="display:none;>Default Comment</li>
    <li style="display:none;>Default Comment</li>
    <li style="display:none;>Default Comment</li>
  </ul>
</div>
<div id="parent">Comments</div>
  <ul>
    <li>Custom Comment</li>
    <li style="display:none;>Default Comment</li>
    <li>Custom Comment</li>
  </ul>
</div>

Any guidance is greatly appreciated

Upvotes: 0

Views: 121

Answers (2)

mdziekon
mdziekon

Reputation: 3627

HTML's text is actually wrapped inside an invisible textNode, which you can access using element's childNodes property.

In your case, it would look like this:

var commentsParent1 = document.querySelector("div.parent:nth-child(1)");

// Text node is the first child in this case
var textNode = commentsParent1.childNodes[0];

// Now we can modify it's text content
textNode.textContent = "**No Comments**";

Edit: after seeing further clarification about the problem.

To detect that comments section has "default comments only" and replace it's "label" accordingly, you have to loop through the contents of the list. To make it more readable, you can wrap this inside a function that operates on a single comments section:

function updateCommentsSection (commentsSection) {
    // Select all comments in the list
    var comments = commentsSection.querySelectorAll("ul li");

    // Convert nodesList to an instance of Array
    var commentsArray = [ ...comments ];

    // Detect non-default comments
    var hasNonDefaultComment = commentsArray.some(function (comment) {
        return comment.textContent !== "Default Comment";
    });

    if (hasNonDefaultComment) {
        // No need to change anything
        return;
    }

    // Default comments only, change the content of the parent
    var textNode = commentsSection.childNodes[0];

    textNode.textContent = "**No Comments**";
}

// Example call to the function, you can use another for-loop to iterate over all the comment sections
updateCommentsSection(document.querySelector("div.parent:nth-child(1)"));

// Example loop that iterates over all comment sections
[ ...document.querySelectorAll("div.parent") ].forEach(function (commentsSection) {
    updateCommentsSection(commentsSection);
}

Upvotes: 1

Rory McCrossan
Rory McCrossan

Reputation: 337733

To achieve this you can loop through the .parent elements and check to find the number of visible li elements within it. If there are none you can change the text in the first node. Try this:

$('.parent').each(function() {
  var comments = $(this).find('li:visible').length;
  $(this).contents()[0].textContent = comments ? 'Comments' : 'No Comments';
}); 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
  Comments
  <ul>
    <li style="display:none;">Default Comment</li>
    <li style="display:none;">Default Comment</li>
    <li style="display:none;">Default Comment</li>
  </ul>
</div>
<div class="parent">
  Comments
  <ul>
    <li>Custom Comment</li>
    <li style="display:none;">Default Comment</li>
    <li>Custom Comment</li>
  </ul>
</div>

Upvotes: 0

Related Questions