we are using weekCalendar with 2 different eventSources, as we are using 2 different eventTypes. one of this eventSource has a dynamic parameter (user) as well ...
var cachableEventManager = {
settings: {
queryStringParameters: {
start: 'start',
end: 'end',
userIds: 'userIds',
transformUserIds: function (userIds) {
return userIds;
},
transformStartDate: function (startDate) {
return startDate.getTime() / 1000;
},
transformEndDate: function (endDate) {
return endDate.getTime() / 1000;
}
},
additionalDays: 7, // how many should be removed from startDate and added to endDate
sources: null, // define an array with strings (= plain urls) or objects with properties url and data
eventLoading: null, // this will be kicked off, if we need to load data via $.ajax
eventFinishedLoading: null, // this will be kicked off, if all $.ajax-requests are completed
// generic way to query against objects
getUserId: function (index, user) {
return index;
},
getEventUserId: function (event) {
return event.userId;
},
getParsedEventStart: function (event) {
var start = event.start;
var typeofStart = typeof start;
if (typeofStart == 'object') {
return start;
}
return Date.parse(start);
},
getParsedEventEnd: function (event) {
var end = event.end;
var typeofEnd = typeof end;
if (typeofEnd == 'object') {
return end;
}
return Date.parse(end);
},
getEventId: function (event) {
return event.id;
}
},
fetchData: function (callback, startDate, endDate, users) {
var self = this;
self._buildAdaptedSources();
var adaptedSourcesLength = self._adaptedSources.length;
if (!adaptedSourcesLength) {
return;
}
var pendingAdaptedSourcesCount = adaptedSourcesLength;
var currentData = new Array();
if ($.isFunction(self.settings.eventLoading)) {
self.settings.eventLoading();
}
for (var i = 0; i < adaptedSourcesLength; i++) {
var adaptedSource = self._adaptedSources[i];
var adaptedOptions = self._buildAdaptedOptions(adaptedSource, startDate, endDate, users);
self._fetchDataFromAdaptedSource(adaptedSource, adaptedOptions, function (data) {
if (data) {
currentData = currentData.concat(data);
}
pendingAdaptedSourcesCount--;
if (!pendingAdaptedSourcesCount) {
callback(currentData);
if ($.isFunction(self.settings.eventFinishedLoading)) {
self.settings.eventFinishedLoading();
}
}
});
}
},
_adaptedSources: null,
_buildAdaptedSources: function () {
var self = this;
if (!self.settings.sources || !self.settings.sources.length) {
return;
}
if (self._adaptedSources) {
return;
}
var adaptedSources = new Array();
for (var i = 0; i < self.settings.sources.length; i++) {
var source = self.settings.sources[i];
var typeOfSource = typeof source;
if (typeOfSource == 'object') {
source = {
url: source.url,
staticData: source.data || [],
sourceIndex: i,
useUsers: source.useUsers || false
}
}
else if (typeOfSource == 'string') {
source = {
url: source,
staticData: [],
sourceIndex: sourceIndex,
useUsers: false
};
}
else {
// currently we cannot deal with anything different than strings (= plain url) or objects
throw '_fetchDataFromSource works with urls only - no functions or alikes supported'
}
adaptedSources.push(source);
}
self._adaptedSources = adaptedSources;
},
_cache: new Array(),
_addToCache: function (adaptedSource, adaptedOptions, result) {
var self = this;
var cacheForAdaptedSource = self._getCacheForAdaptedSource(adaptedSource);
cacheForAdaptedSource.addDateRange(adaptedOptions);
$.each(result, function (index, element) {
cacheForAdaptedSource.addEvent(element);
});
},
_getCacheForAdaptedSource: function (adaptedSource) {
var manager = this;
var cacheForAdaptedSource = manager._cache[adaptedSource.sourceIndex];
if (!cacheForAdaptedSource) {
cacheForAdaptedSource = {
_adaptedSource: adaptedSource,
_cacheForUsers: null, // this could be an array of 'cacheForUser' or a single 'cacheForUser' - depending on adaptedSource.useUsers
_getCacheForUser: function (userId) {
var self = this;
var cacheForUser;
if (!self._adaptedSource.useUsers) {
cacheForUser = self._cacheForUsers;
if (!cacheForUser) {
cacheForUser = self._createCacheForUser(userId);
self._cacheForUsers = cacheForUser;
}
}
else {
if (!self._cacheForUsers) {
self._cacheForUsers = new Array();
}
else {
$.each(self._cacheForUsers, function (index, element) {
if (element.userId == userId) {
cacheForUser = element;
}
});
}
if (!cacheForUser) {
cacheForUser = self._createCacheForUser(userId);
self._cacheForUsers.push(cacheForUser);
}
}
return cacheForUser;
},
_createCacheForUser: function (userId) {
var cacheForUser = {
userId: userId,
events: new Array(),
addEvent: function (event) {
var self = this;
event = manager._cloneEvent(event);
event = self._parseEvent(event);
self.events.push(event);
},
_parseEvent: function (event) {
var self = this;
var eventStartDate = manager.settings.getParsedEventStart(event);
var eventEndDate = manager.settings.getParsedEventEnd(event);
event.startDate = eventStartDate;
event.endDate = eventEndDate;
return event;
},
getEvents: function (startDate, endDate) {
var self = this;
var result = new Array();
$.each(self.events, function (index, element) {
var overlaps = element.startDate <= endDate && element.endDate >= startDate;
if (overlaps) {
var copiedElement = manager._cloneEvent(element);
result.push(element);
}
});
return result;
}
};
return cacheForUser;
},
addEvent: function (event) {
var self = this;
var userId = manager.settings.getEventUserId(event);
var cacheForUser = self._getCacheForUser(userId);
cacheForUser.addEvent(event);
},
getEvents: function (startDate, endDate, userId) {
var self = this;
var cacheForUser = self._getCacheForUser(userId);
return cacheForUser.getEvents(startDate, endDate);
},
_requestDateRanges: new Array(),
addDateRange: function (adaptedOptions) {
var self = this;
if (self._adaptedSource.useUsers) {
$.each(adaptedOptions.adaptedUsers, function (index, element) {
var userId = manager.settings.getUserId(index, element);
self._requestDateRanges.push({
startDate: adaptedOptions.adaptedStartDate,
endDate: adaptedOptions.adaptedEndDate,
userId: userId
});
});
}
else {
self._requestDateRanges.push({
startDate: adaptedOptions.adaptedStartDate,
endDate: adaptedOptions.adaptedEndDate
});
}
},
hasDateRange: function (startDate, endDate, userId) {
var self = this;
var success = false;
$.each(self._requestDateRanges, function (index, element) {
if (success) {
return;
}
success = (userId ? element.userId == userId : true) && element.startDate <= endDate && element.endDate >= startDate;
});
return success;
},
getAdaptedDateRange: function (startDate, endDate, userId) {
var self = this;
var dateRange = {
startDate: manager._cloneDate(startDate),
endDate: manager._cloneDate(endDate)
};
dateRange.startDate.setDate(dateRange.startDate.getDate() - manager.settings.additionalDays);
dateRange.endDate.setDate(dateRange.endDate.getDate() + manager.settings.additionalDays);
$.each(self._requestDateRanges, function (index, element) {
if (self._adaptedSource.useUsers) {
if (element.userId != userId) {
return;
}
}
if (element.startDate < dateRange.startDate
&& dateRange.startDate < element.endDate
&& element.endDate < dateRange.endDate) {
dateRange.startDate = manager._cloneDate(element.endDate);
}
if (dateRange.startDate < element.startDate
&& element.startDate < dateRange.endDate
&& dateRange.endDate < element.endDate) {
dateRange.endDate = manager._cloneDate(element.startDate);
}
});
return dateRange;
}
};
manager._cache[adaptedSource.sourceIndex] = cacheForAdaptedSource;
}
return cacheForAdaptedSource;
},
_buildAdaptedOptions: function (adaptedSource, startDate, endDate, users) {
var self = this;
var adaptedStartDate;
var adaptedEndDate;
var adaptedUsers = new Array();
var adaptedData = new Array();
var cachedEvents;
var cacheForAdaptedSource = self._getCacheForAdaptedSource(adaptedSource);
if (adaptedSource.useUsers) {
$.each(users, function (index, element) {
var userId = self.settings.getUserId(index, element);
var hasDateRange = cacheForAdaptedSource.hasDateRange(startDate, endDate, userId);
if (hasDateRange) {
if (!cachedEvents) {
cachedEvents = new Array();
}
var events = cacheForAdaptedSource.getEvents(startDate, endDate, userId);
cachedEvents = cachedEvents.concat(events);
}
else {
adaptedUsers.push(element);
var dateRange = cacheForAdaptedSource.getAdaptedDateRange(startDate, endDate, userId);
if (!adaptedStartDate) {
adaptedStartDate = dateRange.startDate;
}
if (!adaptedEndDate) {
adaptedEndDate = dateRange.endDate;
}
}
});
}
else {
var hasDateRange = cacheForAdaptedSource.hasDateRange(startDate, endDate);
if (hasDateRange) {
cachedEvents = cacheForAdaptedSource.getEvents(startDate, endDate);
}
else {
var dateRange = cacheForAdaptedSource.getAdaptedDateRange(startDate, endDate);
adaptedStartDate = dateRange.startDate;
adaptedEndDate = dateRange.endDate;
}
}
if (adaptedUsers.length) {
var userIds = new Array();
$.each(adaptedUsers, function (index, element) {
var userId = self.settings.getUserId(index, element);
userIds.push(userId);
});
adaptedData[self.settings.queryStringParameters.userIds] = self.settings.queryStringParameters.transformUserIds(userIds);
}
if (adaptedStartDate && adaptedEndDate) {
adaptedData[self.settings.queryStringParameters.start] = self.settings.queryStringParameters.transformStartDate(adaptedStartDate);
adaptedData[self.settings.queryStringParameters.end] = self.settings.queryStringParameters.transformEndDate(adaptedEndDate);
}
var adaptedOptions = {
adaptedStartDate: adaptedStartDate,
adaptedEndDate: adaptedEndDate,
adaptedUsers: adaptedUsers,
adaptedData: adaptedData,
cachedEvents: cachedEvents
};
return adaptedOptions;
},
_fetchDataFromAdaptedSource: function (adaptedSource, adaptedOptions, callback) {
var self = this;
var cachedEvents = adaptedOptions.cachedEvents;
var needFetch = false;
if (adaptedSource.useUsers && adaptedOptions.adaptedUsers.length) {
needFetch = true;
}
else if (adaptedOptions.adaptedStartDate && adaptedOptions.adaptedEndDate) {
needFetch = true;
}
if (!needFetch) {
if (cachedEvents) {
callback(cachedEvents);
}
return;
}
var staticData = adaptedSource.staticData;
var adaptedData = adaptedOptions.adaptedData;
data = jQuery.extend({}, staticData, adaptedData);
var options = {
url: adaptedSource.url,
data: data,
dataType: 'json',
success: function (result) {
self._addToCache(adaptedSource, adaptedOptions, result);
if (cachedEvents) {
result = result.concat(cachedEvents);
}
callback(result);
}
};
$.ajax(options);
},
_cloneDate: function (date) {
var clonedDate = new Date(date.getTime());
return clonedDate;
},
_cloneEvent: function (event) {
var clonedEvent = jQuery.extend(true, {}, event);
return clonedEvent;
}
};
cachableEventManager.settings.queryStringParameters.start = 'customStart';
cachableEventManager.settings.queryStringParameters.end = 'customeEnd';
cachableEventManager.settings.queryStringParameters.userIds = 'userIds';
cachableEventManager.settings.additionalDays = 14;
cachableEventManager.settings.eventLoading = function () {
$.blockUI();
};
cachableEventManager.settings.eventFinishedLoading = function () {
$.unblockUI();
};
cachableEventManager.settings.sources = [
{
'url': 'service.wcf',
'data': {
'staticParamter': 'testValue'
},
'useUsers': true
}
];
var weekCalendar = $('#weekCalendar');
weekCalendar.weekCalendar({
data: function (start, end, callback) {
// maybe update this.users here ...
cachableEventManager.fetchData(callback, start, end, this.users);
}
});