Carter Steinhoff Carter Steinhoff - 18 days ago 6
jQuery Question

how to limit scope of jQuery function to one instance of a class at a time

I'm working on more / less buttons for text in jQuery. When my jQuery script is loaded, I want to only display some of the of the text in a div. In this case, any text > 650 characters I want to hide initially. After a button is clicked, all the text will appear. When it is clicked again, the text will condense to original partially hidden size. I'm having trouble figuring out how to have the jQuery function run separately for each class iteration. As of right now, both classes text gets replaced with the text from first DIV. I need to limit the functions scope to just one class at a time.

Any suggestions?

Here is a fiddle detailing my problem - https://jsfiddle.net/carbot3000/q6k8yr9o/40/

Here is the function I'm referring to -

jQuery('.reviewbody').each(function() {
console.log(h);
if (rvwbody.length > showChar) {
jQuery(".btnMore").show();
jQuery(this).html(c);
console.log(c);

Answer

Ok here is a working example:

jQuery(document).ready(function() {
  var showChar = 50; // How many characters are shown by default
  var ellipsestext = "...";

  jQuery('.reviewbody').each(function() {
    var rvwElem = jQuery(this);
    var fullVal = rvwElem.html();
    var truncatedVal = fullVal.substr(0, showChar);

    console.log(fullVal);
    if (fullVal.length > showChar) {
      debugger;
      $(rvwElem).next(".btnMore").first().show().on('click', function() {
          jQuery(this).html(jQuery(this).text() == 'View Less' ? 'View More' : 'View Less');
          jQuery(".home_testimonial_section .home_testimonial_slider_wrap").toggleClass("rvwHeight");
          $(rvwElem).html($(rvwElem).html() == truncatedVal ? fullVal : truncatedVal);
          console.log(fullVal);
        });
    }

    // You still want to show the content if it is shorter than "showChar"
    $(rvwElem).html(truncatedVal);
    console.log(truncatedVal);
  });
});
.morecontent span {
  display: none;
}

.morelink {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="home_testimonial_slider_wrap">

  <div class="mySlides w3-animate-fading">
  </div>
  <div class="reviewbody">12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing12345testing
  </div>

  <button class="btnMore" style="display:none;">View More</button>

  <div class="mySlides w3-animate-fading">
  </div>
  <div class="reviewbody"> 6789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing67896789testing6789testing6789testing6789testing6789testing6789testing6789testing6789
  </div>
  <button class="btnMore" style="display:none;">View More</button>
</div>

The here the main things that were changed:

  • Variables were given proper names. Never use single letter variable names unless it is an iterator (ex. for(var i = 0; ...) )
  • The values for the text and the element were moved into the ".each" handler. This was needed so that you are not sharing variables between "reviewbody" elements.
  • Moved the click handler wireup for the "btnMore" into the each and used the "next" selector to get the next instance of it so we are only wiring up one button for each div. Also this way it has access to our "reviewbody" variables.
  • Moved the last "btnMore" div into the shared div container.