<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<title>ng-bs-animated-button</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" />
<link rel="stylesheet" href="page.css">
<link rel="stylesheet" href="ng-bs-animated-button.css">
</head>
<body ng-app="demoApp">
<div class="container-fluid">
<div class="page-header">
<h1><a href="https://github.com/jeremypeters/ng-bs-animated-button">ng-bs-animated-button</a><br /><small>Angular/Bootstrap animated submit button directive</small></h1>
<a class="btn btn-default btn-sm" href="https://github.com/jeremypeters/ng-bs-animated-button" role="button">View on GitHub</a>
</div>
<div class="row">
<div class="col-sm-6">
<h3>Demos</h3>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 1: </strong>Default options | success
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo1Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 2: </strong>Default options | error
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo2Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 3: </strong>Icons on right
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo3Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
<br />
<pre>
$scope.options = {
iconsPosition: 'right'
};
</pre>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 4: </strong>Different colours for each state
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo4Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
<br />
<pre>
$scope.options = {
buttonDefaultClass: 'btn-default',
buttonSubmittingClass: 'btn-info',
buttonSuccessClass: 'btn-success'
};
</pre>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 5: </strong>Custom text for each state
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo5Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
<br />
<pre>
$scope.options = {
buttonDefaultText: 'Lorem ipsum',
buttonSubmittingText: 'Dolor sit amet',
buttonSuccessText: 'Consectetur elit'
};
</pre>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 6: </strong>Using Font Awesome icons
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo6Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
<br />
<pre>
$scope.options = {
buttonSubmittingIcon: 'fa fa-spinner',
buttonSuccessIcon: 'fa fa-smile-o',
};
</pre>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 7: </strong>Custom animation complete hold timing
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo7Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
<br />
<pre>
$scope.options = {
animationCompleteTime: '5000'
};
</pre>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<strong>Demo 8: </strong>Button size
</div>
<div class="panel-body">
<form name="form" role="form" ng-controller="demo8Ctrl" ng-submit="fakeSubmit()">
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</form>
<br />
<pre>
$scope.options = {
buttonSizeClass: 'btn-lg'
};
</pre>
</div>
</div>
</div>
<div class="col-sm-6">
<h3>Install</h3>
<kbd>bower install jeremypeters/ng-bs-animated-button</kbd>
<h3>Usage</h3>
<p>Add as a module dependency to your app:</p>
<pre>
angular.module('yourApp', ['jp.ng-bs-animated-button']);
</pre>
<p>Add the directive to your template:</p>
<pre>
<jp-ng-bs-animated-button is-submitting="isSubmitting" result="result" options="options"></jp-ng-bs-animated-button>
</pre>
<p>Add the required scope variables and any options to your controller:</p>
<pre>
app.controller('yourCtrl', function($scope) {
<strong><em>// Required - set to true on submission</em></strong>
$scope.isSubmitting = null;
<strong><em>// Required - set to 'success' or 'error' on success/failure</em></strong>
$scope.result = null;
<strong><em>// Optional</em></strong>
$scope.options = {
buttonDefaultText: 'Lorem ipsum',
...
};
});
</pre>
<h3>Options</h3>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Option</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>buttonDefaultClass</code>
</td>
<td>'btn-primary'</td>
</tr>
<tr>
<td>
<code>buttonSubmittingClass</code>
</td>
<td>'btn-primary'</td>
</tr>
<tr>
<td>
<code>buttonSuccessClass</code>
</td>
<td>'btn-primary'</td>
</tr>
<tr>
<td>
<code>buttonErrorClass</code>
</td>
<td>'btn-danger'</td>
</tr>
<tr>
<td>
<code>buttonSizeClass</code>
</td>
<td>null</td>
</tr>
<tr>
<td>
<code>buttonDefaultText</code>
</td>
<td>'Submit'</td>
</tr>
<tr>
<td>
<code>buttonSubmittingText</code>
</td>
<td>'Submitting...'</td>
</tr>
<tr>
<td>
<code>buttonSuccessText</code>
</td>
<td>'Completed'</td>
</tr>
<tr>
<td>
<code>buttonErrorText</code>
</td>
<td>'There was an error'</td>
</tr>
<tr>
<td>
<code>buttonSubmittingIcon</code>
</td>
<td>'glyphicon glyphicon-refresh'</td>
</tr>
<tr>
<td>
<code>buttonSuccessIcon</code>
</td>
<td>'glyphicon glyphicon-ok'</td>
</tr>
<tr>
<td>
<code>buttonErrorIcon</code>
</td>
<td>'glyphicon glyphicon-remove'</td>
</tr>
<tr>
<td>
<code>formIsInvalid</code>
</td>
<td>'form.$invalid'</td>
</tr>
<tr>
<td>
<code>animationCompleteTime</code>
</td>
<td>'2000'</td>
</tr>
<tr>
<td>
<code>iconsPosition</code>
</td>
<td>'left'</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<script src="app.js"></script>
<script src="ng-bs-animated-button.js"></script>
</body>
</html>
ng-bs-animated-button
=====================
Angular/Bootstrap animated submit button directive.
See https://github.com/jeremypeters/ng-bs-animated-button
@-webkit-keyframes btn-ng-bs-rotation {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-moz-keyframes btn-ng-bs-rotation {
0% {
-moz-transform: rotate(0);
transform: rotate(0);
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-o-keyframes btn-ng-bs-rotation {
0% {
-o-transform: rotate(0);
transform: rotate(0);
}
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes btn-ng-bs-rotation {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
.btn-ng-bs-animated .icons {
opacity: 0;
width: 0;
-webkit-transition: opacity 0.15s, width 0.15s;
-moz-transition: opacity 0.15s, width 0.15s;
-o-transition: opacity 0.15s, width 0.15s;
transition: opacity 0.15s, width 0.15s;
}
.btn-ng-bs-animated.is-active .icons {
opacity: 1;
width: 1em;
}
.btn-ng-bs-animated.is-active .icons.pull-left {
margin-right: 0.4em;
}
.btn-ng-bs-animated.is-active .icons.pull-right {
margin-left: 0.4em;
}
.btn-ng-bs-animated.is-active .icons .icon-spinner {
-webkit-animation: btn-ng-bs-rotation 2s infinite linear;
-moz-animation: btn-ng-bs-rotation 2s infinite linear;
-o-animation: btn-ng-bs-rotation 2s infinite linear;
animation: btn-ng-bs-rotation 2s infinite linear;
}
"use strict";angular.module("jp.ng-bs-animated-button",[]).directive("jpNgBsAnimatedButton",["$timeout",function(a){return{restrict:"AE",replace:!0,scope:{isSubmitting:"=",result:"=",options:"=?"},controller:["$scope",function(a){a.options=a.options||{},a.options={buttonDefaultClass:a.options.buttonDefaultClass||"btn-primary",buttonSubmittingClass:a.options.buttonSubmittingClass||"btn-primary",buttonSuccessClass:a.options.buttonSuccessClass||"btn-primary",buttonErrorClass:a.options.buttonErrorClass||"btn-danger",buttonSizeClass:a.options.buttonSizeClass||null,buttonDefaultText:a.options.buttonDefaultText||"Submit",buttonSubmittingText:a.options.buttonSubmittingText||"Submitting...",buttonSuccessText:a.options.buttonSuccessText||"Completed",buttonErrorText:a.options.buttonErrorText||"There was an error",buttonSubmittingIcon:a.options.buttonSubmittingIcon||"glyphicon glyphicon-refresh",buttonSuccessIcon:a.options.buttonSuccessIcon||"glyphicon glyphicon-ok",buttonErrorIcon:a.options.buttonErrorIcon||"glyphicon glyphicon-remove",formIsInvalid:a.options.formIsInvalid||"",animationCompleteTime:a.options.animationCompleteTime||"2000",iconsPosition:a.options.iconsPosition||"left"}}],template:'<button type="submit" class="btn {{buttonClass}} {{buttonSize}} btn-ng-bs-animated clearfix" ng-disabled="{{formIsInvalid}}"><div class="icons pull-{{iconsPosition}}"><span class="{{buttonSubmittingIcon}} icon-spinner icon-submit hidden"></span><span class="{{buttonSuccessIcon}} icon-result icon-success hidden"></span><span class="{{buttonErrorIcon}} icon-result icon-error hidden"></span></div><div class="text {{buttonTextFloatClass}}">{{buttonText}}</div></button>',link:function(b,c){var d=c,e={submitting:angular.element(d[0].querySelector(".icon-submit")),result:angular.element(d[0].querySelectorAll(".icon-result")),success:angular.element(d[0].querySelector(".icon-success")),error:angular.element(d[0].querySelector(".icon-error"))},f=function(){b.result=null,b.buttonClass=b.options.buttonDefaultClass,b.buttonText=b.options.buttonDefaultText,d.removeClass("is-active").attr("disabled",!1),e.result.addClass("hidden")},g=function(){return"left"===b.iconsPosition?"pull-right":"pull-left"};b.buttonClass=b.options.buttonDefaultClass,b.buttonSize=b.options.buttonSizeClass,b.formIsInvalid=b.options.formIsInvalid,b.iconsPosition=b.options.iconsPosition,b.buttonSubmittingIcon=b.options.buttonSubmittingIcon,b.buttonSuccessIcon=b.options.buttonSuccessIcon,b.buttonErrorIcon=b.options.buttonErrorIcon,b.iconsPosition=b.options.iconsPosition,b.buttonText=b.options.buttonDefaultText,b.buttonTextFloatClass=g(),b.$watch("isSubmitting",function(a){a&&(b.buttonClass=b.options.buttonSubmittingClass,b.buttonText=b.options.buttonSubmittingText,d.attr("disabled",!0).addClass("is-active"),e.submitting.removeClass("hidden"))},!0).bind(this),b.$watch("result",function(c){b.isSubmitting=null,"success"===c&&(b.buttonClass=b.options.buttonSuccessClass,b.buttonText=b.options.buttonSuccessText,e.submitting.addClass("hidden"),e.success.removeClass("hidden"),a(f,b.options.animationCompleteTime)),"error"===c&&(b.buttonClass=b.options.buttonErrorClass,b.buttonText=b.options.buttonErrorText,e.submitting.addClass("hidden"),e.error.removeClass("hidden"),a(f,b.options.animationCompleteTime))},!0).bind(this)}}}]);
'use strict';
var app = angular.module('demoApp', ['jp.ng-bs-animated-button']);
app.controller('demo1Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'success';
}, 2000);
};
});
app.controller('demo2Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'error';
}, 2000);
};
});
app.controller('demo3Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.options = {
iconsPosition: 'right'
};
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'success';
}, 2000);
};
});
app.controller('demo4Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.options = {
buttonDefaultClass: 'btn-default',
buttonSubmittingClass: 'btn-info',
buttonSuccessClass: 'btn-success'
};
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'success';
}, 2000);
};
});
app.controller('demo5Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.options = {
buttonDefaultText: 'Lorem ipsum',
buttonSubmittingText: 'Dolor sit amet',
buttonSuccessText: 'Consectetur elit'
};
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'success';
}, 2000);
};
});
app.controller('demo6Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.options = {
buttonSubmittingIcon : 'fa fa-spinner',
buttonSuccessIcon : 'fa fa-smile-o'
};
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'success';
}, 2000);
};
});
app.controller('demo7Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.options = {
animationCompleteTime: '5000'
};
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'success';
}, 2000);
};
});
app.controller('demo8Ctrl', function($scope, $timeout) {
$scope.isSubmitting = null;
$scope.result = null;
$scope.options = {
buttonSizeClass: 'btn-lg'
};
$scope.fakeSubmit = function() {
$scope.isSubmitting = true;
$timeout(function(){
$scope.result = 'success';
}, 2000);
};
});
.container-fluid {
padding-left: 30px;
padding-right: 30px;
}
.page-header {
padding-bottom: 20px;
margin: 40px 0 10px;
}