0

Objective

  • Reduce long text to six words, with a "...show more"
  • Way to collapse the text again after being expanded

Summary

I want to cut the text to show a ".. read more" link that expands the content. This should cut off based on the number of words, not characters. I want to display only the first 6 words.

I also need to expand the collapse the text again by clicking a "show less" button.

Current state

I have this working on my development site, but I had to cut to 36 which is an approximation to get to 6 words. I set up this demo on codepen

Previous research

I searched various similar questions but address how to collapse based on characters, not word count. For example, Using javascript substring() to create a read more link

And I read this but unclear as to how to integrate that back into my project: javascript shorten string without cutting words



Code

HTML

<p class="ticket-text">Bacon ipsum dolor amet beef ribs shankle shoulder, chicken meatloaf andouille meatball. Filet mignon pork tenderloin prosciutto porchetta andouille, strip steak tri-tip biltong beef ribs shoulder doner t-bone alcatra kevin.</p>

Javascript

$(function(){
    $('.ticket-text').each(function(event){
        var max_length = 36;

        if($(this).html().length > max_length){

            var short_content   = $(this).html().substr(0,max_length);
            var long_content    = $(this).html().substr(max_length);

            $(this).html(short_content+
                    '<a href="#" class="read_more">...<br>[Read More]</a>'+
                    '<span class="more_text" style="display:none;">'+long_content+'</span>');

            $(this).find('a.read_more').click(function(event){ 
                event.preventDefault();
                $(this).hide();
                $(this).parents('.ticket-text').find('.more_text').show();
            }); 
        }   
    });
});
Community
  • 1
  • 1
JGallardo
  • 11,074
  • 10
  • 82
  • 96

2 Answers2

2

You can just split the words and do the show More when you have more than 6 words, and then change to Show Less so you can hide the long text again:

$('.ticket-text').each(function(){
 var words = $(this).text().split(" ");
    var maxWords = 6;
    
    if(words.length > maxWords){
        html = words.slice(0,maxWords) +'<span class="more_text" style="display:none;"> '+words.slice(maxWords, words.length)+'</span>' + '<a href="#" class="read_more">...<br/>[Read More]</a>'
    
        $(this).html(html)
    
     $(this).find('a.read_more').click(function(event){
            $(this).toggleClass("less");
            event.preventDefault();
            if($(this).hasClass("less")){
             $(this).html("<br/>[Read Less]")
                $(this).parent().find(".more_text").show();
            }else{
             $(this).html("...<br/>[Read More]")
                $(this).parent().find(".more_text").hide();
            }
        })
    
    }
    
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<p class="ticket-text">Bacon ipsum dolor amet beef ribs shankle shoulder, chicken meatloaf andouille meatball. Filet mignon pork tenderloin prosciutto porchetta andouille, strip steak tri-tip biltong beef ribs shoulder doner t-bone alcatra kevin.</p>
<p class="ticket-text">short text</p>

To handle commas and dots, you could do something like this:

var words = $(this).text().replace(".").replace(",").split(" ").filter(function(a){return a});

This will replace all dots and commas for white spaces, then split by whitespaces, and then filter out the empty strings to keep only the words

juvian
  • 15,875
  • 2
  • 37
  • 38
  • This is helpful. The new challenge now is that the words now have a comma (sometimes 2) added after each word and no spacing between the words. – JGallardo Oct 16 '15 at 17:41
  • @JGallardo updated. You would need to do other stuff to keep the commans and dots on the text though – juvian Oct 16 '15 at 17:50
  • sorry this is new to me. I am curious where the commas are being generated from anyways. I am happy to have this cut down to six words, but the new problem of added commas and no spaces seem to add an problem. Your second line removes periods but I cant do that because it is a paragraph, so that would make it entirely unreadable. – JGallardo Oct 16 '15 at 18:01
  • @JGallardo yeah its a bit harder to do that. The example on jsfiddle works, although the text is not exactly replicated as in original, its understandable. You could make your own function to append words+space or the comma and dot without space instead of words.slice().join(" ") and it would look better – juvian Oct 16 '15 at 18:07
  • ok your example on jsfiddle works well. for some reason it is adding random spaces before a few commas and periods when I used this code on my page. But this is great, thank you. – JGallardo Oct 16 '15 at 18:09
  • @JGallardo no problem, here is a more manual version that keeps text without changing it: http://jsfiddle.net/sLaapxff/1/ – juvian Oct 16 '15 at 18:25
0

You can split the words according to max word count and have 2 string namely shortStr and longStr, then you can add read more in the html. This will also not generate any commas.

$('.ticket-text').each(function () {
  // var words = $(this).text().split(' ')
  var words = $(this)
    .text()
    .replace('.')
    .replace(',')
    .split(' ')
    .filter(function (a) {
      return a
    })
  var maxWords = 6
  var shortStr = words.slice(0, maxWords).join(' ')
  var longStr = words.slice(maxWords, words.length).join(' ')
  if (words.length > maxWords) {
    html =
      shortStr +
      '<span class="more_text" style="display:none;"> ' +
      longStr +
      '</span>' +
      '<a href="#" class="read_more">...<br/>[Read More]</a>'

    $(this).html(html)

    $(this)
      .find('a.read_more')
      .click(function (event) {
        $(this).toggleClass('less')
        event.preventDefault()
        if ($(this).hasClass('less')) {
          $(this).html('<br/>[Read Less]')
          $(this).parent().find('.more_text').show()
        } else {
          $(this).html('...<br/>[Read More]')
          $(this).parent().find('.more_text').hide()
        }
      })
  }
})