angular.module('cgBusy',[]); //loosely modeled after angular-promise-tracker angular.module('cgBusy').factory('_cgBusyTrackerFactory',['$timeout','$q',function($timeout,$q){ return function(){ var tracker = {}; tracker.promises = []; tracker.delayPromise = null; tracker.durationPromise = null; tracker.delayJustFinished = false; tracker.reset = function(options){ tracker.minDuration = options.minDuration; tracker.promises = []; angular.forEach(options.promises,function(p){ if (!p || p.$cgBusyFulfilled) { return; } addPromiseLikeThing(p); }); if (tracker.promises.length === 0) { //if we have no promises then dont do the delay or duration stuff return; } tracker.delayJustFinished = false; if (options.delay) { tracker.delayPromise = $timeout(function(){ tracker.delayPromise = null; tracker.delayJustFinished = true; },parseInt(options.delay,10)); } if (options.minDuration) { tracker.durationPromise = $timeout(function(){ tracker.durationPromise = null; },parseInt(options.minDuration,10) + (options.delay ? parseInt(options.delay,10) : 0)); } }; tracker.isPromise = function(promiseThing){ var then = promiseThing && (promiseThing.then || promiseThing.$then || (promiseThing.$promise && promiseThing.$promise.then)); return typeof then !== 'undefined'; }; tracker.callThen = function(promiseThing,success,error){ var promise; if (promiseThing.then || promiseThing.$then){ promise = promiseThing; } else if (promiseThing.$promise){ promise = promiseThing.$promise; } else if (promiseThing.denodeify){ promise = $q.when(promiseThing); } var then = (promise.then || promise.$then); then.call(promise,success,error); }; var addPromiseLikeThing = function(promise){ if (!tracker.isPromise(promise)) { throw new Error('cgBusy expects a promise (or something that has a .promise or .$promise'); } if (tracker.promises.indexOf(promise) !== -1){ return; } tracker.promises.push(promise); tracker.callThen(promise, function(){ promise.$cgBusyFulfilled = true; if (tracker.promises.indexOf(promise) === -1) { return; } tracker.promises.splice(tracker.promises.indexOf(promise),1); },function(){ promise.$cgBusyFulfilled = true; if (tracker.promises.indexOf(promise) === -1) { return; } tracker.promises.splice(tracker.promises.indexOf(promise),1); }); }; tracker.active = function(){ if (tracker.delayPromise){ return false; } if (!tracker.delayJustFinished){ if (tracker.durationPromise){ return true; } return tracker.promises.length > 0; } else { //if both delay and min duration are set, //we don't want to initiate the min duration if the //promise finished before the delay was complete tracker.delayJustFinished = false; if (tracker.promises.length === 0) { tracker.durationPromise = null; } return tracker.promises.length > 0; } }; return tracker; }; }]); angular.module('cgBusy').value('cgBusyDefaults',{}); angular.module('cgBusy').directive('cgBusy',['$compile','$templateCache','cgBusyDefaults','$http','_cgBusyTrackerFactory', function($compile,$templateCache,cgBusyDefaults,$http,_cgBusyTrackerFactory){ return { restrict: 'A', link: function(scope, element, attrs, fn) { //Apply position:relative to parent element if necessary var position = element.css('position'); if (position === 'static' || position === '' || typeof position === 'undefined'){ element.css('position','relative'); } var templateElement; var backdropElement; var currentTemplate; var templateScope; var backdrop; var tracker = _cgBusyTrackerFactory(); var defaults = { templateUrl: 'angular-busy.html', delay:0, minDuration:0, backdrop: true, message:'Please Wait...', wrapperClass: 'cg-busy cg-busy-animation' }; angular.extend(defaults,cgBusyDefaults); scope.$watchCollection(attrs.cgBusy,function(options){ if (!options) { options = {promise:null}; } if (angular.isString(options)) { throw new Error('Invalid value for cg-busy. cgBusy no longer accepts string ids to represent promises/trackers.'); } //is it an array (of promises) or one promise if (angular.isArray(options) || tracker.isPromise(options)) { options = {promise:options}; } options = angular.extend(angular.copy(defaults),options); if (!options.templateUrl){ options.templateUrl = defaults.templateUrl; } if (!angular.isArray(options.promise)){ options.promise = [options.promise]; } // options.promise = angular.isArray(options.promise) ? options.promise : [options.promise]; // options.message = options.message ? options.message : 'Please Wait...'; // options.template = options.template ? options.template : cgBusyTemplateName; // options.minDuration = options.minDuration ? options.minDuration : 0; // options.delay = options.delay ? options.delay : 0; if (!templateScope) { templateScope = scope.$new(); } templateScope.$message = options.message; if (!angular.equals(tracker.promises,options.promise)) { tracker.reset({ promises:options.promise, delay:options.delay, minDuration: options.minDuration }); } templateScope.$cgBusyIsActive = function() { return tracker.active(); }; if (!templateElement || currentTemplate !== options.templateUrl || backdrop !== options.backdrop) { if (templateElement) { templateElement.remove(); } if (backdropElement){ backdropElement.remove(); } currentTemplate = options.templateUrl; backdrop = options.backdrop; $http.get(currentTemplate,{cache: $templateCache}).success(function(indicatorTemplate){ options.backdrop = typeof options.backdrop === 'undefined' ? true : options.backdrop; if (options.backdrop){ var backdrop = '
'; backdropElement = $compile(backdrop)(templateScope); element.append(backdropElement); } var template = ' '; templateElement = $compile(template)(templateScope); angular.element(templateElement.children()[0]) .css('position','absolute') .css('top',0) .css('left',0) .css('right',0) .css('bottom',0); element.append(templateElement); }).error(function(data){ throw new Error('Template specified for cgBusy ('+options.templateUrl+') could not be loaded. ' + data); }); } },true); } }; } ]); angular.module('cgBusy').run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('angular-busy.html', "