├── LICENSE ├── README.md ├── bower.json ├── ngLoader.css ├── ngLoader.js ├── ngLoader.min.css └── ngLoader.min.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 James 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ngLoader 2 | Loading animation for AngularJS 3 | 4 | Used the SVG loading animations from this Pen by Aurer. 5 | 6 | This module can be used in any version of Angular (see the Plunk below). All major browsers, except IE, are supported. Template 9, the default and now using CSS animations, is supported in IE10+ and the other templates are not supported in IE. 7 | 8 | 9 | ##### 1. Install the module via bower. 10 | ``` 11 | bower install ng-loaders 12 | ``` 13 | 14 | ##### 2. Add the module as a dependency 15 | ```JavaScript 16 | angular.module('app',['ngLoader']); 17 | ``` 18 | 19 | ##### 3. Include the CSS file in your HTML file or import it in your CSS 20 | ```HTML 21 | 22 | ``` 23 | 24 | OR 25 | 26 | ```CSS 27 | @import "bower_components/ngLoader/ngLoader.min.css"; 28 | ``` 29 | 30 | ##### 4. Include the JS file in your HTML file 31 | ```HTML 32 | 33 | ``` 34 | 35 | ##### 5. Add the loader in your view and ensure the corresponding scope variable is defined 36 | ```HTML 37 | 42 | 43 | ``` 44 | 45 | ## Example 46 | This loader can be used in many instances, one in which being for AJAX requests using Anuglar's $http service. 47 | Set your scope variable to true before the request and in the `finally` condition of the promised returned. 48 | 49 | Example plunk can be found here. 50 | ```JavaScript 51 | $scope.working = true; 52 | $scope.message = 'Loading...' 53 | $http.get('').then( 54 | function(success) { 55 | console.log('Success! ' + success); 56 | }, 57 | function(error) { 58 | console.error('Error! ' + error); 59 | } 60 | )['finally'](function() { 61 | $scope.working = false; 62 | }); 63 | ``` 64 | 65 | ## Options 66 | Only the `working` attribute is required. 67 | 68 | | Attribute | Default | Accepted Values | 69 | | ------------------ | ------------------------ | ------------------------ | 70 | | working | _name of scope variable_ | Any valid scope variable | 71 | | disable-background | _false_ | true or false | 72 | | message | _undefined_ | Any string | 73 | | template | _9_ | Any number 1-9 | 74 | 75 | ## Notes 76 | Styles of the loader can be updated / modified by targeting the `loader-content` class. 77 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ng-loaders", 3 | "main": "ngLoader.js", 4 | "version": "1.0.0", 5 | "homepage": "https://github.com/jfeigel/ngLoader", 6 | "authors": [ 7 | "James Feigel " 8 | ], 9 | "description": "AngularJS Loading animation", 10 | "keywords": [ 11 | "AngularJS", 12 | "SVG", 13 | "Loading" 14 | ], 15 | "ignore": [], 16 | "license": "MIT" 17 | } 18 | -------------------------------------------------------------------------------- /ngLoader.css: -------------------------------------------------------------------------------- 1 | .loader-bars { 2 | height: 25px; 3 | width: 30px; 4 | margin: 0 auto; 5 | text-align: center; 6 | } 7 | 8 | .bar { 9 | background-color: #ccc; 10 | float: left; 11 | height: 25px; 12 | margin-left: 4px; 13 | width: 5px; 14 | opacity: 0.1; 15 | -moz-animation-name: bounceG; 16 | -moz-animation-duration: 1.5s; 17 | -moz-animation-iteration-count: infinite; 18 | -moz-animation-direction: linear; 19 | -moz-transform: scale(0.7); 20 | -webkit-animation-name: bounceG; 21 | -webkit-animation-duration: 1.5s; 22 | -webkit-animation-iteration-count: infinite; 23 | -webkit-animation-direction: linear; 24 | -webkit-transform: scale(0.7); 25 | -ms-animation-name: bounceG; 26 | -ms-animation-duration: 1.5s; 27 | -ms-animation-iteration-count: infinite; 28 | -ms-animation-direction: linear; 29 | -ms-transform: scale(0.7); 30 | -o-animation-name: bounceG; 31 | -o-animation-duration: 1.5s; 32 | -o-animation-iteration-count: infinite; 33 | -o-animation-direction: linear; 34 | -o-transform: scale(0.7); 35 | animation-name: bounceG; 36 | animation-duration: 1.5s; 37 | animation-iteration-count: infinite; 38 | animation-direction: linear; 39 | transform: scale(0.7); 40 | } 41 | 42 | .bar1 { 43 | -moz-animation-delay: 0.45s; 44 | -webkit-animation-delay: 0.45s; 45 | -ms-animation-delay: 0.45s; 46 | -o-animation-delay: 0.45s; 47 | animation-delay: 0.45s; 48 | } 49 | 50 | .bar2 { 51 | -moz-animation-delay: 0.6s; 52 | -webkit-animation-delay: 0.6s; 53 | -ms-animation-delay: 0.6s; 54 | -o-animation-delay: 0.6s; 55 | animation-delay: 0.6s; 56 | } 57 | 58 | .bar3 { 59 | -moz-animation-delay: 0.75s; 60 | -webkit-animation-delay: 0.75s; 61 | -ms-animation-delay: 0.75s; 62 | -o-animation-delay: 0.75s; 63 | animation-delay: 0.75s; 64 | } 65 | 66 | @-moz-keyframes bounceG { 67 | 0% { 68 | -moz-transform: scale(1.2); 69 | opacity: 1; 70 | } 71 | 100% { 72 | -moz-transform: scale(0.7); 73 | opacity: 0.1; 74 | } 75 | } 76 | @-webkit-keyframes bounceG { 77 | 0% { 78 | -webkit-transform: scale(1.2); 79 | opacity: 1; 80 | } 81 | 100% { 82 | -webkit-transform: scale(0.7); 83 | opacity: 0.1; 84 | } 85 | } 86 | @-ms-keyframes bounceG { 87 | 0% { 88 | -ms-transform: scale(1.2); 89 | opacity: 1; 90 | } 91 | 100% { 92 | -ms-transform: scale(0.7); 93 | opacity: 0.1; 94 | } 95 | } 96 | @-o-keyframes bounceG { 97 | 0% { 98 | -o-transform: scale(1.2); 99 | opacity: 1; 100 | } 101 | 100% { 102 | -o-transform: scale(0.7); 103 | opacity: 0.1; 104 | } 105 | } 106 | @keyframes bounceG { 107 | 0% { 108 | transform: scale(1.2); 109 | opacity: 1; 110 | } 111 | 100% { 112 | transform: scale(0.7); 113 | opacity: 0.1; 114 | } 115 | } -------------------------------------------------------------------------------- /ngLoader.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * AngularJS Loader animation 3 | * @author James Feigel 4 | * @version 1.0.0 5 | */ 6 | angular.module('ngLoaderTemplates', ['template/ngLoader/ngLoaderTemplate1.html', 'template/ngLoader/ngLoaderTemplate2.html', 'template/ngLoader/ngLoaderTemplate3.html', 'template/ngLoader/ngLoaderTemplate4.html', 'template/ngLoader/ngLoaderTemplate5.html', 'template/ngLoader/ngLoaderTemplate6.html', 'template/ngLoader/ngLoaderTemplate7.html', 'template/ngLoader/ngLoaderTemplate8.html', 'template/ngLoader/ngLoaderTemplate9.html']); 7 | 8 | angular.module('template/ngLoader/ngLoaderTemplate1.html', []).run(['$templateCache', 9 | function($templateCache) { 10 | $templateCache.put('template/ngLoader/ngLoaderTemplate1.html', 11 | "
\n" + 12 | "
\n" + 13 | " \n" + 15 | " \n" + 18 | " \n" + 20 | " \n" + 27 | " \n" + 28 | " \n" + 29 | "

\n" + 30 | "

\n" + 31 | "
\n" + 32 | "
"); 33 | }]); 34 | angular.module('template/ngLoader/ngLoaderTemplate2.html', []).run(['$templateCache', 35 | function($templateCache) { 36 | $templateCache.put('template/ngLoader/ngLoaderTemplate2.html', 37 | "
\n" + 38 | "
\n" + 39 | " \n" + 41 | " \n" + 42 | " \n" + 49 | " \n" + 50 | " \n" + 51 | "

\n" + 52 | "

\n" + 53 | "
\n" + 54 | "
"); 55 | }]); 56 | angular.module('template/ngLoader/ngLoaderTemplate3.html', []).run(['$templateCache', 57 | function($templateCache) { 58 | $templateCache.put('template/ngLoader/ngLoaderTemplate3.html', 59 | "
\n" + 60 | "
\n" + 61 | " \n" + 63 | " \n" + 64 | " \n" + 71 | " \n" + 72 | " \n" + 73 | "

\n" + 74 | "

\n" + 75 | "
\n" + 76 | "
"); 77 | }]); 78 | angular.module('template/ngLoader/ngLoaderTemplate4.html', []).run(['$templateCache', 79 | function($templateCache) { 80 | $templateCache.put('template/ngLoader/ngLoaderTemplate4.html', 81 | "
\n" + 82 | "
\n" + 83 | " \n" + 85 | " \n" + 86 | " \n" + 90 | " \n" + 91 | " \n" + 92 | " \n" + 96 | " \n" + 97 | " \n" + 98 | " \n" + 102 | " \n" + 103 | " \n" + 104 | "

\n" + 105 | "

\n" + 106 | "
\n" + 107 | "
"); 108 | }]); 109 | angular.module('template/ngLoader/ngLoaderTemplate5.html', []).run(['$templateCache', 110 | function($templateCache) { 111 | $templateCache.put('template/ngLoader/ngLoaderTemplate5.html', 112 | "
\n" + 113 | "
\n" + 114 | " \n" + 116 | " \n" + 117 | " \n" + 121 | " \n" + 122 | " \n" + 123 | " \n" + 127 | " \n" + 128 | " \n" + 129 | " \n" + 133 | " \n" + 134 | " \n" + 135 | "

\n" + 136 | "

\n" + 137 | "
\n" + 138 | "
"); 139 | }]); 140 | angular.module('template/ngLoader/ngLoaderTemplate6.html', []).run(['$templateCache', 141 | function($templateCache) { 142 | $templateCache.put('template/ngLoader/ngLoaderTemplate6.html', 143 | "
\n" + 144 | "
\n" + 145 | " \n" + 147 | " \n" + 148 | " \n" + 151 | " \n" + 154 | " \n" + 155 | " \n" + 156 | " \n" + 159 | " \n" + 162 | " \n" + 163 | " \n" + 164 | " \n" + 167 | " \n" + 170 | " \n" + 171 | " \n" + 172 | "

\n" + 173 | "

\n" + 174 | "
\n" + 175 | "
"); 176 | }]); 177 | angular.module('template/ngLoader/ngLoaderTemplate7.html', []).run(['$templateCache', 178 | function($templateCache) { 179 | $templateCache.put('template/ngLoader/ngLoaderTemplate7.html', 180 | "
\n" + 181 | "
\n" + 182 | " \n" + 184 | " \n" + 185 | " \n" + 188 | " \n" + 189 | " \n" + 190 | " \n" + 193 | " \n" + 194 | " \n" + 195 | " \n" + 198 | " \n" + 199 | " \n" + 200 | " \n" + 203 | " \n" + 204 | " \n" + 205 | "

\n" + 206 | "

\n" + 207 | "
\n" + 208 | "
"); 209 | }]); 210 | angular.module('template/ngLoader/ngLoaderTemplate8.html', []).run(['$templateCache', 211 | function($templateCache) { 212 | $templateCache.put('template/ngLoader/ngLoaderTemplate8.html', 213 | "
\n" + 214 | "
\n" + 215 | " \n" + 217 | " \n" + 218 | " \n" + 219 | " \n" + 220 | " \n" + 221 | " \n" + 222 | " \n" + 223 | " \n" + 224 | " \n" + 225 | " \n" + 226 | " \n" + 227 | " \n" + 228 | " \n" + 229 | " \n" + 230 | " \n" + 231 | " \n" + 232 | " \n" + 233 | "

\n" + 234 | "

