ChatGPT解决这个技术问题 Extra ChatGPT

How to add a spinner icon to button when it's in the Loading state?

Twitter Bootstrap's buttons have a nice Loading... state available.

The thing is that it just shows a message like Loading... passed through the data-loading-text attribute like this:

<button type="button" class="btn btn-primary start" id="btnStartUploads"
        data-loading-text="@Localization.Uploading">
    <i class="icon-upload icon-large"></i>
    <span>@Localization.StartUpload</span>
</button>

Looking at Font Awesome, you see that there's now an animated spinner icon.

I tried to integrate that spinner icon when firing an Upload operation like this:

$("#btnStartUploads").button('loading');
$("#btnStartUploads i").removeAttr('class');
$("#btnStartUploads i").addClass('icon-spinner icon-spin icon-large');

but this had no effect at all, that is, I just see the Uploading... text on the button.

Is it possible to add an icon when the button is in the Loading state? Looks like somehow Bootstrap just removes the icon <i class="icon-upload icon-large"></i> inside the button while in the Loading state.

Here's a simple demo that shows the behavior I describe above. As you see when it enters the Loading state the icon just disappears. It reappears right after the time interval.

You can check out my solution to animate spinner appearance: stackoverflow.com/questions/15982233/…
I recommend to use this approach stackoverflow.com/a/15988830/437690

u
user664833

Simple solution for Bootstrap 3 using CSS3 animations.

Put the following in your CSS:

.glyphicon.spinning {
    animation: spin 1s infinite linear;
    -webkit-animation: spin2 1s infinite linear;
}

@keyframes spin {
    from { transform: scale(1) rotate(0deg); }
    to { transform: scale(1) rotate(360deg); }
}

@-webkit-keyframes spin2 {
    from { -webkit-transform: rotate(0deg); }
    to { -webkit-transform: rotate(360deg); }
}

Then just add the spinning class to a glyphicon while loading to get your spinning icon:

<button class="btn btn-lg btn-warning">
    <span class="glyphicon glyphicon-refresh spinning"></span> Loading...    
</button>

Based on http://www.bootply.com/128062#

Note: IE9 and below do not support CSS3 animations.


Shouldn't it be animation and not -animation?
Excellent solution. I'm having issues with this animating in Safari on the desktop and on the iPad. It shows the icon but doesn't animate it. Ever experience something like that?
@JayhawksFan93 yes I recently noticed the same in IE. Will look into it soon
the answer was updated to animation instead of -animation. With that change fine in FF and IE for me. The firefox animation doesnt look very smooth though.
+1. Found a similar one here.... Posting for record...
S
Shahzad Barkati

If you look at the bootstrap-button.js source, you'll see that the bootstrap plugin replaces the buttons inner html with whatever is in data-loading-text when calling $(myElem).button('loading').

For your case, I think you should just be able to do this:

<button type="button"
        class="btn btn-primary start"
        id="btnStartUploads"
        data-loading-text="<i class='icon-spinner icon-spin icon-large'></i> @Localization.Uploading">
    <i class="icon-upload icon-large"></i>
    <span>@Localization.StartUpload</span>
</button>

Works great gurch101! I forget that one can mix HTML with text in a tag property. :-)
Fiddle not working for Safari 6.0.5 (7536.30.1), Chrome 31.0.1604.0 canary on Mac OS X.
Fixed: jsfiddle.net/6U5q2/270 Note this is for v2.3.2. Don't know if it works for 3.x
data-loading-text is deprecated since v3.3.5 and will be removed in v4.
@Jonathan If it is deprecated in v3.3.5 what is the replacement for that in both after v3.3.5 and v4?
r
raveren

There's now a full-fledged plugin for that:

http://msurguy.github.io/ladda-bootstrap/


Hi @Eru Penkman. What is the difference between yours and the original?
Hey Ivan, sort but I never got around to updating my copy of ladda! It's just the original, I removed my previous comment. Sorry about that!
j
jake

To make the solution by @flion look really great, you could adjust the center point for that icon so it doesn't wobble up and down. This looks right for me at a small font size:

.glyphicon-refresh.spinning {
  transform-origin: 48% 50%;
}

.glyphicon-refresh.spinning { transform-origin: 50% 58%; } worked for me
hum, { transform-origin: 50% 49%; } solve in my case where I'm using cog instead.
I also notice the wobble, but what's the rationale for changing these numbers? How should I tune them?
V
Volomike

A lazy way to do this is with the UTF-8 entity code for a half circle \25E0 (aka &#x25e0;), which looks like ◠ and then keyframe animate it. It's a simple as:

.busy { animation: spin 1s infinite linear; display:inline-block; font-weight: bold; font-family: sans-serif; font-size: 35px; font-style:normal; color:#555; } .busy::before { content:"\25E0"; } @keyframes spin { 0% {transform: rotate(0deg);} 100% {transform: rotate(359deg);} }


m
mikemsq

Here's my solution for Bootstrap 4:

<button id="search" class="btn btn-primary" 
data-loading-text="<i class='fa fa-spinner fa-spin fa-fw' aria-hidden='true'></i>Searching">
  Search
</button>

var setLoading = function () {
  var search = $('#search');
  if (!search.data('normal-text')) {
    search.data('normal-text', search.html());
  }
  search.html(search.data('loading-text'));
};

var clearLoading = function () {
  var search = $('#search');
  search.html(search.data('normal-text'));
};

setInterval(() => {
  setLoading();
  setTimeout(() => {
    clearLoading();
  }, 1000);
}, 2000);

Check it out on JSFiddle


D
Damiano

These are mine, based on pure SVG and CSS animations. Don't pay attention to JS code in the snippet bellow, it's just for demoing purposes. Feel free to make your custom ones basing on mine, it's super easy.

var svg = d3.select("svg"), columnsCount = 3; ['basic', 'basic2', 'basic3', 'basic4', 'loading', 'loading2', 'spin', 'chrome', 'chrome2', 'flower', 'flower2', 'backstreet_boys'].forEach(function(animation, i){ var x = (i%columnsCount+1) * 200-100, y = 20 + (Math.floor(i/columnsCount) * 200); svg.append("text") .attr('text-anchor', 'middle') .attr("x", x) .attr("y", y) .text((i+1)+". "+animation); svg.append("circle") .attr("class", animation) .attr("cx", x) .attr("cy", y+40) .attr("r", 16) }); circle { fill: none; stroke: #bbb; stroke-width: 4 } .basic { animation: basic 0.5s linear infinite; stroke-dasharray: 20 80; } @keyframes basic { 0% {stroke-dashoffset: 100;} 100% {stroke-dashoffset: 0;} } .basic2 { animation: basic2 0.5s linear infinite; stroke-dasharray: 80 20; } @keyframes basic2 { 0% {stroke-dashoffset: 100;} 100% {stroke-dashoffset: 0;} } .basic3 { animation: basic3 0.5s linear infinite; stroke-dasharray: 20 30; } @keyframes basic3 { 0% {stroke-dashoffset: 100;} 100% {stroke-dashoffset: 0;} } .basic4 { animation: basic4 0.5s linear infinite; stroke-dasharray: 10 23.3; } @keyframes basic4 { 0% {stroke-dashoffset: 100;} 100% {stroke-dashoffset: 0;} } .loading { animation: loading 1s linear infinite; stroke-dashoffset: 25; } @keyframes loading { 0% {stroke-dashoffset: 0; stroke-dasharray: 50 0; } 50% {stroke-dashoffset: -100; stroke-dasharray: 0 50;} 100% { stroke-dashoffset: -200;stroke-dasharray: 50 0;} } .loading2 { animation: loading2 1s linear infinite; } @keyframes loading2 { 0% {stroke-dasharray: 5 28.3; stroke-dashoffset: 75;} 50% {stroke-dasharray: 45 5; stroke-dashoffset: -50;} 100% {stroke-dasharray: 5 28.3; stroke-dashoffset: -125; } } .spin { animation: spin 1s linear infinite; stroke-dashoffset: 25; } @keyframes spin { 0% {stroke-dashoffset: 0; stroke-dasharray: 33.3 0; } 50% {stroke-dashoffset: -100; stroke-dasharray: 0 33.3;} 100% { stroke-dashoffset: -200;stroke-dasharray: 33.3 0;} } .chrome { animation: chrome 2s linear infinite; } @keyframes chrome { 0% {stroke-dasharray: 0 100; stroke-dashoffset: 25;} 25% {stroke-dasharray: 75 25; stroke-dashoffset: 0;} 50% {stroke-dasharray: 0 100; stroke-dashoffset: -125;} 75% {stroke-dasharray: 75 25; stroke-dashoffset: -150;} 100% {stroke-dasharray: 0 100; stroke-dashoffset: -275;} } .chrome2 { animation: chrome2 1s linear infinite; } @keyframes chrome2 { 0% {stroke-dasharray: 0 100; stroke-dashoffset: 25;} 25% {stroke-dasharray: 50 50; stroke-dashoffset: 0;} 50% {stroke-dasharray: 0 100; stroke-dashoffset: -50;} 75% {stroke-dasharray: 50 50; stroke-dashoffset: -125;} 100% {stroke-dasharray: 0 100; stroke-dashoffset: -175;} } .flower { animation: flower 1s linear infinite; } @keyframes flower { 0% {stroke-dasharray: 0 20; stroke-dashoffset: 25;} 50% {stroke-dasharray: 20 0; stroke-dashoffset: -50;} 100% {stroke-dasharray: 0 20; stroke-dashoffset: -125;} } .flower2 { animation: flower2 1s linear infinite; } @keyframes flower2 { 0% {stroke-dasharray: 5 20; stroke-dashoffset: 25;} 50% {stroke-dasharray: 20 5; stroke-dashoffset: -50;} 100% {stroke-dasharray: 5 20; stroke-dashoffset: -125;} } .backstreet_boys { animation: backstreet_boys 3s linear infinite; } @keyframes backstreet_boys { 0% {stroke-dasharray: 5 28.3; stroke-dashoffset: -225;} 15% {stroke-dasharray: 5 28.3; stroke-dashoffset: -300;} 30% {stroke-dasharray: 5 20; stroke-dashoffset: -300;} 45% {stroke-dasharray: 5 20; stroke-dashoffset: -375;} 60% {stroke-dasharray: 5 15; stroke-dashoffset: -375;} 75% {stroke-dasharray: 5 15; stroke-dashoffset: -450;} 90% {stroke-dasharray: 5 15; stroke-dashoffset: -525;} 100% {stroke-dasharray: 5 28.3; stroke-dashoffset: -925;} }

Also available on CodePen: https://codepen.io/anon/pen/PeRazr


B
Brendan Weinstein

Here is a full-fledged css solution inspired by Bulma. Just add

    .button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      position: relative;
      min-width: 200px;
      max-width: 100%;
      min-height: 40px;
      text-align: center;
      cursor: pointer;
    }

    @-webkit-keyframes spinAround {
      from {
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
      }
      to {
        -webkit-transform: rotate(359deg);
        transform: rotate(359deg);
      }
    }
    @keyframes spinAround {
      from {
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
      }
      to {
        -webkit-transform: rotate(359deg);
        transform: rotate(359deg);
      }
    }

    .button.is-loading {
      text-indent: -9999px;
      box-shadow: none;
      font-size: 1rem;
      height: 2.25em;
      line-height: 1.5;
      vertical-align: top;
      padding-bottom: calc(0.375em - 1px);
      padding-left: 0.75em;
      padding-right: 0.75em;
      padding-top: calc(0.375em - 1px);
      white-space: nowrap;
    }

    .button.is-loading::after  {
      -webkit-animation: spinAround 500ms infinite linear;
      animation: spinAround 500ms infinite linear;
      border: 2px solid #dbdbdb;
      border-radius: 290486px;
      border-right-color: transparent;
      border-top-color: transparent;
      content: "";
      display: block;
      height: 1em;
      position: relative;
      width: 1em;
    }

C
Colin

The only thing I found that worked was a post here: https://stackoverflow.com/a/44548729/9488229

I improved it, and now it provides all these features:

Disable the button after click

Show an animated loading icon using native bootstrap

Re-enable the button after the page is done loading

Text goes back to original when page loading is done

Javascript:

$(document).ready(function () {
    $('.btn').on('click', function() {
        var e=this;
        setTimeout(function() {
            e.innerHTML='<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Searching...';
            e.disabled=true;
        },0);
        return true;
    });
});

Welcome to Stack Overflow. I don't see where you've used the solution Andreas used, and I don't see in the provided code where the button gets re-enabled or restored.
You're right it was another answer, I've updated the link. As for how the button gets re-enabled, it works. I think it has to do with the fact it's being disabled inside a setTimeout() function that everything that happens inside that function is undone when the page finishes loading. It's a really clean solution.
It may be that the re-enable and text restoration is being taken care of by Bootstrap. Try running this code without the Bootstrap JavaScript on a test page.
This has worked for me with the Form submit button.
G
GucciBananaKing99

You can use the Bootstrap spinner. Use "position: absolute" to make both buttons over each other. With the JavaScript code you can remove the front button and the back button will be displayed.

button { position: absolute; top: 50px; left: 150px; width: 150px; font-size: 120%; padding: 5px; background: #B52519; color: #EAEAEA; border: none; margin: 120px; border-radius: 5px; display: flex; align-content: center; justify-content: center; transition: all 0.5s; height: 40px } #orderButton:hover { color: #c8c8c8; }


关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now