user2513846
user2513846

Reputation: 1236

append "show more" link to truncated paragraph only if set amount of characters is met

I want to append the "show more" link (if clicked will reveal the content that has been trimmed/hidden) to my paragraph only if the X amount of characters are passed.

For example I set the minimum to 120 chars, and the paragraph has only 60 therefore I dont need to append the "show more" link.

How Can I solve it? The code below works great but will apply "show more" to any paragraph I have even though is less then the X amount.. What should I do?

https://jsfiddle.net/vm0uj7fc/1/

    var charLimit = 122;

function truncate(el) {
  var clone = el.children().first(),
      originalContent = el.html(),
      text = clone.text();
  el.attr("data-originalContent", originalContent);
  clone.text(text.substring(0, charLimit) + "...")
  el.empty().append(clone);
}

function reveal(el) {
  el.html(el.attr("data-originalContent"));
}

$("a").on("click", function (e) {
  e.preventDefault();
  var truncateElement = $(this).parent().prev().find(".truncate");
  if ($(this).text() === "Read More") {
      $(this).text("Read Less");
      reveal(truncateElement);
  } else {
      $(this).text("Read More");
      truncate(truncateElement);
  }
});

$(".truncate").each(function () {
    truncate($(this));
});

to recap:

Upvotes: 7

Views: 4393

Answers (4)

user2560539
user2560539

Reputation:

I just placed a small addition to your code

$(".truncate").each(function(){
if($(this).length < 122) {
  $(this).parent().next().find(".read-more").hide();    
  } 
});  

and changed this also

function truncate(el) {
  var clone = el.children().first(),
      originalContent = el.html(),
      text = clone.text();  
  if(text.length>charLimit) {
   el.attr("data-originalContent", originalContent);
   clone.text(text.substring(0, charLimit) + "...")
   el.empty().append(clone); 
   } 
}

Updated Fiddle

Upvotes: 0

Ibrahim Khan
Ibrahim Khan

Reputation: 20740

I've changed your js to following and it is working fine as your expectation. I've added comments after the changed lines.

var charLimit = 122;

function truncate(el) {
    var shortText = $('<p/>'), //create new <p/> instead of clone
      originalContent = el.html(),
      text = el.text().trim(); // take all text & trim starting and trailing white spaces

    if (text.length > charLimit) { //check char limit overflow
        el.next(".read-more").length || el.after('<div class="read-more"><a href="#" class="more">Read More</a>'); //append "Read More" button if not exist 
        el.attr("data-originalContent", originalContent);
        shortText.text(text.substring(0, charLimit) + "...")
        el.html(shortText); // use html() instead of empty() and append()
    }
}

function reveal(el) {
    el.html(el.attr("data-originalContent"));
}

$(".container").on("click", ".more", function (e) { //use delegated event for dynamically added "Read More" button
    e.preventDefault();
    var truncateElement = $(this).parent().prev(".truncate"); //change here as we added "Read More" button after ".truncate"
    if ($(this).text() === "Read More") {
        $(this).text("Read Less");
        reveal(truncateElement);
    } else {
        $(this).text("Read More");
        truncate(truncateElement);
    }
});

$(".truncate").each(function () {
    truncate($(this));
});

WORKING DEMO

Upvotes: 1

Ahmed Salama
Ahmed Salama

Reputation: 2825

I write a pure javascript that handle your request, see the demo here: https://jsfiddle.net/IA7medd/751sLn0n/

HTML:

<div class="container">
      <div class="events-left-col">
        <h2 class="eventTitle">Event Title</h2>
          <div class="wrap">
            <div class="truncate">
              <p class="toggledText">
                  Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod 
                  tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, 
                  quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo 
                  consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie 
                  consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto 
                  odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait 
                  nulla facilisi.
              </p>
            </div>
          </div>

          <div class="wrap">
            <div class="truncate">
              <p class="toggledText">
                  Not enough characters here to show/append the "Read more" link
              </p>

            </div>
          </div>

           <div class="wrap">
            <div class="truncate">
              <p class="toggledText">
                  Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod 
                  tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, 
                  quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo 
                  consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie 
                  consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto 
                  odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait 
                  nulla facilisi.
              </p>
            </div>
          </div>


        </div>
      </div>

style:

.toggledText span.trimmed{
  display:none;
}
.read-more .more:before{
  content:'Read More';
}
.showAll .toggledText span.morePoints{
  display:none;
}
.showAll .toggledText span.trimmed{
  display:inline;
}
.showAll .read-more .more:before{
  content:'Read Less';
}

script:

var charLimit = 120;

        var numberOfToggled = document.getElementsByClassName('toggledText');
        for(i=0; i<numberOfToggled.length; i++){

            var el = numberOfToggled[i];
            var elText = el.innerHTML.trim();

            if(elText.length > charLimit){
                var showStr = elText.slice(0,charLimit);
                var hideStr = elText.slice(charLimit);
                el.innerHTML = showStr + '<span class="morePoints">...</span> <span class="trimmed">' + hideStr + '</span>';
                el.parentElement.innerHTML = el.parentElement.innerHTML + "<div class='read-more'><a href='#' class='more'></a>";
            }

        }

        window.onclick = function(event) {
            if (event.target.className == 'more') {
                event.preventDefault();
                event.target.parentElement.parentElement.classList.toggle('showAll');

            }
        }

I also made some edits on your code and it work fine. you can see it here: https://jsfiddle.net/IA7medd/j78L76qj/ ( if you nedd it )

Upvotes: 5

brk
brk

Reputation: 50291

I have make some changes in your code.I have listed down the approch which me help you to understand

  1. Iterate through each .truncate
  2. Check if total character length is more than 122;
  3. If true remove the class normHeight & add class modHeight
  4. On click of the link remove the modHeight & add class 'normHeight'

This below snippet can be useful

var charLimit = 122;
function _truncate(el) {
      var _clone = el.children().first();
       //Removing white space & checking length
        // _clone[0] because _clone is array of jquery object
        if(_clone[0].innerHTML.trim().length>charLimit){  
           _clone.removeClass('normHeight').addClass('modHeight');
         //Appending read me link
          el.append($("<div class='read-more'><a href='#' class='more'>Read More</a>"));
       }
    }

    // Since a.more is dynamic element so using event delegation.
    $("body").on("click",'a.more',function (e) {
      e.preventDefault();
      $(this).parent().siblings('p.modHeight').removeClass('modHeight').addClass('normHeight');
      $(this).hide(); // Once entire text is visible remove read me link
    });

    $(".truncate").each(function () {
        _truncate($(this));
    });

Also note the minor change in HTML and CSS

Check this jsfiddle for demo

Upvotes: 1

Related Questions