/*

SPINNERS

A Sass mixin to generate a pure CSS3 loading/busy indicator. github.com/franzheidl/spinners Franz Heidl 2014 MIT License


USAGE

Default:

.my-spinner {

@include spinner();

}

Custom:

.my-spinner {

@include spinner(1.25em, 3px solid #555, .7s, background rgba(0, 0, 0, .2);

}

All arguments are optional.

Accepts any valid CSS dimensional declaration, e.g px, em, rem as an argument for size.

Use either shorthand border declarations or individual ‘border- [value]’ (no colon!) pairs for the style.

Pass any number of seconds referring to the duration of one full rotation for animation speed.


*/

@mixin spinner-keyframes {

@-webkit-keyframes spinner-animation {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
  }
}
@-moz-keyframes spinner-animation {
  0% {
    -moz-transform: rotate(0deg);
  }
  100% {
    -moz-transform: rotate(360deg);
  }
}
@-ms-keyframes spinner-animation {
  0% {
    -ms-transform: rotate(0deg);
  }
  100% {
    -ms-transform: rotate(360deg);
  }
}
@-o-keyframes spinner-animation {
  0% {
    -o-transform: rotate(0deg);
  }
  100% {
    -o-transform: rotate(100deg);
  }
}
@keyframes spinner-animation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

}

@include spinner-keyframes();

@mixin spinner($args…) {

$prefixes: -webkit- -moz- -o- -ms- "";
$dimensional-units: ('px', 'em', 'rem', '%', 'ex');
$border-props: 'border-width' 'border-style' 'border-color';
$border-styles: solid dotted dashed double;
$size: 1em;
$border-width: 3px;
$border-style: solid;
$border-color: #1277c2;
$border: $border-width $border-style $border-color;
$duration: .65s;
$background: transparent; //

// Parse arguments:
@if $args {
  @each $arg in $args {
    @if length($arg) == 1 {
      @if type-of($arg) == number {
        @if unit($arg) != "" {
          @if unit($arg) == 's' {
            $duration: $arg;
          }
          @else if isIn($dimensional-units, unit($arg)) {
            $size: $arg;
          }
          @else {
            @warn "Spinner: \"#{$arg}\" is not a valid size or duration declaration!";
          }
        }
        @else {
          @warn "Spinner: \"#{$arg}\" is not a valid size or duration declaration!";
        }
      }
    }
    @else if length($arg) == 2 {
      $prop: nth($arg, 1);
      $val: nth($arg, 2);
      @if isIn($border-props, $prop) {
        @if $prop == 'border-width' {
          @if unit($val) == 'px' {
            $border-width: $val;
          }
          @else {
            @warn "Spinner: \"#{unit($val)}\" is not a valid border-width! Using default border-width.";
          }
        }
        @else if $prop == 'border-style' {
          @if isIn($border-styles, $val) {
            $border-style: $val;
          }
          @else {
            @warn "Spinner: \"#{$val}\" is not a valid border-style! Using default border-style.";
          }
        }
        @else if $prop == 'border-color' {
          @if type-of($val) == color {
            $border-color: $val;
          }
          @else {
            @warn "Spinner: \"#{$val}\" is not a valid border-color! Using default border-color.";
          }
        }
      }
      @else if $prop == 'background' {
        @if type-of($val) == color {
          $background: $val;
        }
        @else {
          @warn "Spinner: \"#{nth($val)}\" is not a valid color for background! Using default \"transparent\".";
        }
      }
      @else {
        @warn "Spinner: \"#{nth($arg, 1)}\" is not a valid border property! Using default border.";
      }
      $border: $border-width $border-style $border-color;
    }
    @else if length($arg) == 3 {
      @if isValidBorder($arg) {
        $border: $arg;
      }
      @else {
        @warn "Spinner: \"#{$arg}\" is not a valid shorthand border declaration! Using default border.";
      }
    }
  }
}

background-color: transparent;
border: $border;
border-radius: 50%;
border-top-color: $background;
border-right-color: $background;
width: $size;
height: $size;
display: inline-block;
vertical-align: middle;
@each $prefix in $prefixes {
  #{$prefix}box-sizing: border-box;
}
@each $prefix in $prefixes {
  #{$prefix}animation: spinner-animation $duration infinite linear;
}

}

@function isValidBorder($border) {

$validBorderTypes: color string number;
$borderStyles: solid dotted dashed double;
$validBorder: false;
$types: ();

@if length($border) == length($validBorderTypes) {
  @each $val in $border {
    @if type-of($val) == number {
      @if unit($val) == "" {
        @return false;
      }
    }
    @else if type-of($val) == string {
      @if not isIn($borderStyles, $val) {
        @return false;
      }
    }
    $types: append($types, type-of($val));
  }
  $validBorder: hasIdenticalValues($validBorderTypes, $types);
}

@return $validBorder;

}

@function hasIdenticalValues($arr1, $arr2) {

$id: false;
@each $val in $arr1 {
  @if isIn($arr2, $val) {
    $id: true;
  }
  @else {
    @return false;
  }
}
@return $id;

}

@function isIn($arr1, $val) {

$hasVal: false;
@each $item in $arr1 {
  @if $item == $val {
    $hasVal: true;
  }
}
@return $hasVal;

}