Skip to content

Instantly share code, notes, and snippets.

@erotte
Last active February 8, 2018 18:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save erotte/6937163 to your computer and use it in GitHub Desktop.
Save erotte/6937163 to your computer and use it in GitHub Desktop.
Ajax loading indicator (Spinner) with Rails/SASS/Bootstrap 2/FontAwesome
%spinner
@extend [class^="icon-"]
@extend .icon-refresh
@extend .icon-spin
+transition(opacity 1s ease, width 0.7s ease, height 0.3s ease)
position: relative
top: -1px
display: inline-block
overflow: hidden
text-decoration: inherit
vertical-align: middle
width: 0
height: 0
opacity: 0
%visible-spinner
width: 12px
height: 14px
opacity: 1
%error-spinner
@extend .icon-warning-sign
@extend %visible-spinner
+vendor-prefix(animation, none)
content: '\f071'
width: 16px
color: #fc0
// Spinner Element, works inside, before and after buttons and inside forms
// <a href='action/1' class='btn btn-primary'><i class='spinner'></i>Button Text</a>
// <i class='spinner'></i><a href='action/1' class='btn btn-primary'>Button Text</a>
.spinner
@extend %spinner
left: -0.5em
&.is-ajax-loading, .is-ajax-loading &
@extend %visible-spinner
.is-ajax-error
.spinner, &.spinner
@extend %error-spinner
// as CSS generated content inside buttons,
// does not work with submit inputs, use <button type='submit'> with Spinner element instead
.btn-spinner
&:before
@extend %spinner
left: -.4em
content: '\f021'
&.is-ajax-loading:before
@extend %visible-spinner
&.is-ajax-error:before
@extend %error-spinner
form.is-ajax-loading .btn-spinner:before
@extend %visible-spinner
// as you may have expected, CSS animations (used in font-awesome's .icon-spin ) is poorly supported by IE.
// It may work in IE10, no chance with lte IE9.
Spinner = do ->
@spinner = (evTarget) ->
$.merge $(evTarget).siblings('.spinner'), $(evTarget)
$ ->
$ajaxTriggers = $(document) #$('[data-remote]')
$ajaxTriggers.on 'ajax:before', (event) ->
@spinDelay = setTimeout ( ->
spinner(event.target).removeClass('is-ajax-error').addClass('is-ajax-loading')
), 200
$ajaxTriggers.on 'ajax:complete', (event) ->
clearTimeout(@spinDelay)
spinner(event.target).removeClass('is-ajax-loading')
$ajaxTriggers.on 'ajax:success', (event, data, status) ->
spinner(event.target).removeClass('is-ajax-loading is-ajax-error')
$ajaxTriggers.on 'ajax:error', (event) ->
spinner(event.target).addClass('is-ajax-error')
<p><a class="btn btn-primary" data-remote="true" href="path/to/resource">
<i class="spinner"></i>do something</a>
</p>
<p>
<i class="spinner"></i>
<a class="btn btn-primary" data-remote="true" href="path/to/resource">do something</a>
</p>
<p><a class="btn btn-primary btn-spinner" data-remote="true" href="path/to/resource">
Neue Nachricht</a>
</p>
<form>
<button class="btn btn-primary btn-spinner" name="button" type="submit">
do something
</button>
<button class="btn btn-primary" name="button" type="submit">
<i class="spinner"></i>
do something
</button>
<p>
<i class="spinner"></i>
<button class="btn btn-primary" name="button" type="submit">
do something
</button>
</p>
</form>
p
= link_to example_path, class: 'btn btn-primary' remote: true do
i.spinner
| do something
p
i.spinner
= link_to example_path, class: 'btn btn-primary', remote: true do
| do something
p
= link_to example_path, class: 'btn btn-primary btn-spinner', remote: true do
| do something
= simple_form_for @example, :html => { remote: true } do |f|
= f.button :button, :class => 'btn-primary btn-spinner', type: :submit do
| do something
= form_for @example, remote: true do |f|
= f.button :button, :class => 'btn-primary btn-spinner', type: :submit do
| do something
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment