1 angular.module('cgBusy',[]);
3 //loosely modeled after angular-promise-tracker
4 angular.module('cgBusy').factory('_cgBusyTrackerFactory',['$timeout','$q',function($timeout,$q){
10 tracker.delayPromise = null;
11 tracker.durationPromise = null;
12 tracker.delayJustFinished = false;
14 tracker.reset = function(options){
15 tracker.minDuration = options.minDuration;
17 tracker.promises = [];
18 angular.forEach(options.promises,function(p){
19 if (!p || p.$cgBusyFulfilled) {
22 addPromiseLikeThing(p);
25 if (tracker.promises.length === 0) {
26 //if we have no promises then dont do the delay or duration stuff
30 tracker.delayJustFinished = false;
32 tracker.delayPromise = $timeout(function(){
33 tracker.delayPromise = null;
34 tracker.delayJustFinished = true;
35 },parseInt(options.delay,10));
37 if (options.minDuration) {
38 tracker.durationPromise = $timeout(function(){
39 tracker.durationPromise = null;
40 },parseInt(options.minDuration,10) + (options.delay ? parseInt(options.delay,10) : 0));
44 tracker.isPromise = function(promiseThing){
45 var then = promiseThing && (promiseThing.then || promiseThing.$then ||
46 (promiseThing.$promise && promiseThing.$promise.then));
48 return typeof then !== 'undefined';
51 tracker.callThen = function(promiseThing,success,error){
53 if (promiseThing.then || promiseThing.$then){
54 promise = promiseThing;
55 } else if (promiseThing.$promise){
56 promise = promiseThing.$promise;
57 } else if (promiseThing.denodeify){
58 promise = $q.when(promiseThing);
61 var then = (promise.then || promise.$then);
63 then.call(promise,success,error);
66 var addPromiseLikeThing = function(promise){
68 if (!tracker.isPromise(promise)) {
69 throw new Error('cgBusy expects a promise (or something that has a .promise or .$promise');
72 if (tracker.promises.indexOf(promise) !== -1){
75 tracker.promises.push(promise);
77 tracker.callThen(promise, function(){
78 promise.$cgBusyFulfilled = true;
79 if (tracker.promises.indexOf(promise) === -1) {
82 tracker.promises.splice(tracker.promises.indexOf(promise),1);
84 promise.$cgBusyFulfilled = true;
85 if (tracker.promises.indexOf(promise) === -1) {
88 tracker.promises.splice(tracker.promises.indexOf(promise),1);
92 tracker.active = function(){
93 if (tracker.delayPromise){
97 if (!tracker.delayJustFinished){
98 if (tracker.durationPromise){
101 return tracker.promises.length > 0;
103 //if both delay and min duration are set,
104 //we don't want to initiate the min duration if the
105 //promise finished before the delay was complete
106 tracker.delayJustFinished = false;
107 if (tracker.promises.length === 0) {
108 tracker.durationPromise = null;
110 return tracker.promises.length > 0;
119 angular.module('cgBusy').value('cgBusyDefaults',{});
121 angular.module('cgBusy').directive('cgBusy',['$compile','$templateCache','cgBusyDefaults','$http','_cgBusyTrackerFactory',
122 function($compile,$templateCache,cgBusyDefaults,$http,_cgBusyTrackerFactory){
125 link: function(scope, element, attrs, fn) {
127 //Apply position:relative to parent element if necessary
128 var position = element.css('position');
129 if (position === 'static' || position === '' || typeof position === 'undefined'){
130 element.css('position','relative');
138 var tracker = _cgBusyTrackerFactory();
141 templateUrl: 'angular-busy.html',
145 message:'Please Wait...',
146 wrapperClass: 'cg-busy cg-busy-animation'
149 angular.extend(defaults,cgBusyDefaults);
151 scope.$watchCollection(attrs.cgBusy,function(options){
154 options = {promise:null};
157 if (angular.isString(options)) {
158 throw new Error('Invalid value for cg-busy. cgBusy no longer accepts string ids to represent promises/trackers.');
161 //is it an array (of promises) or one promise
162 if (angular.isArray(options) || tracker.isPromise(options)) {
163 options = {promise:options};
166 options = angular.extend(angular.copy(defaults),options);
168 if (!options.templateUrl){
169 options.templateUrl = defaults.templateUrl;
172 if (!angular.isArray(options.promise)){
173 options.promise = [options.promise];
176 // options.promise = angular.isArray(options.promise) ? options.promise : [options.promise];
177 // options.message = options.message ? options.message : 'Please Wait...';
178 // options.template = options.template ? options.template : cgBusyTemplateName;
179 // options.minDuration = options.minDuration ? options.minDuration : 0;
180 // options.delay = options.delay ? options.delay : 0;
182 if (!templateScope) {
183 templateScope = scope.$new();
186 templateScope.$message = options.message;
188 if (!angular.equals(tracker.promises,options.promise)) {
190 promises:options.promise,
192 minDuration: options.minDuration
196 templateScope.$cgBusyIsActive = function() {
197 return tracker.active();
201 if (!templateElement || currentTemplate !== options.templateUrl || backdrop !== options.backdrop) {
203 if (templateElement) {
204 templateElement.remove();
206 if (backdropElement){
207 backdropElement.remove();
210 currentTemplate = options.templateUrl;
211 backdrop = options.backdrop;
213 $http.get(currentTemplate,{cache: $templateCache}).success(function(indicatorTemplate){
215 options.backdrop = typeof options.backdrop === 'undefined' ? true : options.backdrop;
217 if (options.backdrop){
218 var backdrop = '<div class="cg-busy cg-busy-backdrop cg-busy-backdrop-animation ng-hide" ng-show="$cgBusyIsActive()"></div>';
219 backdropElement = $compile(backdrop)(templateScope);
220 element.append(backdropElement);
223 var template = '<div class="'+options.wrapperClass+' ng-hide" ng-show="$cgBusyIsActive()">' + indicatorTemplate + '</div>';
224 templateElement = $compile(template)(templateScope);
226 angular.element(templateElement.children()[0])
227 .css('position','absolute')
232 element.append(templateElement);
234 }).error(function(data){
235 throw new Error('Template specified for cgBusy ('+options.templateUrl+') could not be loaded. ' + data);