1

I'm trying to add a "Read more" link when HTML text exceeds about 50 characters and after the last closing tag.

$(document).ready(function(){
  var maxLength = 50;
  $(".html-text").each(function(){
  var myStr = $(this).html();
  if($.trim(myStr).length > maxLength){
    var newStr = myStr.substring(0, maxLength);
    var removedStr = myStr.substring(maxLength, $.trim(myStr).length);
    $(this).empty().html(newStr);
    $(this).append('<a href="javascript:void(0);" class="read-more">Read more</a>');
    $(this).append('<span class="more-text">' + removedStr + '</span>');
  }
});
$(".read-more").click(function(){
  $(this).siblings(".more-text").contents().unwrap();
  $(this).remove();
});
});
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="html-text">
<p>John has a red and white car that goes really fast.</p> <p>He needs to be careful.</p>
</div>

My result:

<div class="html-text">
   <p>John has a red and white car that goes really fas <a href="javascript:void(0);" class="read-more">Read more</a>
</div>

Expected result:

<div class="html-text">
    <p>John has a red and white car that goes really fast.</p> <a href="javascript:void(0);" class="read-more">Read more</a>
</div>

Any idea? Hope I made myself clear.

Rubyx
  • 708
  • 1
  • 11
  • 32

3 Answers3

1

I think could approach this a different way:

What you need seems to be the last text within a tag and not just the text. This means that you probably want to check for the tags and then the text size. You can check each child of the parent node until the HTML string reaches your max length and then output the entire child. This way, you a guaranteed you'll get a full HTML. Hope the function below helps

function findRequestedChild(el) {
  var cs = el.children();
  var textLength = 0;

  for (var i = 0; i < cs.length; i++) {
    var c = cs[i];
    textLength += $(c).html().length;

    if(textLength > 50) {
      break;
    }
  }

  return $(c).html();
}

alert(findRequestedChild($(".html-text")));
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="html-text">
<p>John has a red and white car that goes really fast.</p> <p>He needs to be careful.</p>
</div>
ren.rocks
  • 772
  • 1
  • 7
  • 22
0

I think that you need to use .text() function and not html(). With the first you’ll take only text without tags.

Marco Moretti
  • 689
  • 4
  • 11
  • I can't use .text() because I need to keep tags in my text. For example

    etc...

    – Rubyx Feb 03 '20 at 21:55
  • So maybe you can loop on children of .html-text and check if substring is greater than max. If not save length and go on the next child. In this way you will consider only text without tag but you’ll preserve tags. Do you have only one level of children ? – Marco Moretti Feb 03 '20 at 22:00
  • No I have multiple children level. – Rubyx Feb 03 '20 at 22:01
0

I wanted to see if I could come up with a CSS only solution, but despite trying out various ideas using:

  • display: flex
  • order
  • z-index
  • opacity

I gave up in the end and wrote the following javascript solution instead...

Working Example:

let textsToTruncate = [... document.getElementsByClassName('text-to-truncate')];

for (textToTruncate of textsToTruncate) {

  if (textToTruncate.textContent.length > 50) {
  
    textToTruncate.textContent = textToTruncate.textContent.substr(0, 50);
    
    textToTruncate.nextElementSibling.style.opacity = '1';
    textToTruncate.nextElementSibling.style.pointerEvents = 'auto';
  }
}
p {
  float: left;
  display: inline-block;
}

.text-to-truncate {
  clear: both;
}

.read-more {
 width: 120px;
 opacity: 0;
 pointer-events: none;
}
<p class="text-to-truncate">To live will be an awfully big adventure.</p>
<p class="read-more">...&nbsp; <a href="/link-1/">Read More</a></p>

<p class="text-to-truncate">Change the game, don’t let the game change you.</p>
<p class="read-more">...&nbsp; <a href="/link-2/">Read More</a></p>

<p class="text-to-truncate">The meaning of life is to give life meaning.</p>
<p class="read-more">...&nbsp; <a href="/link-3/">Read More</a></p>

<p class="text-to-truncate">Change the world by being yourself.</p>
<p class="read-more">...&nbsp; <a href="/link-4/">Read More</a></p>

<p class="text-to-truncate">Every moment is a fresh beginning.</p>
<p class="read-more">...&nbsp; <a href="/link-5/">Read More</a></p>

<p class="text-to-truncate">Never regret anything that made you smile.</p>
<p class="read-more">...&nbsp; <a href="/link-6/">Read More</a></p>

<p class="text-to-truncate">Dream as if you’ll live forever, live as if you’ll die today.</p>
<p class="read-more">...&nbsp; <a href="/link-7/">Read More</a></p>
Rounin
  • 27,134
  • 9
  • 83
  • 108