fixed issue 679, a bit of event fetching rejiggering

This commit is contained in:
Adam Shaw 2010-10-24 13:32:08 -07:00
parent 8086b3d252
commit c1a19a24c8
6 changed files with 289 additions and 242 deletions

View file

@ -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();
} }
} }

View file

@ -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
} }

View file

@ -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();
} }

View file

@ -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();
} }

View file

@ -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
View 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>