fixed issue 679, a bit of event fetching rejiggering
This commit is contained in:
parent
8086b3d252
commit
c1a19a24c8
6 changed files with 289 additions and 242 deletions
129
src/Calendar.js
129
src/Calendar.js
|
@ -8,10 +8,12 @@ function Calendar(element, options, eventSources) {
|
||||||
t.options = options;
|
t.options = options;
|
||||||
t.render = render;
|
t.render = render;
|
||||||
t.destroy = destroy;
|
t.destroy = destroy;
|
||||||
|
t.refetchEvents = refetchEvents;
|
||||||
|
t.reportEvents = reportEvents;
|
||||||
|
t.reportEventChange = reportEventChange;
|
||||||
t.changeView = changeView;
|
t.changeView = changeView;
|
||||||
t.select = select;
|
t.select = select;
|
||||||
t.unselect = unselect;
|
t.unselect = unselect;
|
||||||
t.rerenderEvents = rerenderEvents; // todo: seems liks an EventManager thing
|
|
||||||
t.prev = prev;
|
t.prev = prev;
|
||||||
t.next = next;
|
t.next = next;
|
||||||
t.prevYear = prevYear;
|
t.prevYear = prevYear;
|
||||||
|
@ -29,9 +31,8 @@ function Calendar(element, options, eventSources) {
|
||||||
|
|
||||||
// imports
|
// imports
|
||||||
EventManager.call(t, options, eventSources);
|
EventManager.call(t, options, eventSources);
|
||||||
var fetchEvents = t.fetchEvents;
|
|
||||||
var isFetchNeeded = t.isFetchNeeded;
|
var isFetchNeeded = t.isFetchNeeded;
|
||||||
var clientEvents = t.clientEvents;
|
var fetchEvents = t.fetchEvents;
|
||||||
|
|
||||||
|
|
||||||
// locals
|
// locals
|
||||||
|
@ -48,6 +49,7 @@ function Calendar(element, options, eventSources) {
|
||||||
var resizeUID = 0;
|
var resizeUID = 0;
|
||||||
var ignoreWindowResize = 0;
|
var ignoreWindowResize = 0;
|
||||||
var date = new Date();
|
var date = new Date();
|
||||||
|
var events = [];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,8 +65,8 @@ function Calendar(element, options, eventSources) {
|
||||||
initialRender();
|
initialRender();
|
||||||
}else{
|
}else{
|
||||||
calcSize();
|
calcSize();
|
||||||
sizesDirty();
|
markSizesDirty();
|
||||||
eventsDirty();
|
markEventsDirty();
|
||||||
renderView(inc);
|
renderView(inc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,10 +142,6 @@ function Calendar(element, options, eventSources) {
|
||||||
var newViewElement;
|
var newViewElement;
|
||||||
|
|
||||||
if (oldView) {
|
if (oldView) {
|
||||||
if (oldView.eventsChanged) {
|
|
||||||
eventsDirty();
|
|
||||||
oldView.eventDirty = oldView.eventsChanged = false;
|
|
||||||
}
|
|
||||||
(oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera)
|
(oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera)
|
||||||
setMinHeight(content, content.height());
|
setMinHeight(content, content.height());
|
||||||
oldView.element.hide();
|
oldView.element.hide();
|
||||||
|
@ -196,29 +194,28 @@ function Calendar(element, options, eventSources) {
|
||||||
calcSize();
|
calcSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var forceEventRender = false;
|
||||||
if (!currentView.start || inc || date < currentView.start || date >= currentView.end) {
|
if (!currentView.start || inc || date < currentView.start || date >= currentView.end) {
|
||||||
|
// view must render an entire new date range (and refetch/render events)
|
||||||
currentView.render(date, inc || 0); // responsible for clearing events
|
currentView.render(date, inc || 0); // responsible for clearing events
|
||||||
setSize(true);
|
setSize(true);
|
||||||
if (!options.lazyFetching || isFetchNeeded()) {
|
forceEventRender = true;
|
||||||
fetchAndRenderEvents();
|
|
||||||
}else{
|
|
||||||
currentView.renderEvents(clientEvents()); // don't refetch
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (currentView.sizeDirty || currentView.eventsDirty || !options.lazyFetching) {
|
else if (currentView.sizeDirty) {
|
||||||
|
// view must resize (and rerender events)
|
||||||
currentView.clearEvents();
|
currentView.clearEvents();
|
||||||
if (currentView.sizeDirty) {
|
setSize();
|
||||||
setSize();
|
forceEventRender = true;
|
||||||
}
|
}
|
||||||
if (!options.lazyFetching || isFetchNeeded()) {
|
else if (currentView.eventsDirty) {
|
||||||
fetchAndRenderEvents();
|
currentView.clearEvents();
|
||||||
}else{
|
forceEventRender = true;
|
||||||
currentView.renderEvents(clientEvents()); // don't refetch
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
elementOuterWidth = element.outerWidth();
|
|
||||||
currentView.sizeDirty = false;
|
currentView.sizeDirty = false;
|
||||||
currentView.eventsDirty = false;
|
currentView.eventsDirty = false;
|
||||||
|
updateEvents(forceEventRender);
|
||||||
|
|
||||||
|
elementOuterWidth = element.outerWidth();
|
||||||
|
|
||||||
header.updateTitle(currentView.title);
|
header.updateTitle(currentView.title);
|
||||||
var today = new Date();
|
var today = new Date();
|
||||||
|
@ -239,6 +236,25 @@ function Calendar(element, options, eventSources) {
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
function updateSize() {
|
||||||
|
markSizesDirty();
|
||||||
|
if (elementVisible()) {
|
||||||
|
calcSize();
|
||||||
|
setSize();
|
||||||
|
unselect();
|
||||||
|
currentView.renderEvents(events);
|
||||||
|
currentView.sizeDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function markSizesDirty() {
|
||||||
|
$.each(viewInstances, function(i, inst) {
|
||||||
|
inst.sizeDirty = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function calcSize() {
|
function calcSize() {
|
||||||
if (options.contentHeight) {
|
if (options.contentHeight) {
|
||||||
suggestedViewHeight = options.contentHeight;
|
suggestedViewHeight = options.contentHeight;
|
||||||
|
@ -272,7 +288,7 @@ function Calendar(element, options, eventSources) {
|
||||||
if (uid == resizeUID && !ignoreWindowResize && elementVisible()) {
|
if (uid == resizeUID && !ignoreWindowResize && elementVisible()) {
|
||||||
if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) {
|
if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) {
|
||||||
ignoreWindowResize++; // in case the windowResize callback changes the height
|
ignoreWindowResize++; // in case the windowResize callback changes the height
|
||||||
sizeChanged();
|
updateSize();
|
||||||
currentView.trigger('windowResize', _element);
|
currentView.trigger('windowResize', _element);
|
||||||
ignoreWindowResize--;
|
ignoreWindowResize--;
|
||||||
}
|
}
|
||||||
|
@ -286,58 +302,57 @@ function Calendar(element, options, eventSources) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// called when we know the element size has changed
|
|
||||||
function sizeChanged() {
|
/* Event Fetching/Rendering
|
||||||
sizesDirty();
|
-----------------------------------------------------------------------------*/
|
||||||
if (elementVisible()) {
|
|
||||||
calcSize();
|
|
||||||
setSize();
|
// fetches events if necessary, rerenders events if necessary (or if forced)
|
||||||
unselect();
|
function updateEvents(forceRender) {
|
||||||
currentView.rerenderEvents();
|
if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) {
|
||||||
currentView.sizeDirty = false;
|
refetchEvents();
|
||||||
|
}
|
||||||
|
else if (forceRender) {
|
||||||
|
rerenderEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// marks other views' sizes as dirty
|
function refetchEvents() {
|
||||||
function sizesDirty() {
|
fetchEvents(currentView.visStart, currentView.visEnd); // will call reportEvents
|
||||||
$.each(viewInstances, function(i, inst) {
|
|
||||||
inst.sizeDirty = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// called when event data arrives
|
||||||
/* Event Rendering
|
function reportEvents(_events) {
|
||||||
-----------------------------------------------------------------------------*/
|
events = _events;
|
||||||
|
rerenderEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// called when any event objects have been added/removed/changed, rerenders
|
// called when a single event's data has been changed
|
||||||
function rerenderEvents() {
|
function reportEventChange(eventID) {
|
||||||
eventsDirty();
|
rerenderEvents(eventID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// attempts to rerenderEvents
|
||||||
|
function rerenderEvents(modifiedEventID) {
|
||||||
|
markEventsDirty();
|
||||||
if (elementVisible()) {
|
if (elementVisible()) {
|
||||||
currentView.clearEvents();
|
currentView.clearEvents();
|
||||||
currentView.renderEvents(clientEvents());
|
currentView.renderEvents(events, modifiedEventID);
|
||||||
currentView.eventsDirty = false;
|
currentView.eventsDirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// marks every views' events as dirty
|
function markEventsDirty() {
|
||||||
function eventsDirty() {
|
|
||||||
$.each(viewInstances, function(i, inst) {
|
$.each(viewInstances, function(i, inst) {
|
||||||
inst.eventsDirty = true;
|
inst.eventsDirty = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// for convenience
|
|
||||||
function fetchAndRenderEvents() {
|
|
||||||
fetchEvents(function(events) {
|
|
||||||
currentView.renderEvents(events); // maintain `this` in view
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Selection
|
/* Selection
|
||||||
|
@ -434,7 +449,7 @@ function Calendar(element, options, eventSources) {
|
||||||
}
|
}
|
||||||
if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') {
|
if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') {
|
||||||
options[name] = value;
|
options[name] = value;
|
||||||
sizeChanged();
|
updateSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
|
|
||||||
var eventGUID = 1;
|
var eventGUID = 1;
|
||||||
|
|
||||||
function EventManager(options, eventSources) {
|
function EventManager(options, sources) {
|
||||||
var t = this;
|
var t = this;
|
||||||
|
|
||||||
|
|
||||||
// exports
|
// exports
|
||||||
t.fetchEvents = fetchEvents;
|
|
||||||
t.refetchEvents = refetchEvents;
|
|
||||||
t.isFetchNeeded = isFetchNeeded;
|
t.isFetchNeeded = isFetchNeeded;
|
||||||
|
t.fetchEvents = fetchEvents;
|
||||||
t.addEventSource = addEventSource;
|
t.addEventSource = addEventSource;
|
||||||
t.removeEventSource = removeEventSource;
|
t.removeEventSource = removeEventSource;
|
||||||
t.updateEvent = updateEvent;
|
t.updateEvent = updateEvent;
|
||||||
|
@ -19,17 +18,91 @@ function EventManager(options, eventSources) {
|
||||||
|
|
||||||
|
|
||||||
// imports
|
// imports
|
||||||
var getDate = t.getDate;
|
|
||||||
var getView = t.getView;
|
|
||||||
var trigger = t.trigger;
|
var trigger = t.trigger;
|
||||||
var rerenderEvents = t.rerenderEvents;
|
var getView = t.getView;
|
||||||
|
var reportEvents = t.reportEvents;
|
||||||
|
|
||||||
|
|
||||||
// locals
|
// locals
|
||||||
var fetchID = 0;
|
var rangeStart, rangeEnd;
|
||||||
var eventStart, eventEnd;
|
var currentFetchID = 0;
|
||||||
var events = [];
|
var pendingSourceCnt = 0;
|
||||||
var loadingLevel = 0;
|
var loadingLevel = 0;
|
||||||
|
var dynamicEventSource = [];
|
||||||
|
var cache = [];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Fetching
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
function isFetchNeeded(start, end) {
|
||||||
|
return !rangeStart || start < rangeStart || end > rangeEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function fetchEvents(start, end) {
|
||||||
|
rangeStart = start;
|
||||||
|
rangeEnd = end;
|
||||||
|
currentFetchID++;
|
||||||
|
cache = [];
|
||||||
|
pendingSourceCnt = sources.length;
|
||||||
|
for (var i=0; i<sources.length; i++) {
|
||||||
|
fetchEventSource(sources[i], currentFetchID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function fetchEventSource(source, fetchID) {
|
||||||
|
_fetchEventSource(source, function(events) {
|
||||||
|
if (fetchID == currentFetchID) {
|
||||||
|
for (var i=0; i<events.length; i++) {
|
||||||
|
normalizeEvent(events[i]);
|
||||||
|
events[i].source = source;
|
||||||
|
}
|
||||||
|
cache = cache.concat(events);
|
||||||
|
pendingSourceCnt--;
|
||||||
|
if (!pendingSourceCnt) {
|
||||||
|
reportEvents(cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _fetchEventSource(source, callback) {
|
||||||
|
if (typeof source == 'string') {
|
||||||
|
var params = {};
|
||||||
|
params[options.startParam] = Math.round(rangeStart.getTime() / 1000);
|
||||||
|
params[options.endParam] = Math.round(rangeEnd.getTime() / 1000);
|
||||||
|
if (options.cacheParam) {
|
||||||
|
params[options.cacheParam] = (new Date()).getTime(); // TODO: deprecate cacheParam
|
||||||
|
}
|
||||||
|
pushLoading();
|
||||||
|
// TODO: respect cache param in ajaxSetup
|
||||||
|
$.ajax({
|
||||||
|
url: source,
|
||||||
|
dataType: 'json',
|
||||||
|
data: params,
|
||||||
|
cache: options.cacheParam || false, // don't let jquery prevent caching if cacheParam is being used
|
||||||
|
success: function(events) {
|
||||||
|
popLoading();
|
||||||
|
callback(events);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if ($.isFunction(source)) {
|
||||||
|
pushLoading();
|
||||||
|
source(cloneDate(rangeStart), cloneDate(rangeEnd), function(events) {
|
||||||
|
popLoading();
|
||||||
|
callback(events);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback(source); // src is an array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,121 +110,25 @@ function EventManager(options, eventSources) {
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
eventSources.unshift([]); // first event source reserved for 'sticky' events
|
sources.push(dynamicEventSource);
|
||||||
|
|
||||||
|
|
||||||
function addEventSource(source) {
|
function addEventSource(source) {
|
||||||
eventSources.push(source);
|
sources.push(source);
|
||||||
fetchEventSource(source, rerenderEvents);
|
pendingSourceCnt++;
|
||||||
|
fetchEventSource(source, currentFetchID); // will eventually call reportEvents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function removeEventSource(source) {
|
function removeEventSource(source) {
|
||||||
eventSources = $.grep(eventSources, function(src) {
|
sources = $.grep(sources, function(src) {
|
||||||
return src != source;
|
return src != source;
|
||||||
});
|
});
|
||||||
// remove all client events from that source
|
// remove all client events from that source
|
||||||
events = $.grep(events, function(e) {
|
cache = $.grep(cache, function(e) {
|
||||||
return e.source != source;
|
return e.source != source;
|
||||||
});
|
});
|
||||||
rerenderEvents();
|
reportEvents(cache);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Fetching
|
|
||||||
-----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
// Fetch from ALL sources. Clear 'events' array and populate
|
|
||||||
function fetchEvents(callback) {
|
|
||||||
events = [];
|
|
||||||
fetchEventSources(eventSources, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// appends to the events array
|
|
||||||
function fetchEventSources(sources, callback) {
|
|
||||||
var savedID = ++fetchID;
|
|
||||||
var queued = sources.length;
|
|
||||||
var origView = getView();
|
|
||||||
eventStart = cloneDate(origView.visStart); // we don't need to make local copies b/c
|
|
||||||
eventEnd = cloneDate(origView.visEnd); // eventStart/eventEnd is only assigned/manipulated here
|
|
||||||
function sourceDone(source, sourceEvents) {
|
|
||||||
var currentView = getView();
|
|
||||||
if (origView != currentView) {
|
|
||||||
origView.eventsDirty = true; // sort of a hack
|
|
||||||
}
|
|
||||||
if (savedID == fetchID && eventStart <= currentView.visStart && eventEnd >= currentView.visEnd) {
|
|
||||||
// same fetchEventSources call, and still in correct date range
|
|
||||||
if ($.inArray(source, eventSources) != -1) { // source hasn't been removed since we started
|
|
||||||
for (var i=0; i<sourceEvents.length; i++) {
|
|
||||||
normalizeEvent(sourceEvents[i]);
|
|
||||||
sourceEvents[i].source = source;
|
|
||||||
}
|
|
||||||
events = events.concat(sourceEvents);
|
|
||||||
}
|
|
||||||
if (!--queued) {
|
|
||||||
if (callback) {
|
|
||||||
callback(events);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (var i=0; i<sources.length; i++) {
|
|
||||||
_fetchEventSource(sources[i], sourceDone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function _fetchEventSource(src, callback) {
|
|
||||||
function reportEvents(a) {
|
|
||||||
callback(src, a);
|
|
||||||
}
|
|
||||||
function reportEventsAndPop(a) {
|
|
||||||
reportEvents(a);
|
|
||||||
popLoading();
|
|
||||||
}
|
|
||||||
if (typeof src == 'string') {
|
|
||||||
var params = {};
|
|
||||||
params[options.startParam] = Math.round(eventStart.getTime() / 1000);
|
|
||||||
params[options.endParam] = Math.round(eventEnd.getTime() / 1000);
|
|
||||||
if (options.cacheParam) {
|
|
||||||
params[options.cacheParam] = (new Date()).getTime(); // TODO: deprecate cacheParam
|
|
||||||
}
|
|
||||||
pushLoading();
|
|
||||||
// TODO: respect cache param in ajaxSetup
|
|
||||||
$.ajax({
|
|
||||||
url: src,
|
|
||||||
dataType: 'json',
|
|
||||||
data: params,
|
|
||||||
cache: options.cacheParam || false, // don't let jquery prevent caching if cacheParam is being used
|
|
||||||
success: reportEventsAndPop
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if ($.isFunction(src)) {
|
|
||||||
pushLoading();
|
|
||||||
src(cloneDate(eventStart), cloneDate(eventEnd), reportEventsAndPop);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reportEvents(src); // src is an array
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function fetchEventSource(src, callback) {
|
|
||||||
fetchEventSources([src], callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function refetchEvents() {
|
|
||||||
fetchEvents(rerenderEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function isFetchNeeded() {
|
|
||||||
var view = getView();
|
|
||||||
return !eventStart || view.visStart < eventStart || view.visEnd > eventEnd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,14 +138,14 @@ function EventManager(options, eventSources) {
|
||||||
|
|
||||||
|
|
||||||
function updateEvent(event) { // update an existing event
|
function updateEvent(event) { // update an existing event
|
||||||
var i, len = events.length, e,
|
var i, len = cache.length, e,
|
||||||
defaultEventEnd = getView().defaultEventEnd,
|
defaultEventEnd = getView().defaultEventEnd, // getView???
|
||||||
startDelta = event.start - event._start,
|
startDelta = event.start - event._start,
|
||||||
endDelta = event.end ?
|
endDelta = event.end ?
|
||||||
(event.end - (event._end || defaultEventEnd(event))) // event._end would be null if event.end
|
(event.end - (event._end || defaultEventEnd(event))) // event._end would be null if event.end
|
||||||
: 0; // was null and event was just resized
|
: 0; // was null and event was just resized
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
e = events[i];
|
e = cache[i];
|
||||||
if (e._id == event._id && e != event) {
|
if (e._id == event._id && e != event) {
|
||||||
e.start = new Date(+e.start + startDelta);
|
e.start = new Date(+e.start + startDelta);
|
||||||
if (event.end) {
|
if (event.end) {
|
||||||
|
@ -189,29 +166,30 @@ function EventManager(options, eventSources) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
normalizeEvent(event);
|
normalizeEvent(event);
|
||||||
rerenderEvents();
|
reportEvents(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function renderEvent(event, stick) { // render a new event
|
function renderEvent(event, stick) {
|
||||||
normalizeEvent(event);
|
normalizeEvent(event);
|
||||||
if (!event.source) {
|
if (!event.source) {
|
||||||
if (stick) {
|
if (stick) {
|
||||||
(event.source = eventSources[0]).push(event);
|
dynamicEventSource.push(event);
|
||||||
|
event.source = dynamicEventSource;
|
||||||
}
|
}
|
||||||
events.push(event);
|
cache.push(event);
|
||||||
}
|
}
|
||||||
rerenderEvents();
|
reportEvents(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function removeEvents(filter) {
|
function removeEvents(filter) {
|
||||||
if (!filter) { // remove all
|
if (!filter) { // remove all
|
||||||
events = [];
|
cache = [];
|
||||||
// clear all array sources
|
// clear all array sources
|
||||||
for (var i=0; i<eventSources.length; i++) {
|
for (var i=0; i<sources.length; i++) {
|
||||||
if (typeof eventSources[i] == 'object') {
|
if (typeof sources[i] == 'object') {
|
||||||
eventSources[i] = [];
|
sources[i] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
@ -221,29 +199,29 @@ function EventManager(options, eventSources) {
|
||||||
return e._id == id;
|
return e._id == id;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
events = $.grep(events, filter, true);
|
cache = $.grep(cache, filter, true);
|
||||||
// remove events from array sources
|
// remove events from array sources
|
||||||
for (var i=0; i<eventSources.length; i++) {
|
for (var i=0; i<sources.length; i++) {
|
||||||
if (typeof eventSources[i] == 'object') {
|
if (typeof sources[i] == 'object') {
|
||||||
eventSources[i] = $.grep(eventSources[i], filter, true);
|
sources[i] = $.grep(sources[i], filter, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rerenderEvents();
|
reportEvents(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function clientEvents(filter) {
|
function clientEvents(filter) {
|
||||||
if ($.isFunction(filter)) {
|
if ($.isFunction(filter)) {
|
||||||
return $.grep(events, filter);
|
return $.grep(cache, filter);
|
||||||
}
|
}
|
||||||
else if (filter) { // an event ID
|
else if (filter) { // an event ID
|
||||||
filter += '';
|
filter += '';
|
||||||
return $.grep(events, function(e) {
|
return $.grep(cache, function(e) {
|
||||||
return e._id == filter;
|
return e._id == filter;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return events; // else, return all
|
return cache; // else, return all
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ function AgendaEventRenderer() {
|
||||||
|
|
||||||
// exports
|
// exports
|
||||||
t.renderEvents = renderEvents;
|
t.renderEvents = renderEvents;
|
||||||
t.rerenderEvents = rerenderEvents;
|
|
||||||
t.clearEvents = clearEvents;
|
t.clearEvents = clearEvents;
|
||||||
t.slotSegHtml = slotSegHtml;
|
t.slotSegHtml = slotSegHtml;
|
||||||
t.bindDaySeg = bindDaySeg;
|
t.bindDaySeg = bindDaySeg;
|
||||||
|
@ -17,7 +16,7 @@ function AgendaEventRenderer() {
|
||||||
var trigger = t.trigger;
|
var trigger = t.trigger;
|
||||||
var eventEnd = t.eventEnd;
|
var eventEnd = t.eventEnd;
|
||||||
var reportEvents = t.reportEvents;
|
var reportEvents = t.reportEvents;
|
||||||
var clearEventData = t.clearEventData;
|
var reportEventClear = t.reportEventClear;
|
||||||
var eventElementHandlers = t.eventElementHandlers;
|
var eventElementHandlers = t.eventElementHandlers;
|
||||||
var setHeight = t.setHeight;
|
var setHeight = t.setHeight;
|
||||||
var getDaySegmentContainer = t.getDaySegmentContainer;
|
var getDaySegmentContainer = t.getDaySegmentContainer;
|
||||||
|
@ -50,12 +49,9 @@ function AgendaEventRenderer() {
|
||||||
/* Rendering
|
/* Rendering
|
||||||
----------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
var cachedEvents = [];
|
|
||||||
|
|
||||||
|
|
||||||
function renderEvents(events, modifiedEventId) {
|
function renderEvents(events, modifiedEventId) {
|
||||||
reportEvents(cachedEvents = events);
|
reportEvents(events);
|
||||||
var i, len=events.length,
|
var i, len=events.length,
|
||||||
dayEvents=[],
|
dayEvents=[],
|
||||||
slotEvents=[];
|
slotEvents=[];
|
||||||
|
@ -74,14 +70,8 @@ function AgendaEventRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function rerenderEvents(modifiedEventId) {
|
|
||||||
clearEvents();
|
|
||||||
renderEvents(cachedEvents, modifiedEventId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function clearEvents() {
|
function clearEvents() {
|
||||||
clearEventData();
|
reportEventClear();
|
||||||
getDaySegmentContainer().empty();
|
getDaySegmentContainer().empty();
|
||||||
getSlotSegmentContainer().empty();
|
getSlotSegmentContainer().empty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ function BasicEventRenderer() {
|
||||||
|
|
||||||
// exports
|
// exports
|
||||||
t.renderEvents = renderEvents;
|
t.renderEvents = renderEvents;
|
||||||
t.rerenderEvents = rerenderEvents;
|
|
||||||
t.clearEvents = clearEvents;
|
t.clearEvents = clearEvents;
|
||||||
t.bindDaySeg = bindDaySeg;
|
t.bindDaySeg = bindDaySeg;
|
||||||
|
|
||||||
|
@ -15,7 +14,7 @@ function BasicEventRenderer() {
|
||||||
var opt = t.opt;
|
var opt = t.opt;
|
||||||
var trigger = t.trigger;
|
var trigger = t.trigger;
|
||||||
var reportEvents = t.reportEvents;
|
var reportEvents = t.reportEvents;
|
||||||
var clearEventData = t.clearEventData;
|
var reportEventClear = t.reportEventClear;
|
||||||
var eventElementHandlers = t.eventElementHandlers;
|
var eventElementHandlers = t.eventElementHandlers;
|
||||||
var showEvents = t.showEvents;
|
var showEvents = t.showEvents;
|
||||||
var hideEvents = t.hideEvents;
|
var hideEvents = t.hideEvents;
|
||||||
|
@ -30,29 +29,19 @@ function BasicEventRenderer() {
|
||||||
var resizableDayEvent = t.resizableDayEvent;
|
var resizableDayEvent = t.resizableDayEvent;
|
||||||
|
|
||||||
|
|
||||||
// locals
|
|
||||||
var cachedEvents=[];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Rendering
|
/* Rendering
|
||||||
--------------------------------------------------------------------*/
|
--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
function renderEvents(events) {
|
function renderEvents(events, modifiedEventId) {
|
||||||
reportEvents(cachedEvents = events);
|
reportEvents(events);
|
||||||
renderDaySegs(compileSegs(events));
|
renderDaySegs(compileSegs(events), modifiedEventId);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function rerenderEvents(modifiedEventId) {
|
|
||||||
clearEvents();
|
|
||||||
renderDaySegs(compileSegs(cachedEvents), modifiedEventId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function clearEvents() {
|
function clearEvents() {
|
||||||
clearEventData();
|
reportEventClear();
|
||||||
getDaySegmentContainer().empty();
|
getDaySegmentContainer().empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ function View(element, calendar, viewName) {
|
||||||
t.opt = opt;
|
t.opt = opt;
|
||||||
t.trigger = trigger;
|
t.trigger = trigger;
|
||||||
t.reportEvents = reportEvents;
|
t.reportEvents = reportEvents;
|
||||||
t.clearEventData = clearEventData;
|
|
||||||
t.eventEnd = eventEnd;
|
t.eventEnd = eventEnd;
|
||||||
t.reportEventElement = reportEventElement;
|
t.reportEventElement = reportEventElement;
|
||||||
|
t.reportEventClear = reportEventClear;
|
||||||
t.eventElementHandlers = eventElementHandlers;
|
t.eventElementHandlers = eventElementHandlers;
|
||||||
t.showEvents = showEvents;
|
t.showEvents = showEvents;
|
||||||
t.hideEvents = hideEvents;
|
t.hideEvents = hideEvents;
|
||||||
|
@ -22,13 +22,12 @@ function View(element, calendar, viewName) {
|
||||||
// t.title
|
// t.title
|
||||||
// t.start, t.end
|
// t.start, t.end
|
||||||
// t.visStart, t.visEnd
|
// t.visStart, t.visEnd
|
||||||
// t.eventsChanged // todo: maybe report to calendar instead
|
|
||||||
|
|
||||||
|
|
||||||
// imports
|
// imports
|
||||||
var defaultEventEnd = t.defaultEventEnd;
|
var defaultEventEnd = t.defaultEventEnd;
|
||||||
var normalizeEvent = calendar.normalizeEvent; // in EventManager
|
var normalizeEvent = calendar.normalizeEvent; // in EventManager
|
||||||
var rerenderEvents = calendar.rerenderEvents;
|
var reportEventChange = calendar.reportEventChange;
|
||||||
|
|
||||||
|
|
||||||
// locals
|
// locals
|
||||||
|
@ -76,12 +75,6 @@ function View(element, calendar, viewName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function clearEventData() { // todo: rename to clearReportedEvents or something
|
|
||||||
eventElements = [];
|
|
||||||
eventElementsByID = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// returns a Date object for an event's end
|
// returns a Date object for an event's end
|
||||||
function eventEnd(event) {
|
function eventEnd(event) {
|
||||||
return event.end ? cloneDate(event.end) : defaultEventEnd(event);
|
return event.end ? cloneDate(event.end) : defaultEventEnd(event);
|
||||||
|
@ -104,6 +97,12 @@ function View(element, calendar, viewName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function reportEventClear() {
|
||||||
|
eventElements = [];
|
||||||
|
eventElementsByID = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// attaches eventClick, eventMouseover, eventMouseout
|
// attaches eventClick, eventMouseover, eventMouseout
|
||||||
function eventElementHandlers(event, eventElement) {
|
function eventElementHandlers(event, eventElement) {
|
||||||
eventElement
|
eventElement
|
||||||
|
@ -156,26 +155,43 @@ function View(element, calendar, viewName) {
|
||||||
var oldAllDay = event.allDay;
|
var oldAllDay = event.allDay;
|
||||||
var eventId = event._id;
|
var eventId = event._id;
|
||||||
moveEvents(eventsByID[eventId], dayDelta, minuteDelta, allDay);
|
moveEvents(eventsByID[eventId], dayDelta, minuteDelta, allDay);
|
||||||
trigger('eventDrop', e, event, dayDelta, minuteDelta, allDay, function() {
|
trigger(
|
||||||
// TODO: investigate cases where this inverse technique might not work
|
'eventDrop',
|
||||||
moveEvents(eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
|
e,
|
||||||
rerenderEvents();
|
event,
|
||||||
}, ev, ui);
|
dayDelta,
|
||||||
t.eventsChanged = true;
|
minuteDelta,
|
||||||
rerenderEvents(eventId);
|
allDay,
|
||||||
|
function() {
|
||||||
|
// TODO: investigate cases where this inverse technique might not work
|
||||||
|
moveEvents(eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
|
||||||
|
reportEventChange(eventId);
|
||||||
|
},
|
||||||
|
ev,
|
||||||
|
ui
|
||||||
|
);
|
||||||
|
reportEventChange(eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
|
function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
|
||||||
var eventId = event._id;
|
var eventId = event._id;
|
||||||
elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
|
elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
|
||||||
trigger('eventResize', e, event, dayDelta, minuteDelta, function() {
|
trigger(
|
||||||
// TODO: investigate cases where this inverse technique might not work
|
'eventResize',
|
||||||
elongateEvents(eventsByID[eventId], -dayDelta, -minuteDelta);
|
e,
|
||||||
rerenderEvents();
|
event,
|
||||||
}, ev, ui);
|
dayDelta,
|
||||||
t.eventsChanged = true;
|
minuteDelta,
|
||||||
rerenderEvents(eventId);
|
function() {
|
||||||
|
// TODO: investigate cases where this inverse technique might not work
|
||||||
|
elongateEvents(eventsByID[eventId], -dayDelta, -minuteDelta);
|
||||||
|
reportEventChange(eventId);
|
||||||
|
},
|
||||||
|
ev,
|
||||||
|
ui
|
||||||
|
);
|
||||||
|
reportEventChange(eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
59
tests/issue_679.html
Normal file
59
tests/issue_679.html
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type='text/javascript' src='../src/_loader.js?debug'></script>
|
||||||
|
<script type='text/javascript' src='../src/gcal/_loader.js'></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var date = new Date();
|
||||||
|
var d = date.getDate();
|
||||||
|
var m = date.getMonth();
|
||||||
|
var y = date.getFullYear();
|
||||||
|
|
||||||
|
$('#calendar').fullCalendar({
|
||||||
|
header: {
|
||||||
|
left: 'prev,next today',
|
||||||
|
center: 'title',
|
||||||
|
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
||||||
|
},
|
||||||
|
editable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function doit() {
|
||||||
|
var calendar = $('#calendar');
|
||||||
|
var holidays = $.fullCalendar.gcalFeed('http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic');
|
||||||
|
var moon = $.fullCalendar.gcalFeed('http://www.google.com/calendar/feeds/ht3jlfaac5lfd6263ulfh4tql8%40group.calendar.google.com/public/basic');
|
||||||
|
var australia = $.fullCalendar.gcalFeed('http://www.google.com/calendar/feeds/en.australian%23holiday%40group.v.calendar.google.com/public/basic');
|
||||||
|
calendar.fullCalendar('addEventSource', holidays);
|
||||||
|
calendar.fullCalendar('addEventSource', moon);
|
||||||
|
calendar.fullCalendar('addEventSource', australia);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style type='text/css'>
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin-top: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calendar {
|
||||||
|
width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<button onclick='doit()'>do it</button>
|
||||||
|
<div id='calendar'></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue