Wednesday, September 12, 2012

jQuery implementing show more - show less

This is a small tutorial on how to create a show-more and show-less feature.

In this example we will be using jQuery's toggleClass() to toggle between class objects. We will also be using jQuery UI's switchClass() for adding animation when toggling classes.

Content


Base HTML

Lorem ipsum dolor

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

Lorem ipsum dolor

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
The above HTML is a basic set of divs which each contain a title and textual content with a show more link.

back to top

Minimum CSS

Using the above HTML we can add the following CSS:
.text-content{
    line-height: 1em;
}

.short-text {
    overflow: hidden;
    height: 2em;
}

.full-text{
    height: auto;
}
The text-content class seta a line-height of 1em overall. Within the short-text class the total height is set to 2em and the overflow is hidden to ensure only 2 lines are visible. Within the full-text class we set the height to auto to ensure the full text is displayed. the other classes are not relevant

back to top

Using jQuery's toggleClass()

$(".show-more a").on("click", function() {
    var $link = $(this);
    var $content = $link.parent().prev("div.text-content");
    var linkText = $link.text().toUpperCase();
    
    $content.toggleClass("short-text, full-text");

    $link.text(getShowLinkText(linkText));
    
    return false;
});

function getShowLinkText(currentText){
    var newText = '';
    
    if (currentText === "SHOW MORE") {
        newText = "Show less";
    } else {
        newText = "Show more";
    }
    
    return newText;
}
​

The click event is attached to the anchor.

Within the click event we traverse to the outer div which has the text-content class and toggle the short-text and full-text classes by using jQuery's toggleClass().

This means that everytime the anchor is clicked either the short-text or full-text class is applied.

All the getShowLinkText method does is determine the text for the show more/less link. The new text is then passed to $link.text();

return false; is not required for the toggle but is my own preference to ensure the click event is not further propagated. Without that line the click on the show more/less link will always scroll back up to the top due to the href="#" attribute setting.

back to top

DEMO: Show More, Show Less


Feel free to play around on the result tab. Clicking the JavaScript, HTML or CSS tabs you will see the implementation details of each. If you would like to play around with the code to test your own solutions, click the "+" icon to open the actual fiddle for modification.


back to top

Using jQuery UI's switchClass()

$(".show-more a").on("click", function() {
    var $link = $(this);
    var $content = $link.parent().prev("div.text-content");
    var linkText = $link.text().toUpperCase();
    
    switchClasses($content);

    $link.text(getShowLinkText(linkText));
    
    return false;
});

function switchClasses($content){
    if($content.hasClass("short-text")){  
        $content.switchClass("short-text", "full-text", 400);
    } else {
        $content.switchClass("full-text", "short-text", 400);
    }
}

function getShowLinkText(currentText){
    var newText = '';
    
    if (currentText === "SHOW MORE") {
        newText = "Show less";
    } else {
        newText = "Show more";
    }
    
    return newText;
}
​

This is nearly identical to using toggleClass().

The only difference is that we are now using jQuery UI's switchClass() which removes the class, specified in the first argument and adds the class specified in the second argument.
The last argument is the duration, in milliseconds.

switchClass() will not only swap the classes but apply any style changes in an animation-like transition over the specified duration.

back to top

DEMO: Adding Animation


Feel free to play around on the result tab. Clicking the JavaScript, HTML or CSS tabs you will see the implementation details of each. If you would like to play around with the code to test your own solutions, click the "+" icon to open the actual fiddle for modification.


back to top

Additional Resources



Happy Coding.
back to top

