angular-gantt
Version:
Gantt chart component for AngularJS
249 lines (219 loc) • 11.2 kB
JavaScript
// This file is adapted from Angular UI ngGrid project
// MIT License
// https://github.com/angular-ui/ng-grid/blob/v3.0.0-rc.20/src/js/core/factories/GridApi.js
(function() {
'use strict';
angular.module('gantt')
.factory('GanttApi', ['$q', '$rootScope', 'ganttUtils',
function($q, $rootScope, utils) {
/**
* @ngdoc function
* @name gantt.class:GanttApi
* @description GanttApi provides the ability to register public methods events inside the gantt and allow
* for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.
* @param {object} gantt gantt that owns api
*/
var GanttApi = function GanttApi(gantt) {
this.gantt = gantt;
this.listeners = [];
this.apiId = utils.newId();
};
/**
* @ngdoc function
* @name gantt.class:suppressEvents
* @methodOf gantt.class:GanttApi
* @description Used to execute a function while disabling the specified event listeners.
* Disables the listenerFunctions, executes the callbackFn, and then enables
* the listenerFunctions again
* @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same
* functions that were used in the .on.eventName method
* @param {object} callBackFn function to execute
* @example
* <pre>
* var navigate = function (newRowCol, oldRowCol){
* //do something on navigate
* }
*
* ganttApi.cellNav.on.navigate(scope,navigate);
*
*
* //call the scrollTo event and suppress our navigate listener
* //scrollTo will still raise the event for other listeners
* ganttApi.suppressEvents(navigate, function(){
* ganttApi.cellNav.scrollTo(aRow, aCol);
* });
*
* </pre>
*/
GanttApi.prototype.suppressEvents = function(listenerFuncs, callBackFn) {
var self = this;
var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];
//find all registered listeners
var foundListeners = [];
listeners.forEach(function(l) {
foundListeners = self.listeners.filter(function(lstnr) {
return l === lstnr.handler;
});
});
//deregister all the listeners
foundListeners.forEach(function(l) {
l.dereg();
});
callBackFn();
//reregister all the listeners
foundListeners.forEach(function(l) {
l.dereg = registerEventWithAngular(l.eventId, l.handler, self.gantt, l._this);
});
};
/**
* @ngdoc function
* @name registerEvent
* @methodOf gantt.class:GanttApi
* @description Registers a new event for the given feature. The event will get a
* .raise and .on prepended to it
* <br>
* .raise.eventName() - takes no arguments
* <br/>
* <br/>
* .on.eventName(scope, callBackFn, _this)
* <br/>
* scope - a scope reference to add a deregister call to the scopes .$on('destroy')
* <br/>
* callBackFn - The function to call
* <br/>
* _this - optional this context variable for callbackFn. If omitted, gantt.api will be used for the context
* <br/>
* .on.eventName returns a dereg funtion that will remove the listener. It's not necessary to use it as the listener
* will be removed when the scope is destroyed.
* @param {string} featureName name of the feature that raises the event
* @param {string} eventName name of the event
*/
GanttApi.prototype.registerEvent = function(featureName, eventName) {
var self = this;
if (!self[featureName]) {
self[featureName] = {};
}
var feature = self[featureName];
if (!feature.on) {
feature.on = {};
feature.raise = {};
}
var eventId = 'event:gantt:' + this.apiId + ':' + featureName + ':' + eventName;
// Creating raise event method featureName.raise.eventName
feature.raise[eventName] = function() {
$rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));
};
// Creating on event method featureName.oneventName
feature.on[eventName] = function(scope, handler, _this) {
var deregAngularOn = registerEventWithAngular(eventId, handler, self.gantt, _this);
//track our listener so we can turn off and on
var listener = {
handler: handler,
dereg: deregAngularOn,
eventId: eventId,
scope: scope,
_this: _this
};
self.listeners.push(listener);
var removeListener = function() {
listener.dereg();
var index = self.listeners.indexOf(listener);
self.listeners.splice(index, 1);
};
//destroy tracking when scope is destroyed
scope.$on('$destroy', function() {
removeListener();
});
return removeListener;
};
};
function registerEventWithAngular(eventId, handler, gantt, _this) {
return $rootScope.$on(eventId, function() {
var args = Array.prototype.slice.call(arguments);
args.splice(0, 1); //remove evt argument
handler.apply(_this ? _this : gantt.api, args);
});
}
/**
* @ngdoc function
* @name registerEventsFromObject
* @methodOf gantt.class:GanttApi
* @description Registers features and events from a simple objectMap.
* eventObjectMap must be in this format (multiple features allowed)
* <pre>
* {featureName:
* {
* eventNameOne:function(args){},
* eventNameTwo:function(args){}
* }
* }
* </pre>
* @param {object} eventObjectMap map of feature/event names
*/
GanttApi.prototype.registerEventsFromObject = function(eventObjectMap) {
var self = this;
var features = [];
angular.forEach(eventObjectMap, function(featProp, featPropName) {
var feature = {name: featPropName, events: []};
angular.forEach(featProp, function(prop, propName) {
feature.events.push(propName);
});
features.push(feature);
});
features.forEach(function(feature) {
feature.events.forEach(function(event) {
self.registerEvent(feature.name, event);
});
});
};
/**
* @ngdoc function
* @name registerMethod
* @methodOf gantt.class:GanttApi
* @description Registers a new event for the given feature
* @param {string} featureName name of the feature
* @param {string} methodName name of the method
* @param {object} callBackFn function to execute
* @param {object} _this binds callBackFn 'this' to _this. Defaults to ganttApi.gantt
*/
GanttApi.prototype.registerMethod = function(featureName, methodName, callBackFn, _this) {
if (!this[featureName]) {
this[featureName] = {};
}
var feature = this[featureName];
feature[methodName] = utils.createBoundedWrapper(_this || this.gantt, callBackFn);
};
/**
* @ngdoc function
* @name registerMethodsFromObject
* @methodOf gantt.class:GanttApi
* @description Registers features and methods from a simple objectMap.
* eventObjectMap must be in this format (multiple features allowed)
* <br>
* {featureName:
* {
* methodNameOne:function(args){},
* methodNameTwo:function(args){}
* }
* @param {object} eventObjectMap map of feature/event names
* @param {object} _this binds this to _this for all functions. Defaults to ganttApi.gantt
*/
GanttApi.prototype.registerMethodsFromObject = function(methodMap, _this) {
var self = this;
var features = [];
angular.forEach(methodMap, function(featProp, featPropName) {
var feature = {name: featPropName, methods: []};
angular.forEach(featProp, function(prop, propName) {
feature.methods.push({name: propName, fn: prop});
});
features.push(feature);
});
features.forEach(function(feature) {
feature.methods.forEach(function(method) {
self.registerMethod(feature.name, method.name, method.fn, _this);
});
});
};
return GanttApi;
}]);
})();