Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toggle Bootstrap button text on button click?

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.

like image 817
George Hawkins Avatar asked Feb 13 '15 13:02

George Hawkins


3 Answers

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.

like image 137
David Hempy Avatar answered Oct 22 '22 00:10

David Hempy


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>...
like image 6
George Hawkins Avatar answered Oct 21 '22 22:10

George Hawkins


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>
like image 4
Mike Reid Avatar answered Oct 21 '22 22:10

Mike Reid