23 comments :

  1. thank you it helped me keep posting

    ReplyDelete
  2. i am using this with pagination. and it does not work after going to another page. how can i fix this? thanx in advance

    ReplyDelete
    Replies
    1. Hi Zeynep.

      When you say pagination, I'm assuming you have a paged grid.

      Is that correct?

      Any additional details on your implementation would be very helpful.

      Would you be able to throw together a jsFiddle on http://jsFiddle.net that shows your issue?

      I'm more than happy to try and help you out but without seeing the implementation it's very hard.

      Delete
    2. thank you for your reply Fran.

      yes i also mentioned about my problem at stackoverflow

      (http://stackoverflow.com/questions/17046110/jquery-for-more-or-less-with-pagination-works-only-once)

      and this is my jsFiddle

      jsfiddle.net/zeynepeyyuboglu/Sv9AM but unfortunately jsFiddle does not show any output to my code because i assume that it does not support Primefaces which is JSF based library.

      if you can help me about this i would be appreciated.

      thanx.

      Delete
    3. I never worked with primefaces before (or JSF in general). I would wonder if there is some DOM change done by the JSF files which cause the element with the ".morelink" to be removed/re-added. This could possible be an issue whereby the click events need to be re-bound every-time the grid is paged.

      This a pure guess though. I also left the feedback on the SO issue itself.

      Sorry I was not able to help you find a solution to this.

      Delete
    4. .live(), .on(), .find(), .filter() || Not necessarily recommended in that order, but chances are you're probably loading via AJAX and new JQuery can't see the newly loaded content in the DOM so it won't work.

      Delete
  3. hi thanks I found this code, but the problem is I'm new website development.Can you show me how to put together all the codes.(html,css , javascript) because mine are not working

    ReplyDelete
  4. This is exactly what I'm trying to do on my site, but it doesn't work at all. I even copied and pasted all the code into a standalone test page and still nothing. It doesn't even work when I preview it locally.

    Am I missing something?

    I have the test page deployed here: http://www.psypher101.com/tests/more-less.html

    Any help would be much appreciated.

    ReplyDelete
    Replies
    1. Upon inspecting the jfiddle IFrame I was able to copy and paste the entire HTML code and it's working now. I'm gonna study that a bit and see how I can make this work on my site. This is pure awesomeness!

      Delete
    2. I like using jsFiddle for those little tests simply to DEMO some code but off course when using the code in an actual project you might need to change it here or there as required.

      I'm glad you got it worked out though and so fast as well :)

      Delete
  5. Oh my God! You don't know for how long I've been looking for something like this! Thank you so much! :)

    ReplyDelete
    Replies
    1. thank you for the nice feedback. I'm glad you found this helpful.

      Delete
  6. Hi Francois

    First of all youre work is geniuss :o)
    Im sitting since 5 houres to get this work, just on a testsite like Sauel (comment above).
    But it just dosent work.
    If I click read more, the Text is still hiding.

    I have copy/paste all 3 Things (HTML, JS,CSS)
    And in the head I have googleapis the hole ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js

    Im not sure, if something has chance since last year.
    Would be really nice if you have a tip for me.

    I wish you a nice day.

    Greets
    Franz

    ReplyDelete
    Replies
    1. When you open the browser's debugger console (F12 in Chrome for example) do you see any error/warning messages?

      In general, unlike in the jsfiddles, the code that binds the events needs to sit in a $(document).ready(function(){ // your code here })

      Otherwise your code will bind the events before the elements have been rendered and they will not work.

      In addition if you are using the second example from the site which uses switchClass() you also need to make sure you have the jQueryUI api referenced as switchClass() is part of jQueryUI.

      https://code.jquery.com/ui/1.10.4/jquery-ui.js -- or similar

      Delete
    2. Hi Fran

      Thanks a lot that you took some time to answer, and that also fast.
      OMG its a shame… i made a mistake when i put in to the website, after that
      i try it in a test site and here i forgot document ready.
      When i read your answer… i thought how stupid am I

      I should really study more js. but its really hard.
      Maybe its for you a easy thing.
      When i want to have a image instead the text "show more" & "show less"
      what i must change?
      Is it a easy doing or very complicated?

      Thank Man for your Help

      Greets
      Franz

      Delete
    3. Hi Franz

      Using an image it all depends on if you want to use an img tag, a background in en element populated with CSS using "background: url(....)" or use the "i" tag.

      If you want to use "i" tags you can do it like this:
      http://jsfiddle.net/jr9CZ/

      Note please that even though the use of the "i" tag is very common and popular it is not what the HTML5 spec defines it as and a lot of web developers would deem it a miss-use of the tag:
      https://www.w3.org/International/questions/qa-b-and-i-tags

      If you want to use background images loaded through CSS you can do it similar to this (I used separate image urls but the use of sprite-sheets is the more preferred in this case as far as I know):
      http://jsfiddle.net/wvvEQ/

      If you want to use img tags you can either add 2 img tags and show/hide them as you switch or use 1 img tag and use the same CSS solution as above, switching the image by class.

      There is probably tons more ways of doing it and each of the above mentioned has its pros/cons. In general, as far as I know, the use of the CSS url property is very common using sprite-sheets.

      Delete
    4. Forgot to mention that the i tag example is using a reference to "font awesome" in the fiddle, in case you wonder where the icons come from.

      Hope this helps :)

      Delete
  7. Hi,

    I use this (http://jsfiddle.net/Wpn94/) code, but its not working.It says: "Uncaught TypeError: undefined is not a function" on line: "$(".show-more a").on("click", function() {". I wrap it with $(document).ready(function(){, and still displays same error.

    Please help. Thanks in advance...

    ReplyDelete
    Replies
    1. Without a fiddle or similar demonstrating the issue I'm going to have to make a guess.

      Check that you are using at least jQuery 1.7 or later in your implementation as "on()" did not exist pre 1.7.

      Hence "$(".show-more a").on("click", function() {" could throw that error as "on" would be undefined.

      Delete
    2. When I change version of jQuery, I now have another problem. Here is the screenshoot: http://tinypic.com/r/330d7i8/8.

      Delete
    3. "switchClass()" belongs to the jQuery UI API not the jQuery API. So you need to ensure you add a reference to the jQuery UI version compatible with your jQuery version as well.

      I would recommend to use the "switchClass()" fiddle in this article as a rough guideline to make sure you have everything added you need.

      http://jsfiddle.net/FranWahl/FUNhG

      In the fiddle you can see all the included references on the left side under the "Frameworks & Extensions" section. You should see jQuery 1.7.2 in the dropdown and jQuery UI 1.8.18 checked.

      Feel free to experiment with the different version of both; jQuery and jQuery UI as required. The fiddle is only a working example to be used as a guideline.

      I hope this helps :)

      Delete