\n" + 235 | "
\n" + 236 | "
"); 237 | }]); 238 | angular.module('template/ngLoader/ngLoaderTemplate9.html', []).run(['$templateCache', 239 | function($templateCache) { 240 | $templateCache.put('template/ngLoader/ngLoaderTemplate9.html', 241 | "
\n" + 242 | "
\n" + 243 | "
\n" + 244 | " \n" + 245 | " \n" + 246 | " \n" + 247 | "
\n" + 248 | "

\n" + 249 | "

\n" + 250 | "
\n" + 251 | "
"); 252 | }]); 253 | 254 | angular.module('ngLoader', ['ngLoaderTemplates']) 255 | .directive('loader', ['$timeout', 256 | function($timeout) { 257 | return { 258 | scope: { 259 | working: '=', 260 | progressPercentage: '=?', 261 | message: '=?', 262 | disableBackground: '@?' 263 | }, 264 | restrict: 'AE', 265 | replace: true, 266 | templateUrl: function(tElem, tAttrs) { 267 | if (tAttrs.template !== undefined) { 268 | if (isNaN(parseInt(tAttrs.template))) { 269 | console.error('Directive Error! Attribute \'template\' must be a number. Found \'' + tAttrs.template + '\''); 270 | } 271 | else if (parseInt(tAttrs.template) < 1 || parseInt(tAttrs.template) > 9) { 272 | console.error('Directive Error! Attribute \'template\' must be a number between 1 and 9. Found \'' + tAttrs.template + '\''); 273 | } 274 | else { 275 | return 'template/ngLoader/ngLoaderTemplate' + tAttrs.template + '.html'; 276 | } 277 | } 278 | return 'template/ngLoader/ngLoaderTemplate9.html'; 279 | }, 280 | link: function(scope, elem, attrs) { 281 | scope.disableBackground = scope.$eval(scope.disableBackground); 282 | 283 | if (scope.disableBackground === true) { 284 | elem.css({ 285 | 'background': 'rgba(0,0,0,0.225)', 286 | 'z-index': '9999' 287 | }); 288 | } else if (scope.disableBackground === undefined) { 289 | 290 | } else { 291 | console.error('Directive Error! Attribute \'disable-background\' must be \'true\' for \'false\'. Found \'' + scope.disableBackground + '\''); 292 | } 293 | 294 | var content = elem.find('div')[0]; 295 | 296 | function positionLoader(watchFunction) { 297 | $timeout(function() { 298 | content.style.marginTop = -(content.offsetHeight / 2)+'px'; 299 | content.style.marginLeft = -(content.offsetWidth / 2)+'px'; 300 | }); 301 | } 302 | 303 | var positionWatch = scope.$watch('working', function(newValue, oldValue) { 304 | if (newValue === true) { 305 | positionLoader(positionWatch); 306 | } 307 | }); 308 | 309 | var messageWatch = scope.$watch('message', function(newValue, oldValue) { 310 | if (newValue != oldValue) { 311 | positionLoader(messageWatch); 312 | } 313 | }); 314 | } 315 | }; 316 | }]); -------------------------------------------------------------------------------- /ngLoader.min.css: -------------------------------------------------------------------------------- 1 | .loader-bars{height:25px;width:30px;margin:0 auto;text-align:center}.bar{background-color:#ccc;float:left;height:25px;margin-left:4px;width:5px;opacity:0.1;-moz-animation-name:bounceG;-moz-animation-duration:1.5s;-moz-animation-iteration-count:infinite;-moz-animation-direction:linear;-moz-transform:scale(0.7);-webkit-animation-name:bounceG;-webkit-animation-duration:1.5s;-webkit-animation-iteration-count:infinite;-webkit-animation-direction:linear;-webkit-transform:scale(0.7);-ms-animation-name:bounceG;-ms-animation-duration:1.5s;-ms-animation-iteration-count:infinite;-ms-animation-direction:linear;-ms-transform:scale(0.7);-o-animation-name:bounceG;-o-animation-duration:1.5s;-o-animation-iteration-count:infinite;-o-animation-direction:linear;-o-transform:scale(0.7);animation-name:bounceG;animation-duration:1.5s;animation-iteration-count:infinite;animation-direction:linear;transform:scale(0.7)}.bar1{-moz-animation-delay:0.45s;-webkit-animation-delay:0.45s;-ms-animation-delay:0.45s;-o-animation-delay:0.45s;animation-delay:0.45s}.bar2{-moz-animation-delay:0.6s;-webkit-animation-delay:0.6s;-ms-animation-delay:0.6s;-o-animation-delay:0.6s;animation-delay:0.6s}.bar3{-moz-animation-delay:0.75s;-webkit-animation-delay:0.75s;-ms-animation-delay:0.75s;-o-animation-delay:0.75s;animation-delay:0.75s}@-moz-keyframes bounceG{0%{-moz-transform:scale(1.2);opacity:1}100%{-moz-transform:scale(0.7);opacity:0.1}}@-webkit-keyframes bounceG{0%{-webkit-transform:scale(1.2);opacity:1}100%{-webkit-transform:scale(0.7);opacity:0.1}}@-ms-keyframes bounceG{0%{-ms-transform:scale(1.2);opacity:1}100%{-ms-transform:scale(0.7);opacity:0.1}}@-o-keyframes bounceG{0%{-o-transform:scale(1.2);opacity:1}100%{-o-transform:scale(0.7);opacity:0.1}}@keyframes bounceG{0%{transform:scale(1.2);opacity:1}100%{transform:scale(0.7);opacity:0.1}} -------------------------------------------------------------------------------- /ngLoader.min.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * AngularJS Loader animation 3 | * @author James Feigel 4 | * @version 1.0.0 5 | */ 6 | angular.module("ngLoaderTemplates",["template/ngLoader/ngLoaderTemplate1.html","template/ngLoader/ngLoaderTemplate2.html","template/ngLoader/ngLoaderTemplate3.html","template/ngLoader/ngLoaderTemplate4.html","template/ngLoader/ngLoaderTemplate5.html","template/ngLoader/ngLoaderTemplate6.html","template/ngLoader/ngLoaderTemplate7.html","template/ngLoader/ngLoaderTemplate8.html","template/ngLoader/ngLoaderTemplate9.html"]),angular.module("template/ngLoader/ngLoaderTemplate1.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate1.html",'
\n
\n \n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate2.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate2.html",'
\n
\n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate3.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate3.html",'
\n
\n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate4.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate4.html",'
\n
\n \n \n \n \n \n \n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate5.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate5.html",'
\n
\n \n \n \n \n \n \n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate6.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate6.html",'
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate7.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate7.html",'
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate8.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate8.html",'
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n

