Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Sean Kenny
2013-08-12 19:15:54 +01:00
37 changed files with 895 additions and 426 deletions
+19
View File
@@ -1,4 +1,23 @@
version 1.6.3 (8/10/13)
- viewRender callback (PR 15)
- viewDestroy callback (PR 15)
- eventDestroy callback (PR 111)
- handleWindowResize option (PR 54)
- eventStartEditable/startEditable options (PR 49)
- eventDurationEditable/durationEditable options (PR 49)
- specify function for $.ajax `data` parameter for JSON event sources (PR 59)
- fixed bug with agenda event dropping in wrong column (PR 55)
- easier event element z-index customization (PR 58)
- classNames on past/future days (PR 88)
- allow null/undefined event titles (PR 84)
- small optimize for agenda event rendering (PR 56)
- deprecated:
- viewDisplay
- disableDragging
- disableResizing
- bundled with latest jQuery (1.10.2) and jQuery UI (1.10.3)
version 1.6.2 (7/18/13)
- hiddenDays option (issue 686)
- bugfix: when eventRender returns false, incorrect stacking of events (issue 762)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 346 B

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 B

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 309 B

+40 -66
View File
@@ -1,6 +1,6 @@
/*! jQuery UI - v1.10.2 - 2013-03-16
/*! jQuery UI - v1.10.3 - 2013-08-10
* http://jqueryui.com
* Includes: jquery.ui.core.css, jquery.ui.resizable.css
* Includes: jquery.ui.core.css, jquery.ui.tabs.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=deedf7&bgTextureHeader=highlight_soft&bgImgOpacityHeader=100&borderColorHeader=aed0ea&fcHeader=222222&iconColorHeader=72a7cf&bgColorContent=f2f5f7&bgTextureContent=highlight_hard&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=362b36&iconColorContent=72a7cf&bgColorDefault=d7ebf9&bgTextureDefault=glass&bgImgOpacityDefault=80&borderColorDefault=aed0ea&fcDefault=2779aa&iconColorDefault=3d80b3&bgColorHover=e4f1fb&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=74b2e2&fcHover=0070a3&iconColorHover=2694e8&bgColorActive=3baae3&bgTextureActive=glass&bgImgOpacityActive=50&borderColorActive=2694e8&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=ffef8f&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=25&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=cd0a0a&bgTextureError=flat&bgImgOpacityError=15&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=eeeeee&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=90&opacityOverlay=80&bgColorShadow=000000&bgTextureShadow=highlight_hard&bgImgOpacityShadow=70&opacityShadow=30&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
@@ -86,73 +86,47 @@
width: 100%;
height: 100%;
}
.ui-resizable {
.ui-tabs {
position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
padding: .2em;
}
.ui-tabs .ui-tabs-nav {
margin: 0;
padding: .2em .2em 0;
}
.ui-tabs .ui-tabs-nav li {
list-style: none;
float: left;
position: relative;
top: 0;
margin: 1px .2em 0 0;
border-bottom-width: 0;
padding: 0;
white-space: nowrap;
}
.ui-resizable-handle {
position: absolute;
font-size: 0.1px;
.ui-tabs .ui-tabs-nav li a {
float: left;
padding: .5em 1em;
text-decoration: none;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active {
margin-bottom: -1px;
padding-bottom: 1px;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active a,
.ui-tabs .ui-tabs-nav li.ui-state-disabled a,
.ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
cursor: text;
}
.ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
cursor: pointer;
}
.ui-tabs .ui-tabs-panel {
display: block;
}
.ui-resizable-disabled .ui-resizable-handle,
.ui-resizable-autohide .ui-resizable-handle {
display: none;
}
.ui-resizable-n {
cursor: n-resize;
height: 7px;
width: 100%;
top: -5px;
left: 0;
}
.ui-resizable-s {
cursor: s-resize;
height: 7px;
width: 100%;
bottom: -5px;
left: 0;
}
.ui-resizable-e {
cursor: e-resize;
width: 7px;
right: -5px;
top: 0;
height: 100%;
}
.ui-resizable-w {
cursor: w-resize;
width: 7px;
left: -5px;
top: 0;
height: 100%;
}
.ui-resizable-se {
cursor: se-resize;
width: 12px;
height: 12px;
right: 1px;
bottom: 1px;
}
.ui-resizable-sw {
cursor: sw-resize;
width: 9px;
height: 9px;
left: -5px;
bottom: -5px;
}
.ui-resizable-nw {
cursor: nw-resize;
width: 9px;
height: 9px;
left: -5px;
top: -5px;
}
.ui-resizable-ne {
cursor: ne-resize;
width: 9px;
height: 9px;
right: -5px;
top: -5px;
border-width: 0;
padding: 1em 1.4em;
background: none;
}
/* Component containers
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "fullcalendar",
"version": "1.6.2",
"version": "1.6.3",
"dependencies": {
"jquery": "~1.9.1"
"jquery": "~1.10.2"
},
"optionalDependencies": {
"jquery-ui": "~1.10.2"
"jquery-ui": "~1.10.3"
},
"title": "FullCalendar",
+6
View File
File diff suppressed because one or more lines are too long
-5
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -18,12 +18,12 @@
"modules": {
"jquery": {
"scripts": [
"lib/jquery-1.9.1.min.js"
"lib/jquery-1.10.2.min.js"
]
},
"jquery-ui": {
"scripts": [
"lib/jquery-ui-1.10.2.custom.min.js"
"lib/jquery-ui-1.10.3.custom.min.js"
]
},
"fullcalendar": {
+188 -152
View File
@@ -44,10 +44,8 @@ function Calendar(element, options, eventSources) {
var content;
var tm; // for making theme classes
var currentView;
var viewInstances = {};
var elementOuterWidth;
var suggestedViewHeight;
var absoluteViewElement;
var resizeUID = 0;
var ignoreWindowResize = 0;
var date = new Date();
@@ -66,11 +64,11 @@ function Calendar(element, options, eventSources) {
function render(inc) {
if (!content) {
initialRender();
}else{
}
else if (elementVisible()) {
// mainly for the public API
calcSize();
markSizesDirty();
markEventsDirty();
renderView(inc);
_renderView(inc);
}
}
@@ -87,15 +85,22 @@ function Calendar(element, options, eventSources) {
if (options.theme) {
element.addClass('ui-widget');
}
content = $("<div class='fc-content' style='position:relative'/>")
.prependTo(element);
header = new Header(t, options);
headerElement = header.render();
if (headerElement) {
element.prepend(headerElement);
}
changeView(options.defaultView);
$(window).resize(windowResize);
if (options.handleWindowResize) {
$(window).resize(windowResize);
}
// needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize
if (!bodyVisible()) {
lateRender();
@@ -115,21 +120,27 @@ function Calendar(element, options, eventSources) {
function destroy() {
if (currentView) {
trigger('viewDestroy', currentView, currentView, currentView.element);
currentView.triggerEventDestroy();
}
$(window).unbind('resize', windowResize);
header.destroy();
content.remove();
element.removeClass('fc fc-rtl ui-widget');
}
function elementVisible() {
return _element.offsetWidth !== 0;
return element.is(':visible');
}
function bodyVisible() {
return $('body')[0].offsetWidth !== 0;
return $('body').is(':visible');
}
@@ -137,133 +148,97 @@ function Calendar(element, options, eventSources) {
/* View Rendering
-----------------------------------------------------------------------------*/
// TODO: improve view switching (still weird transition in IE, and FF has whiteout problem)
function changeView(newViewName) {
if (!currentView || newViewName != currentView.name) {
ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached
unselect();
var oldView = currentView;
var newViewElement;
if (oldView) {
(oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera)
setMinHeight(content, content.height());
oldView.element.hide();
}else{
setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated
}
content.css('overflow', 'hidden');
currentView = viewInstances[newViewName];
if (currentView) {
currentView.element.show();
}else{
currentView = viewInstances[newViewName] = new fcViews[newViewName](
newViewElement = absoluteViewElement =
$("<div class='fc-view fc-view-" + newViewName + "' style='position:absolute'/>")
.appendTo(content),
t // the calendar object
);
}
if (oldView) {
header.deactivateButton(oldView.name);
}
header.activateButton(newViewName);
renderView(); // after height has been set, will make absoluteViewElement's position=relative, then set to null
content.css('overflow', '');
if (oldView) {
setMinHeight(content, 1);
}
if (!newViewElement) {
(currentView.afterShow || noop)(); // called after setting min-height/overflow, so in final scroll state (for Opera)
}
ignoreWindowResize--;
_changeView(newViewName);
}
}
function _changeView(newViewName) {
ignoreWindowResize++;
if (currentView) {
trigger('viewDestroy', currentView, currentView, currentView.element);
unselect();
currentView.triggerEventDestroy(); // trigger 'eventDestroy' for each event
freezeContentHeight();
currentView.element.remove();
header.deactivateButton(currentView.name);
}
header.activateButton(newViewName);
currentView = new fcViews[newViewName](
$("<div class='fc-view fc-view-" + newViewName + "' style='position:relative'/>")
.appendTo(content),
t // the calendar object
);
renderView();
unfreezeContentHeight();
ignoreWindowResize--;
}
function renderView(inc) {
if (elementVisible()) {
ignoreWindowResize++; // because renderEvents might temporarily change the height before setSize is reached
unselect();
if (suggestedViewHeight === undefined) {
calcSize();
if (
!currentView.start || // never rendered before
inc || date < currentView.start || date >= currentView.end // or new date range
) {
if (elementVisible()) {
_renderView(inc);
}
var forceEventRender = false;
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
setSize(true);
forceEventRender = true;
}
else if (currentView.sizeDirty) {
// view must resize (and rerender events)
currentView.clearEvents();
setSize();
forceEventRender = true;
}
else if (currentView.eventsDirty) {
currentView.clearEvents();
forceEventRender = true;
}
currentView.sizeDirty = false;
currentView.eventsDirty = false;
updateEvents(forceEventRender);
elementOuterWidth = element.outerWidth();
header.updateTitle(currentView.title);
var today = new Date();
if (today >= currentView.start && today < currentView.end) {
header.disableButton('today');
}else{
header.enableButton('today');
}
ignoreWindowResize--;
currentView.trigger('viewDisplay', _element);
}
}
function _renderView(inc) { // assumes elementVisible
ignoreWindowResize++;
if (currentView.start) { // already been rendered?
trigger('viewDestroy', currentView, currentView, currentView.element);
unselect();
clearEvents();
}
freezeContentHeight();
currentView.render(date, inc || 0); // the view's render method ONLY renders the skeleton, nothing else
setSize();
unfreezeContentHeight();
(currentView.afterRender || noop)();
updateTitle();
updateTodayButton();
trigger('viewRender', currentView, currentView, currentView.element);
currentView.trigger('viewDisplay', _element); // deprecated
ignoreWindowResize--;
getAndRenderEvents();
}
/* Resizing
-----------------------------------------------------------------------------*/
function updateSize() {
markSizesDirty();
if (elementVisible()) {
unselect();
clearEvents();
calcSize();
setSize();
unselect();
currentView.clearEvents();
currentView.renderEvents(events);
currentView.sizeDirty = false;
renderEvents();
}
}
function markSizesDirty() {
$.each(viewInstances, function(i, inst) {
inst.sizeDirty = true;
});
}
function calcSize() {
function calcSize() { // assumes elementVisible
if (options.contentHeight) {
suggestedViewHeight = options.contentHeight;
}
@@ -276,15 +251,20 @@ function Calendar(element, options, eventSources) {
}
function setSize(dateChanged) { // todo: dateChanged?
ignoreWindowResize++;
currentView.setHeight(suggestedViewHeight, dateChanged);
if (absoluteViewElement) {
absoluteViewElement.css('position', 'relative');
absoluteViewElement = null;
function setSize() { // assumes elementVisible
if (suggestedViewHeight === undefined) {
calcSize(); // for first time
// NOTE: we don't want to recalculate on every renderView because
// it could result in oscillating heights due to scrollbars.
}
currentView.setWidth(content.width(), dateChanged);
ignoreWindowResize++;
currentView.setHeight(suggestedViewHeight);
currentView.setWidth(content.width());
ignoreWindowResize--;
elementOuterWidth = element.outerWidth();
}
@@ -313,52 +293,85 @@ function Calendar(element, options, eventSources) {
/* Event Fetching/Rendering
-----------------------------------------------------------------------------*/
// TODO: going forward, most of this stuff should be directly handled by the view
function refetchEvents() { // can be called as an API method
clearEvents();
fetchAndRenderEvents();
}
function rerenderEvents(modifiedEventID) { // can be called as an API method
clearEvents();
renderEvents(modifiedEventID);
}
function renderEvents(modifiedEventID) { // TODO: remove modifiedEventID hack
if (elementVisible()) {
currentView.setEventData(events); // for View.js, TODO: unify with renderEvents
currentView.renderEvents(events, modifiedEventID); // actually render the DOM elements
currentView.trigger('eventAfterAllRender');
}
}
function clearEvents() {
currentView.triggerEventDestroy(); // trigger 'eventDestroy' for each event
currentView.clearEvents(); // actually remove the DOM elements
currentView.clearEventData(); // for View.js, TODO: unify with clearEvents
}
// fetches events if necessary, rerenders events if necessary (or if forced)
function updateEvents(forceRender) {
function getAndRenderEvents() {
if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) {
refetchEvents();
fetchAndRenderEvents();
}
else if (forceRender) {
rerenderEvents();
else {
renderEvents();
}
}
function refetchEvents() {
fetchEvents(currentView.visStart, currentView.visEnd); // will call reportEvents
function fetchAndRenderEvents() {
fetchEvents(currentView.visStart, currentView.visEnd);
// ... will call reportEvents
// ... which will call renderEvents
}
// called when event data arrives
function reportEvents(_events) {
events = _events;
rerenderEvents();
renderEvents();
}
// called when a single event's data has been changed
function reportEventChange(eventID) {
rerenderEvents(eventID);
}
// attempts to rerenderEvents
function rerenderEvents(modifiedEventID) {
markEventsDirty();
if (elementVisible()) {
currentView.clearEvents();
currentView.renderEvents(events, modifiedEventID);
currentView.eventsDirty = false;
}
/* Header Updating
-----------------------------------------------------------------------------*/
function updateTitle() {
header.updateTitle(currentView.title);
}
function markEventsDirty() {
$.each(viewInstances, function(i, inst) {
inst.eventsDirty = true;
});
function updateTodayButton() {
var today = new Date();
if (today >= currentView.start && today < currentView.end) {
header.disableButton('today');
}
else {
header.enableButton('today');
}
}
@@ -439,6 +452,29 @@ function Calendar(element, options, eventSources) {
function getDate() {
return cloneDate(date);
}
/* Height "Freezing"
-----------------------------------------------------------------------------*/
function freezeContentHeight() {
content.css({
width: '100%',
height: content.height(),
overflow: 'hidden'
});
}
function unfreezeContentHeight() {
content.css({
width: '',
height: '',
overflow: ''
});
}
+17 -1
View File
@@ -136,7 +136,22 @@ function EventManager(options, _sources) {
var success = source.success;
var error = source.error;
var complete = source.complete;
var data = $.extend({}, source.data || {});
// retrieve any outbound GET/POST $.ajax data from the options
var customData;
if ($.isFunction(source.data)) {
// supplied as a function that returns a key/value object
customData = source.data();
}
else {
// supplied as a straight key/value object
customData = source.data;
}
// use a copy of the custom data so we can modify the parameters
// and not affect the passed-in object.
var data = $.extend({}, customData || {});
var startParam = firstDefined(source.startParam, options.startParam);
var endParam = firstDefined(source.endParam, options.endParam);
if (startParam) {
@@ -145,6 +160,7 @@ function EventManager(options, _sources) {
if (endParam) {
data[endParam] = Math.round(+rangeEnd / 1000);
}
pushLoading();
$.ajax($.extend({}, ajaxDefaults, source, {
data: data,
+123 -65
View File
@@ -16,8 +16,6 @@ function AgendaEventRenderer() {
var isEventDraggable = t.isEventDraggable;
var isEventResizable = t.isEventResizable;
var eventEnd = t.eventEnd;
var reportEvents = t.reportEvents;
var reportEventClear = t.reportEventClear;
var eventElementHandlers = t.eventElementHandlers;
var setHeight = t.setHeight;
var getDaySegmentContainer = t.getDaySegmentContainer;
@@ -26,6 +24,7 @@ function AgendaEventRenderer() {
var getMaxMinute = t.getMaxMinute;
var getMinMinute = t.getMinMinute;
var timePosition = t.timePosition;
var getIsCellAllDay = t.getIsCellAllDay;
var colContentLeft = t.colContentLeft;
var colContentRight = t.colContentRight;
var cellToDate = t.cellToDate;
@@ -58,7 +57,6 @@ function AgendaEventRenderer() {
function renderEvents(events, modifiedEventId) {
reportEvents(events);
var i, len=events.length,
dayEvents=[],
slotEvents=[];
@@ -76,13 +74,10 @@ function AgendaEventRenderer() {
}
renderSlotSegs(compileSlotSegs(slotEvents), modifiedEventId);
trigger('eventAfterAllRender');
}
function clearEvents() {
reportEventClear();
getDaySegmentContainer().empty();
getSlotSegmentContainer().empty();
}
@@ -332,14 +327,20 @@ function AgendaEventRenderer() {
}
html +=
" class='" + classes.join(' ') + "'" +
" style='position:absolute;z-index:8;top:" + seg.top + "px;left:" + seg.left + "px;" + skinCss + "'" +
" style=" +
"'" +
"position:absolute;" +
"top:" + seg.top + "px;" +
"left:" + seg.left + "px;" +
skinCss +
"'" +
">" +
"<div class='fc-event-inner'>" +
"<div class='fc-event-time'>" +
htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +
"</div>" +
"<div class='fc-event-title'>" +
htmlEscape(event.title) +
htmlEscape(event.title || '') +
"</div>" +
"</div>" +
"<div class='fc-event-bg'></div>";
@@ -386,7 +387,6 @@ function AgendaEventRenderer() {
var snapMinutes = getSnapMinutes();
var minMinute = getMinMinute();
eventElement.draggable({
zIndex: 9,
opacity: opt('dragOpacity', 'month'), // use whatever the month view was using
revertDuration: opt('dragRevertDuration'),
start: function(ev, ui) {
@@ -472,80 +472,147 @@ function AgendaEventRenderer() {
// when event starts out IN TIMESLOTS
function draggableSlotEvent(event, eventElement, timeElement) {
var origPosition;
var allDay = false;
var dayDelta;
var minuteDelta;
var prevMinuteDelta;
var hoverListener = getHoverListener();
var coordinateGrid = t.getCoordinateGrid();
var colCnt = getColCnt();
var colWidth = getColWidth();
var snapHeight = getSnapHeight();
var snapMinutes = getSnapMinutes();
// states
var origPosition; // original position of the element, not the mouse
var origCell;
var isInBounds, prevIsInBounds;
var isAllDay, prevIsAllDay;
var colDelta, prevColDelta;
var dayDelta; // derived from colDelta
var minuteDelta, prevMinuteDelta;
eventElement.draggable({
zIndex: 9,
scroll: false,
grid: [colWidth, snapHeight],
grid: [ colWidth, snapHeight ],
axis: colCnt==1 ? 'y' : false,
opacity: opt('dragOpacity'),
revertDuration: opt('dragRevertDuration'),
start: function(ev, ui) {
trigger('eventDragStart', eventElement, event, ev, ui);
hideEvents(event, eventElement);
coordinateGrid.build();
// initialize states
origPosition = eventElement.position();
origCell = coordinateGrid.cell(ev.pageX, ev.pageY);
isInBounds = prevIsInBounds = true;
isAllDay = prevIsAllDay = getIsCellAllDay(origCell);
colDelta = prevColDelta = 0;
dayDelta = 0;
minuteDelta = prevMinuteDelta = 0;
hoverListener.start(function(cell, origCell) {
eventElement.draggable('option', 'revert', !cell);
clearOverlays();
if (cell) {
var origDate = cellToDate(0, origCell.col);
var date = cellToDate(0, cell.col);
dayDelta = dayDiff(date, origDate);
if (opt('allDaySlot') && !cell.row) {
// over full days
if (!allDay) {
// convert to temporary all-day event
allDay = true;
timeElement.hide();
eventElement.draggable('option', 'grid', null);
}
renderDayOverlay(
addDays(cloneDate(event.start), dayDelta),
addDays(exclEndDay(event), dayDelta)
);
}else{
// on slots
resetElement();
}
}
}, ev, 'drag');
},
drag: function(ev, ui) {
minuteDelta = Math.round((ui.position.top - origPosition.top) / snapHeight) * snapMinutes;
if (minuteDelta != prevMinuteDelta) {
if (!allDay) {
updateTimeText(minuteDelta);
// NOTE: this `cell` value is only useful for determining in-bounds and all-day.
// Bad for anything else due to the discrepancy between the mouse position and the
// element position while snapping. (problem revealed in PR #55)
//
// PS- the problem exists for draggableDayEvent() when dragging an all-day event to a slot event.
// We should overhaul the dragging system and stop relying on jQuery UI.
var cell = coordinateGrid.cell(ev.pageX, ev.pageY);
// update states
isInBounds = !!cell;
if (isInBounds) {
isAllDay = getIsCellAllDay(cell);
// calculate column delta
colDelta = Math.round((ui.position.left - origPosition.left) / colWidth);
if (colDelta != prevColDelta) {
// calculate the day delta based off of the original clicked column and the column delta
var origDate = cellToDate(0, origCell.col);
var col = origCell.col + colDelta;
col = Math.max(0, col);
col = Math.min(colCnt-1, col);
var date = cellToDate(0, col);
dayDelta = dayDiff(date, origDate);
}
// calculate minute delta (only if over slots)
if (!isAllDay) {
minuteDelta = Math.round((ui.position.top - origPosition.top) / snapHeight) * snapMinutes;
}
}
// any state changes?
if (
isInBounds != prevIsInBounds ||
isAllDay != prevIsAllDay ||
colDelta != prevColDelta ||
minuteDelta != prevMinuteDelta
) {
updateUI();
// update previous states for next time
prevIsInBounds = isInBounds;
prevIsAllDay = isAllDay;
prevColDelta = colDelta;
prevMinuteDelta = minuteDelta;
}
// if out-of-bounds, revert when done, and vice versa.
eventElement.draggable('option', 'revert', !isInBounds);
},
stop: function(ev, ui) {
var cell = hoverListener.stop();
clearOverlays();
trigger('eventDragStop', eventElement, event, ev, ui);
if (cell && (dayDelta || minuteDelta || allDay)) {
// changed!
eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui);
}else{
// either no change or out-of-bounds (draggable has already reverted)
resetElement();
if (isInBounds && (isAllDay || dayDelta || minuteDelta)) { // changed!
eventDrop(this, event, dayDelta, isAllDay ? 0 : minuteDelta, isAllDay, ev, ui);
}
else { // either no change or out-of-bounds (draggable has already reverted)
// reset states for next time, and for updateUI()
isInBounds = true;
isAllDay = false;
colDelta = 0;
dayDelta = 0;
minuteDelta = 0;
updateUI();
eventElement.css('filter', ''); // clear IE opacity side-effects
eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position
updateTimeText(0);
// sometimes fast drags make event revert to wrong position, so reset.
// also, if we dragged the element out of the area because of snapping,
// but the *mouse* is still in bounds, we need to reset the position.
eventElement.css(origPosition);
showEvents(event, eventElement);
}
}
});
function updateUI() {
clearOverlays();
if (isInBounds) {
if (isAllDay) {
timeElement.hide();
eventElement.draggable('option', 'grid', null); // disable grid snapping
renderDayOverlay(
addDays(cloneDate(event.start), dayDelta),
addDays(exclEndDay(event), dayDelta)
);
}
else {
updateTimeText(minuteDelta);
timeElement.css('display', ''); // show() was causing display=inline
eventElement.draggable('option', 'grid', [colWidth, snapHeight]); // re-enable grid snapping
}
}
}
function updateTimeText(minuteDelta) {
var newStart = addMinutes(cloneDate(event.start), minuteDelta);
var newEnd;
@@ -554,14 +621,7 @@ function AgendaEventRenderer() {
}
timeElement.text(formatDates(newStart, newEnd, opt('timeFormat')));
}
function resetElement() {
// convert back to original slot-event
if (allDay) {
timeElement.css('display', ''); // show() was causing display=inline
eventElement.draggable('option', 'grid', [colWidth, snapHeight]);
allDay = false;
}
}
}
@@ -582,7 +642,6 @@ function AgendaEventRenderer() {
start: function(ev, ui) {
snapDelta = prevSnapDelta = 0;
hideEvents(event, eventElement);
eventElement.css('z-index', 9);
trigger('eventResizeStart', this, event, ev, ui);
},
resize: function(ev, ui) {
@@ -605,7 +664,6 @@ function AgendaEventRenderer() {
if (snapDelta) {
eventResize(this, event, 0, snapMinutes*snapDelta, ev, ui);
}else{
eventElement.css('z-index', 8);
showEvents(event, eventElement);
// BUG: if event was really short, need to put title back in span
}
+24 -25
View File
@@ -29,12 +29,12 @@ function AgendaView(element, calendar, viewName) {
t.renderAgenda = renderAgenda;
t.setWidth = setWidth;
t.setHeight = setHeight;
t.beforeHide = beforeHide;
t.afterShow = afterShow;
t.afterRender = afterRender;
t.defaultEventEnd = defaultEventEnd;
t.timePosition = timePosition;
t.getIsCellAllDay = getIsCellAllDay;
t.allDayRow = getAllDayRow;
t.getCoordinateGrid = function() { return coordinateGrid }; // specifically for AgendaEventRenderer
t.getHoverListener = function() { return hoverListener };
t.colLeft = colLeft;
t.colRight = colRight;
@@ -66,7 +66,6 @@ function AgendaView(element, calendar, viewName) {
AgendaEventRenderer.call(t);
var opt = t.opt;
var trigger = t.trigger;
var clearEvents = t.clearEvents;
var renderOverlay = t.renderOverlay;
var clearOverlays = t.clearOverlays;
var reportSelection = t.reportSelection;
@@ -119,7 +118,6 @@ function AgendaView(element, calendar, viewName) {
var colPositions;
var colContentPositions;
var slotTopCache = {};
var savedScrollTop;
var tm;
var rtl;
@@ -141,11 +139,12 @@ function AgendaView(element, calendar, viewName) {
function renderAgenda(c) {
colCnt = c;
updateOptions();
if (!dayTable) {
if (!dayTable) { // first time rendering?
buildSkeleton(); // builds day table, slot area, events containers
}else{
}
else {
buildDayTable(); // rebuilds day table
clearEvents();
}
}
@@ -196,7 +195,7 @@ function AgendaView(element, calendar, viewName) {
if (opt('allDaySlot')) {
daySegmentContainer =
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
$("<div class='fc-event-container' style='position:absolute;z-index:8;top:0;left:0'/>")
.appendTo(slotLayer);
s =
@@ -235,7 +234,7 @@ function AgendaView(element, calendar, viewName) {
.appendTo(slotScroller);
slotSegmentContainer =
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
$("<div class='fc-event-container' style='position:absolute;z-index:8;top:0;left:0'/>")
.appendTo(slotContainer);
s =
@@ -388,6 +387,12 @@ function AgendaView(element, calendar, viewName) {
'fc-today'
);
}
else if (date < today) {
classNames.push('fc-past');
}
else {
classNames.push('fc-future');
}
cellHTML =
"<td class='" + classNames.join(' ') + "'>" +
@@ -419,7 +424,7 @@ function AgendaView(element, calendar, viewName) {
-----------------------------------------------------------------------*/
function setHeight(height, dateChanged) {
function setHeight(height) {
if (height === undefined) {
height = viewHeight;
}
@@ -444,10 +449,6 @@ function AgendaView(element, calendar, viewName) {
snapRatio = opt('slotMinutes') / snapMinutes;
snapHeight = slotHeight / snapRatio;
if (dateChanged) {
resetScroll();
}
}
@@ -514,15 +515,10 @@ function AgendaView(element, calendar, viewName) {
scroll();
setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
}
function beforeHide() {
savedScrollTop = slotScroller.scrollTop();
}
function afterShow() {
slotScroller.scrollTop(savedScrollTop);
function afterRender() { // after the view has been freshly rendered and sized
resetScroll();
}
@@ -715,7 +711,11 @@ function AgendaView(element, calendar, viewName) {
slotI = Math.floor(minutes / slotMinutes),
slotTop = slotTopCache[slotI];
if (slotTop === undefined) {
slotTop = slotTopCache[slotI] = slotTable.find('tr:eq(' + slotI + ') td div')[0].offsetTop; //.position().top; // need this optimization???
slotTop = slotTopCache[slotI] =
slotTable.find('tr').eq(slotI).find('td div')[0].offsetTop;
// .eq() is faster than ":eq()" selector
// [0].offsetTop is faster than .position().top (do we really need this optimization?)
// a better optimization would be to cache all these divs
}
return Math.max(0, Math.round(
slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
@@ -779,7 +779,6 @@ function AgendaView(element, calendar, viewName) {
var helperRes = helperOption(startDate, endDate);
if (helperRes) {
rect.position = 'absolute';
rect.zIndex = 8;
selectionHelper = $(helperRes)
.css(rect)
.appendTo(slotContainer);
-3
View File
@@ -13,14 +13,11 @@ function BasicEventRenderer() {
function renderEvents(events, modifiedEventId) {
t.reportEvents(events);
t.renderDayEvents(events, modifiedEventId);
t.trigger('eventAfterAllRender');
}
function clearEvents() {
t.reportEventClear();
t.getDaySegmentContainer().empty();
}
+12 -24
View File
@@ -40,7 +40,6 @@ function BasicView(element, calendar, viewName) {
BasicEventRenderer.call(t);
var opt = t.opt;
var trigger = t.trigger;
var clearEvents = t.clearEvents;
var renderOverlay = t.renderOverlay;
var clearOverlays = t.clearOverlays;
var daySelectionMousedown = t.daySelectionMousedown;
@@ -95,12 +94,11 @@ function BasicView(element, calendar, viewName) {
colCnt = _colCnt;
showNumbers = _showNumbers;
updateOptions();
var firstTime = !body;
if (firstTime) {
if (!body) {
buildEventContainer();
}else{
clearEvents();
}
buildTable();
}
@@ -123,7 +121,7 @@ function BasicView(element, calendar, viewName) {
function buildEventContainer() {
daySegmentContainer =
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
$("<div class='fc-event-container' style='position:absolute;z-index:8;top:0;left:0'/>")
.appendTo(element);
}
@@ -131,7 +129,6 @@ function BasicView(element, calendar, viewName) {
function buildTable() {
var html = buildTableHTML();
lockHeight(); // the unlock happens later, in setHeight()...
if (table) {
table.remove();
}
@@ -266,6 +263,12 @@ function BasicView(element, calendar, viewName) {
tm + '-state-highlight'
);
}
else if (date < today) {
classNames.push('fc-past');
}
else {
classNames.push('fc-future');
}
html +=
"<td" +
@@ -312,14 +315,13 @@ function BasicView(element, calendar, viewName) {
bodyFirstCells.each(function(i, _cell) {
if (i < rowCnt) {
cell = $(_cell);
setMinHeight(
cell.find('> div'),
cell.find('> div').css(
'min-height',
(i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell)
);
}
});
unlockHeight();
}
@@ -514,19 +516,5 @@ function BasicView(element, calendar, viewName) {
function allDayRow(i) {
return bodyRows.eq(i);
}
// makes sure height doesn't collapse while we destroy/render new cells
// (this causes a bad end-user scrollbar jump)
// TODO: generalize this for all view rendering. (also in Calendar.js)
function lockHeight() {
setMinHeight(element, element.height());
}
function unlockHeight() {
setMinHeight(element, 1);
}
}
+3 -4
View File
@@ -307,7 +307,6 @@ function DayEventRenderer() {
" style=" +
"'" +
"position:absolute;" +
"z-index:8;" + // TODO: move this into a constant or put it in the stylesheet
"left:" + segment.left + "px;" +
skinCss +
"'" +
@@ -322,7 +321,9 @@ function DayEventRenderer() {
"</span>";
}
html +=
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
"<span class='fc-event-title'>" +
htmlEscape(event.title || '') +
"</span>" +
"</div>";
if (segment.isEnd && isEventResizable(event)) {
html +=
@@ -366,7 +367,6 @@ function DayEventRenderer() {
triggerRes = $(triggerRes)
.css({
position: 'absolute',
zIndex: 8, // TODO: move this into a constant or put it in the stylesheet
left: segment.left
});
@@ -610,7 +610,6 @@ function DayEventRenderer() {
var hoverListener = getHoverListener();
var dayDelta;
eventElement.draggable({
zIndex: 9,
delay: 50,
opacity: opt('dragOpacity'),
revertDuration: opt('dragRevertDuration'),
+44 -21
View File
@@ -12,10 +12,11 @@ function View(element, calendar, viewName) {
t.trigger = trigger;
t.isEventDraggable = isEventDraggable;
t.isEventResizable = isEventResizable;
t.reportEvents = reportEvents;
t.setEventData = setEventData;
t.clearEventData = clearEventData;
t.eventEnd = eventEnd;
t.reportEventElement = reportEventElement;
t.reportEventClear = reportEventClear;
t.triggerEventDestroy = triggerEventDestroy;
t.eventElementHandlers = eventElementHandlers;
t.showEvents = showEvents;
t.hideEvents = hideEvents;
@@ -33,9 +34,9 @@ function View(element, calendar, viewName) {
// locals
var eventsByID = {};
var eventElements = [];
var eventElementsByID = {};
var eventsByID = {}; // eventID mapped to array of events (there can be multiple b/c of repeating events)
var eventElementsByID = {}; // eventID mapped to array of jQuery elements
var eventElementCouples = []; // array of objects, { event, element } // TODO: unify with segment system
var options = calendar.options;
@@ -59,21 +60,34 @@ function View(element, calendar, viewName) {
/* Event Editable Boolean Calculations
------------------------------------------------------------------------------*/
function isEventDraggable(event) {
return isEventEditable(event) && !opt('disableDragging');
var source = event.source || {};
return firstDefined(
event.startEditable,
source.startEditable,
opt('eventStartEditable'),
event.editable,
source.editable,
opt('editable')
)
&& !opt('disableDragging'); // deprecated
}
function isEventResizable(event) { // but also need to make sure the seg.isEnd == true
return isEventEditable(event) && !opt('disableResizing');
}
function isEventEditable(event) {
return firstDefined(event.editable, (event.source || {}).editable, opt('editable'));
var source = event.source || {};
return firstDefined(
event.durationEditable,
source.durationEditable,
opt('eventDurationEditable'),
event.editable,
source.editable,
opt('editable')
)
&& !opt('disableResizing'); // deprecated
}
@@ -82,8 +96,7 @@ function View(element, calendar, viewName) {
------------------------------------------------------------------------------*/
// report when view receives new events
function reportEvents(events) { // events are already normalized at this point
function setEventData(events) { // events are already normalized at this point
eventsByID = {};
var i, len=events.length, event;
for (i=0; i<len; i++) {
@@ -95,6 +108,13 @@ function View(element, calendar, viewName) {
}
}
}
function clearEventData() {
eventsByID = {};
eventElementsByID = {};
eventElementCouples = [];
}
// returns a Date object for an event's end
@@ -110,18 +130,19 @@ function View(element, calendar, viewName) {
// report when view creates an element for an event
function reportEventElement(event, element) {
eventElements.push(element);
eventElementCouples.push({ event: event, element: element });
if (eventElementsByID[event._id]) {
eventElementsByID[event._id].push(element);
}else{
eventElementsByID[event._id] = [element];
}
}
function reportEventClear() {
eventElements = [];
eventElementsByID = {};
function triggerEventDestroy() {
$.each(eventElementCouples, function(i, couple) {
t.trigger('eventDestroy', couple.event, couple.event, couple.element);
});
}
@@ -158,6 +179,8 @@ function View(element, calendar, viewName) {
function eachEventElement(event, exceptElement, funcName) {
// NOTE: there may be multiple events per ID (repeating events)
// and multiple segments per event
var elements = eventElementsByID[event._id],
i, len = elements.length;
for (i=0; i<len; i++) {
+9
View File
@@ -138,6 +138,15 @@
/* Global Event Styles
------------------------------------------------------------------------*/
.fc-event-container > * {
z-index: 8;
}
.fc-event-container > .ui-draggable-dragging,
.fc-event-container > .ui-resizable-resizing {
z-index: 9;
}
.fc-event {
border: 1px solid #3a87ad; /* default BORDER color */
+3 -1
View File
@@ -70,7 +70,9 @@ var defaults = {
//selectable: false,
unselectAuto: true,
dropAccept: '*'
dropAccept: '*',
handleWindowResize: true
};
+2 -1
View File
@@ -102,10 +102,11 @@ html .fc,
.fc-content {
clear: both;
zoom: 1; /* for IE7, gives accurate coordinates for [un]freezeContentHeight */
}
.fc-view {
width: 100%; /* needed for view switching (when view is absolute) */
width: 100%;
overflow: hidden;
}
-9
View File
@@ -113,15 +113,6 @@ function vborders(element) {
}
function setMinHeight(element, height) {
height = (typeof height == 'number' ? height + 'px' : height);
element.each(function(i, _element) {
_element.style.cssText += ';min-height:' + height + ';_height:' + height;
// why can't we just use .css() ? i forget
});
}
/* Misc Utils
-----------------------------------------------------------------------------*/
+54
View File
@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<link href='../build/out/fullcalendar.css' rel='stylesheet' />
<link href='../build/out/fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='../build/out/jquery.js'></script>
<script src='../build/out/jquery-ui.js'></script>
<script src='../build/out/fullcalendar.js'></script>
<script>
$(document).ready(function() {
$('#calendar').fullCalendar({
year: 2010,
month: 0,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
},
editable: true,
events: {
url: "many_events_json.txt",
data: function() {
var custom_data = { q: 'custom data value' }; // should see this in Networking
console.log('setting custom_data as part of the eventSource fetch');
return custom_data;
}
}
});
});
</script>
<style>
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>
<div id='calendar'></div>
</body>
</html>
+4 -35
View File
File diff suppressed because one or more lines are too long
+2
View File
@@ -21,6 +21,8 @@
//weekMode: 'variable',
minTime: '5:30am',
maxTime: '5:30pm',
//handleWindowResize: false,
// TODO: there is a bug switching into agendaWeek from month with a 1280x1024 (with firebug showing)
+67
View File
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<link href='../build/out/fullcalendar.css' rel='stylesheet' />
<link href='../build/out/fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='../build/out/jquery.js'></script>
<script src='../build/out/jquery-ui.js'></script>
<script src='../build/out/fullcalendar.js'></script>
<script>
$(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,
events: [
{
title: null,
start: new Date(y, m, 1)
},
{
title: '',
start: new Date(y, m, d-5),
end: new Date(y, m, d-2)
},
{
start: new Date(y, m, d, 10, 30),
allDay: false
}
],
eventRender: function(event, el) {
el.find('.fc-event-title').text("something");
}
});
});
</script>
<style>
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>
<div id='calendar'></div>
</body>
</html>
+103
View File
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
<link href='../build/out/fullcalendar.css' rel='stylesheet' />
<link href='../build/out/fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='../build/out/jquery.js'></script>
<script src='../build/out/jquery-ui.js'></script>
<script src='../build/out/fullcalendar.js'></script>
<script>
$(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,
events: [
{
title: 'All Day Event',
start: new Date(y, m, 1)
},
{
title: 'Long Event',
start: new Date(y, m, d-5),
end: new Date(y, m, d-2)
},
{
id: 999,
title: 'Repeating Event',
start: new Date(y, m, d-3, 16, 0),
allDay: false
},
{
id: 999,
title: 'Repeating Event',
start: new Date(y, m, d+4, 16, 0),
allDay: false
},
{
title: 'Meeting',
start: new Date(y, m, d, 10, 30),
allDay: false
},
{
title: 'Lunch',
start: new Date(y, m, d, 12, 5),
end: new Date(y, m, d, 14, 43),
allDay: false
},
{
title: 'Birthday Party',
start: new Date(y, m, d+1, 19, 0),
end: new Date(y, m, d+1, 22, 30),
allDay: false
},
{
title: 'Click for Google',
start: new Date(y, m, 28),
end: new Date(y, m, 29),
url: 'http://google.com/'
}
]
});
});
</script>
<style>
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;
}
.fc-past {
background: #fbc0fc;
}
.fc-future {
background: #a4ffa4;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>
+11 -2
View File
@@ -59,9 +59,13 @@ $(document).ready(function() {
center: 'title',
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
},
editable: true,
//disableResizing: true,
//disableDragging: true,
//eventStartEditable: false,
//eventDurationEditable: false,
//disableResizing: true, // deprecated
//disableDragging: true, // deprecated
selectable: true,
selectHelper: true,
dragOpacity: .5,
@@ -98,9 +102,14 @@ $(document).ready(function() {
{
color: 'purple',
//editable: false,
//startEditable: false,
//durationEditable: false,
events: [
{
title: 'All Day Event',
//startEditable: false,
//durationEditable: false,
start: new Date(y, m, 1)
},
{
+1 -1
View File
@@ -13,7 +13,7 @@
$(document).ready(function() {
$('#tabs').tabs({
show: function() {
activate: function() {
$('#calendar').fullCalendar('render');
}
});
+152
View File
@@ -0,0 +1,152 @@
<!DOCTYPE html>
<html>
<head>
<link href='../build/out/fullcalendar.css' rel='stylesheet' />
<link href='../build/out/fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='../build/out/jquery.js'></script>
<script src='../build/out/jquery-ui.js'></script>
<script src='../build/out/fullcalendar.js'></script>
<script src='../build/out/gcal.js'></script>
<script>
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var verbose = false;
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
},
editable: true,
selectable: true,
viewRender: function(view, element) {
console.log('viewRender');
//alert('viewRender');
if (verbose) {
console.log(' this', this);
console.log(' view', view);
console.log(' element', element);
}
},
eventAfterAllRender: function(view) {
console.log('eventAfterAllRender');
if (verbose) {
console.log(' this', this);
console.log(' view', view);
}
},
viewDestroy: function(view, element) {
console.log('viewDestroy');
//alert('viewDestroy');
if (verbose) {
console.log(' this', this);
console.log(' view', view);
console.log(' element', element);
}
},
eventDestroy: function(event, element) {
console.log('eventDestroy');
//alert('eventDestroy');
if (verbose) {
console.log(' this', this);
console.log(' event', event);
console.log(' element', element);
}
},
/*
viewDisplay: function(view) { // deprecated
console.log('viewDisplay');
if (verbose) {
console.log('The new title of the view is ' + view.title);
}
},
*/
eventSources: [
{
url: "http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic",
editable: true,
className: 'holiday'
},
{
events: [
{
title: 'All Day Event',
start: new Date(y, m, 1)
},
{
title: 'Long Event',
start: new Date(y, m, d-5),
end: new Date(y, m, d-2)
},
{
id: 999,
title: 'Repeating Event',
start: new Date(y, m, d-3, 16, 0),
allDay: false
},
{
id: 999,
title: 'Repeating Event',
start: new Date(y, m, d+4, 16, 0),
allDay: false
},
{
id: 888,
title: 'Meeting',
start: new Date(y, m, d, 10, 30),
allDay: false
},
{
id: 777,
title: 'Lunch',
start: new Date(y, m, d, 12, 0),
end: new Date(y, m, d, 14, 0),
allDay: false
},
{
title: 'Birthday Party',
start: new Date(y, m, d+1, 19, 0),
end: new Date(y, m, d+1, 22, 30),
allDay: false
},
{
title: 'Click for Google',
start: new Date(y, m, 28),
end: new Date(y, m, 29),
url: 'http://google.com/'
}
]
}
]
});
});
function hyperJump() {console.log('hyperJump');
$('#calendar').fullCalendar('changeView', 'agendaWeek');
//alert('pause');
$('#calendar').fullCalendar('gotoDate', new Date(y, m+2, d));
}
</script>
</head>
<body style='font-size:14px'>
<button onclick='hyperJump()'>changeView+gotoDate</button>
<div id='calendar' style='width:75%;margin:20px auto 0;font-family:arial'></div>
</body>
</html>