Toggle Bootstrap button text on button click?
Asked Answered
U

5

7

I want to toggle the text on a button each time it's clicked, e.g. from "Show more..." to "Show less...".

I have a button that's used to expand or collapse a nearby block (see the Collapse section of the Bootstrap docs, click the example "Link with href" button there to see what I mean).

The HTML for such a Bootstrap button looks like this:

<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample">
    See more...
</a>

When the related block is collapsed I want the button text to be e.g. "Show more..." and when it's expanded I want it to be e.g. "Show less...".

I've seen solutions that separate the button text off into jQuery, Javascript or CSS - but that makes it difficult to read the HTML (the button text is somewhere else entirely to the button) and also makes it more difficult to localize.

Unpaged answered 13/2, 2015 at 13:24 Comment(0)
U
7

Using jQuery the answer is simple. Just mark such buttons with a new class called toggle-text and use <span> and <span class="hidden"> to mark the text you want to toggle back and forward between:

<a class="btn btn-primary toggle-text" data-toggle="collapse" href="#collapseExample">
    See <span>more</span><span class="hidden">less</span>...
</a>

You can have as many or few <span> tags as you want and can order them as you want, all that's important is whether or not they're marked with class hidden.

Now in jQuery you can do:

$('.hidden').removeClass('hidden').hide();
$('.toggle-text').click(function() {
    $(this).find('span').each(function() { $(this).toggle(); });
});

The first line is a bit of boiler plate - jQuery and Bootstrap have somewhat conflicting ideas about hidden. This just flips everything you've marked as hidden using the Bootstrap class hidden to being hidden by jQuery which makes it easier to use the jQuery visibility functions afterwards.

The next bit is the important stuff - it installs a handler on all elements marked with our new class toggle-text - this handler toggles the visibility of the <span> children of the given element when it's clicked.

See everything in action with this jFiddle - http://jsfiddle.net/w3y421m9/1/

Note: the name toggle-text is completely arbitrary and is just used for marking buttons for which we want this toggle behavior.

This is the first time I've written a question with the intention of answering it. I'm interested to see if someone has a better answer.

To me this solution looks super simple and has the big plus of keeping the button text together with the HTML for the button, without additional button specific CSS or Javascript/jQuery code.


The jQuery is nice in that it doesn't have to be customized on a per-button basis depending on the text you want to display. And you've got a lot of flexibility with mixing text that you do and don't want to toggle, e.g. the following are all equivalent:

<span>Show more...</span><span class=hidden">Show less...</span>
Show <span>more</span><span class=hidden">less</span>...
Show <span class=hidden">less</span><span>more</span>...
Unpaged answered 13/2, 2015 at 13:24 Comment(0)
A
6

I tried a couple of these approaches before cobbling this one together. It is the simplest, most readable approach I've seen so far:

    <a href="#" data-toggle='collapse' 
        data-target="#filters,#view_filters,#hide_filters">
      <span id='view_filters' class='collapse in'>View Filters</span>
      <span id='hide_filters' class='collapse out'>Hide Filters</span>
    </a>

    <div id="filters" class="collapse out">
      Now you see me!
    </div>

The main purpose of this link is to toggle visibility of div#filters...but it takes advantage of multiple selectors in data_target to also toggle the visibility of the two versions of the link text. Just make sure you've got one text as ".collapse .in" and the other as ".collapse .out".

Beyond its simplicity, I like that this is very reliable. Because the tag is never hidden or manipulated, you'll never accidentally lose the view/hide link while debugging.

Airliner answered 6/12, 2017 at 6:11 Comment(3)
Great solution David! fyi you're missing a closing '>' on the anchorHandknit
Thanks, @Liz. Typo fixed. :)Airliner
Perfect answer but I had the issue that .collapsing transitions too long and so users did see both options visile for a moment. Thereby I added this part .collapsing, .show, .hide { transition: none !important; transition-delay: 0s; transition-delay: 0s !important; } and this doesn't happen anymoreMossy
P
5

Rather than dealing with excess tags or placing your alternate button text within your JavaScript directly, I personally prefer leveraging HTML5 custom data attributes. This way you can easily rotate between the original and alternate button text on each click, but keep it relative to your toggle element.

jQuery(function($){
  $('.btn[data-toggle="collapse"]').on('click', function(){
    $(this)
    .data('text-original', $(this).text())
    .text($(this).data('text-alt') )
    .data('text-alt', $(this).data('text-original'));
  });
});
<!--styles-->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>

<!--toggle 1-->
<button class="btn btn-link" data-toggle="collapse" data-target=".details-1" data-text-alt="- hide details">+ show details</button>
<div class="details-1 collapse">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>

<hr>

<!--toggle 2-->
<button class="btn btn-link" data-toggle="collapse" data-target=".details-2" data-text-alt="- hide details">+ show details</button>
<div class="details-2 collapse">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>

<!--scripts-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
Plainlaid answered 21/4, 2016 at 17:45 Comment(0)
S
3

You can use simple jQuery to achive this.

https://jsfiddle.net/YameenYasin/5j0ehez1/40/

<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample">
    See more...
</a>

$('a').click(function(){        
    if($(this).text().trim() == 'See more...' ){
        $(this).text('See Less...');
    }else{
         $(this).text('See more...');
    }
});
Sunda answered 13/2, 2015 at 14:24 Comment(1)
Like I said I think it's nice to have the text in the same place as the rest of the HTML involved rather than separated out somewhere else entirely in some button specific jQuery code.Unpaged
M
2

Thanks for your suggestions. You pointed me in the right direction but I ended up doing it slightly different. My solution uses a bit of CSS to tell what the "hidden" class means and then jQuery toggles this class on all SPAN elements:

HTML (similar to yours):

<a class="toggle-link" href="...">
  <span>Show more...</span>
  <span class="hidden">Show less...</span>
</a>

CSS:

.toggle-link .hidden {
  display: none;
}

Update: You don't need this bit of css if you're using bootstrap, as pointed out by George Hawkins

jQuery:

jQuery(".toggle-link").click(function() {
    jQuery(this).find("span").toggleClass("hidden");
    /* Add more logic here */
});

I'm not saying it's better per se but to me it looks a bit cleaner. Also, you could expand on this method by not hiding a text but changing it's color back and forth, etcetera.

Mellisa answered 3/3, 2015 at 18:9 Comment(2)
This question was about Bootstrap and in Bootstrap .hidden is already defined - see line 45 of bootstrap/utilities.less so I'm not sure what this adds. Unless you're not using Bootstrap?Unpaged
Thanks, George. I updated my answer accordingly. Indeed I wasn't using Bootstrap at the time.Mellisa

© 2022 - 2024 — McMap. All rights reserved.