\n

\n
\n
')}]),angular.module("template/ngLoader/ngLoaderTemplate9.html",[]).run(["$templateCache",function(e){e.put("template/ngLoader/ngLoaderTemplate9.html",'
\n
\n
\n \n \n \n
\n

\n

\n
\n
')}]),angular.module("ngLoader",["ngLoaderTemplates"]).directive("loader",["$timeout",function(e){return{scope:{working:"=",progressPercentage:"=?",message:"=?",disableBackground:"@?"},restrict:"AE",replace:!0,templateUrl:function(e,t){if(void 0!==t.template)if(isNaN(parseInt(t.template)))console.error("Directive Error! Attribute 'template' must be a number. Found '"+t.template+"'") 7 | else{if(!(parseInt(t.template)<1||parseInt(t.template)>9))return"template/ngLoader/ngLoaderTemplate"+t.template+".html" 8 | console.error("Directive Error! Attribute 'template' must be a number between 1 and 9. Found '"+t.template+"'")}return"template/ngLoader/ngLoaderTemplate9.html"},link:function(t,a,n){function r(t){e(function(){i.style.marginTop=-(i.offsetHeight/2)+"px",i.style.marginLeft=-(i.offsetWidth/2)+"px"})}t.disableBackground=t.$eval(t.disableBackground),t.disableBackground===!0?a.css({background:"rgba(0,0,0,0.225)","z-index":"9999"}):void 0===t.disableBackground||console.error("Directive Error! Attribute 'disable-background' must be 'true' for 'false'. Found '"+t.disableBackground+"'") 9 | var i=a.find("div")[0],o=t.$watch("working",function(e,t){e===!0&&r(o)}),l=t.$watch("message",function(e,t){e!=t&&r(l)})}}}]) 10 | --------------------------------------------------------------------------------