This commit is contained in:
sean kenny
2014-09-12 15:18:47 +01:00
parent ea04fbf745
commit 98a9b3e077
5 changed files with 744 additions and 1703 deletions
+1 -1
View File
@@ -243,7 +243,7 @@ function Calendar(element, instanceOptions) {
EventManager.call(t, options);
//ResourceManager.call(t, options);
ResourceManager.call(t, options);
var isFetchNeeded = t.isFetchNeeded;
var fetchEvents = t.fetchEvents;
+430 -430
View File
@@ -1,430 +1,430 @@
/* An abstract class for all agenda-related views. Displays one more columns with time slots running vertically.
----------------------------------------------------------------------------------------------------------------------*/
// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
// Responsible for managing width/height.
setDefaults({
allDaySlot: true,
allDayText: 'all-day',
scrollTime: '06:00:00',
slotDuration: '00:30:00',
axisFormat: generateAgendaAxisFormat,
timeFormat: {
agenda: generateAgendaTimeFormat
},
minTime: '00:00:00',
maxTime: '24:00:00',
slotEventOverlap: true
});
var AGENDA_ALL_DAY_EVENT_LIMIT = 5;
function generateAgendaAxisFormat(options, langData) {
return langData.longDateFormat('LT')
.replace(':mm', '(:mm)')
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign langs
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
}
function generateAgendaTimeFormat(options, langData) {
return langData.longDateFormat('LT')
.replace(/\s*a$/i, ''); // remove trailing AM/PM
}
function AgendaView(calendar) {
View.call(this, calendar); // call the super-constructor
this.timeGrid = new TimeGrid(this);
if (this.opt('allDaySlot')) { // should we display the "all-day" area?
this.dayGrid = new DayGrid(this); // the all-day subcomponent of this view
// the coordinate grid will be a combination of both subcomponents' grids
this.coordMap = new ComboCoordMap([
this.dayGrid.coordMap,
this.timeGrid.coordMap
]);
}
else {
this.coordMap = this.timeGrid.coordMap;
}
}
AgendaView.prototype = createObject(View.prototype); // define the super-class
$.extend(AgendaView.prototype, {
timeGrid: null, // the main time-grid subcomponent of this view
dayGrid: null, // the "all-day" subcomponent. if all-day is turned off, this will be null
axisWidth: null, // the width of the time axis running down the side
noScrollRowEls: null, // set of fake row elements that must compensate when scrollerEl has scrollbars
// when the time-grid isn't tall enough to occupy the given height, we render an <hr> underneath
bottomRuleEl: null,
bottomRuleHeight: null,
/* Rendering
------------------------------------------------------------------------------------------------------------------*/
// Renders the view into `this.el`, which has already been assigned.
// `colCnt` has been calculated by a subclass and passed here.
render: function(colCnt) {
// needed for cell-to-date and date-to-cell calculations in View
this.rowCnt = 1;
this.colCnt = colCnt;
this.el.addClass('fc-agenda-view').html(this.renderHtml());
// the element that wraps the time-grid that will probably scroll
this.scrollerEl = this.el.find('.fc-time-grid-container');
this.timeGrid.coordMap.containerEl = this.scrollerEl; // don't accept clicks/etc outside of this
this.timeGrid.el = this.el.find('.fc-time-grid');
this.timeGrid.render();
// the <hr> that sometimes displays under the time-grid
this.bottomRuleEl = $('<hr class="' + this.widgetHeaderClass + '"/>')
.appendTo(this.timeGrid.el); // inject it into the time-grid
if (this.dayGrid) {
this.dayGrid.el = this.el.find('.fc-day-grid');
this.dayGrid.render();
// have the day-grid extend it's coordinate area over the <hr> dividing the two grids
this.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight();
}
this.noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)'); // fake rows not within the scroller
View.prototype.render.call(this); // call the super-method
this.resetScroll(); // do this after sizes have been set
},
// Make subcomponents ready for cleanup
destroy: function() {
this.timeGrid.destroy();
if (this.dayGrid) {
this.dayGrid.destroy();
}
View.prototype.destroy.call(this); // call the super-method
},
// Builds the HTML skeleton for the view.
// The day-grid and time-grid components will render inside containers defined by this HTML.
renderHtml: function() {
return '' +
'<table>' +
'<thead>' +
'<tr>' +
'<td class="' + this.widgetHeaderClass + '">' +
this.timeGrid.headHtml() + // render the day-of-week headers
'</td>' +
'</tr>' +
'</thead>' +
'<tbody>' +
'<tr>' +
'<td class="' + this.widgetContentClass + '">' +
(this.dayGrid ?
'<div class="fc-day-grid"/>' +
'<hr class="' + this.widgetHeaderClass + '"/>' :
''
) +
'<div class="fc-time-grid-container">' +
'<div class="fc-time-grid"/>' +
'</div>' +
'</td>' +
'</tr>' +
'</tbody>' +
'</table>';
},
// Generates the HTML that will go before the day-of week header cells.
// Queried by the TimeGrid subcomponent when generating rows. Ordering depends on isRTL.
headIntroHtml: function() {
var date;
var weekNumber;
var weekTitle;
var weekText;
if (this.opt('weekNumbers')) {
date = this.cellToDate(0, 0);
weekNumber = this.calendar.calculateWeekNumber(date);
weekTitle = this.opt('weekNumberTitle');
if (this.opt('isRTL')) {
weekText = weekNumber + weekTitle;
}
else {
weekText = weekTitle + weekNumber;
}
return '' +
'<th class="fc-axis fc-week-number ' + this.widgetHeaderClass + '" ' + this.axisStyleAttr() + '>' +
'<span>' + // needed for matchCellWidths
htmlEscape(weekText) +
'</span>' +
'</th>';
}
else {
return '<th class="fc-axis ' + this.widgetHeaderClass + '" ' + this.axisStyleAttr() + '></th>';
}
},
// Generates the HTML that goes before the all-day cells.
// Queried by the DayGrid subcomponent when generating rows. Ordering depends on isRTL.
dayIntroHtml: function() {
return '' +
'<td class="fc-axis ' + this.widgetContentClass + '" ' + this.axisStyleAttr() + '>' +
'<span>' + // needed for matchCellWidths
(this.opt('allDayHtml') || htmlEscape(this.opt('allDayText'))) +
'</span>' +
'</td>';
},
// Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
slotBgIntroHtml: function() {
return '<td class="fc-axis ' + this.widgetContentClass + '" ' + this.axisStyleAttr() + '></td>';
},
// Generates the HTML that goes before all other types of cells.
// Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.
// Queried by the TimeGrid and DayGrid subcomponents when generating rows. Ordering depends on isRTL.
introHtml: function() {
return '<td class="fc-axis" ' + this.axisStyleAttr() + '></td>';
},
// Generates an HTML attribute string for setting the width of the axis, if it is known
axisStyleAttr: function() {
if (this.axisWidth !== null) {
return 'style="width:' + this.axisWidth + 'px"';
}
return '';
},
/* Dimensions
------------------------------------------------------------------------------------------------------------------*/
updateSize: function(isResize) {
if (isResize) {
this.timeGrid.resize();
}
View.prototype.updateSize.call(this, isResize);
},
// Refreshes the horizontal dimensions of the view
updateWidth: function() {
// make all axis cells line up, and record the width so newly created axis cells will have it
this.axisWidth = matchCellWidths(this.el.find('.fc-axis'));
},
// Adjusts the vertical dimensions of the view to the specified values
setHeight: function(totalHeight, isAuto) {
var eventLimit;
var scrollerHeight;
if (this.bottomRuleHeight === null) {
// calculate the height of the rule the very first time
this.bottomRuleHeight = this.bottomRuleEl.outerHeight();
}
this.bottomRuleEl.hide(); // .show() will be called later if this <hr> is necessary
// reset all dimensions back to the original state
this.scrollerEl.css('overflow', '');
unsetScroller(this.scrollerEl);
uncompensateScroll(this.noScrollRowEls);
// limit number of events in the all-day area
if (this.dayGrid) {
this.dayGrid.destroySegPopover(); // kill the "more" popover if displayed
eventLimit = this.opt('eventLimit');
if (eventLimit && typeof eventLimit !== 'number') {
eventLimit = AGENDA_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number
}
if (eventLimit) {
this.dayGrid.limitRows(eventLimit);
}
}
if (!isAuto) { // should we force dimensions of the scroll container, or let the contents be natural height?
scrollerHeight = this.computeScrollerHeight(totalHeight);
if (setPotentialScroller(this.scrollerEl, scrollerHeight)) { // using scrollbars?
// make the all-day and header rows lines up
compensateScroll(this.noScrollRowEls, getScrollbarWidths(this.scrollerEl));
// the scrollbar compensation might have changed text flow, which might affect height, so recalculate
// and reapply the desired height to the scroller.
scrollerHeight = this.computeScrollerHeight(totalHeight);
this.scrollerEl.height(scrollerHeight);
this.restoreScroll();
}
else { // no scrollbars
// still, force a height and display the bottom rule (marks the end of day)
this.scrollerEl.height(scrollerHeight).css('overflow', 'hidden'); // in case <hr> goes outside
this.bottomRuleEl.show();
}
}
},
// Sets the scroll value of the scroller to the intial pre-configured state prior to allowing the user to change it.
resetScroll: function() {
var _this = this;
var scrollTime = moment.duration(this.opt('scrollTime'));
var top = this.timeGrid.computeTimeTop(scrollTime);
// zoom can give weird floating-point values. rather scroll a little bit further
top = Math.ceil(top);
if (top) {
top++; // to overcome top border that slots beyond the first have. looks better
}
function scroll() {
_this.scrollerEl.scrollTop(top);
}
scroll();
setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
},
/* Events
------------------------------------------------------------------------------------------------------------------*/
// Renders events onto the view and populates the View's segment array
renderEvents: function(events) {
var dayEvents = [];
var timedEvents = [];
var daySegs = [];
var timedSegs;
var i;
// separate the events into all-day and timed
for (i = 0; i < events.length; i++) {
if (events[i].allDay) {
dayEvents.push(events[i]);
}
else {
timedEvents.push(events[i]);
}
}
// render the events in the subcomponents
timedSegs = this.timeGrid.renderEvents(timedEvents);
if (this.dayGrid) {
daySegs = this.dayGrid.renderEvents(dayEvents);
}
// the all-day area is flexible and might have a lot of events, so shift the height
this.updateHeight();
View.prototype.renderEvents.call(this, events); // call the super-method
},
// Retrieves all segment objects that are rendered in the view
getSegs: function() {
return this.timeGrid.getSegs().concat(
this.dayGrid ? this.dayGrid.getSegs() : []
);
},
// Unrenders all event elements and clears internal segment data
destroyEvents: function() {
View.prototype.destroyEvents.call(this); // do this before the grids' segs have been cleared
// if destroyEvents is being called as part of an event rerender, renderEvents will be called shortly
// after, so remember what the scroll value was so we can restore it.
this.recordScroll();
// destroy the events in the subcomponents
this.timeGrid.destroyEvents();
if (this.dayGrid) {
this.dayGrid.destroyEvents();
}
// we DON'T need to call updateHeight() because:
// A) a renderEvents() call always happens after this, which will eventually call updateHeight()
// B) in IE8, this causes a flash whenever events are rerendered
},
/* Event Dragging
------------------------------------------------------------------------------------------------------------------*/
// Renders a visual indication of an event being dragged over the view.
// A returned value of `true` signals that a mock "helper" event has been rendered.
renderDrag: function(start, end, seg) {
if (start.hasTime()) {
return this.timeGrid.renderDrag(start, end, seg);
}
else if (this.dayGrid) {
return this.dayGrid.renderDrag(start, end, seg);
}
},
// Unrenders a visual indications of an event being dragged over the view
destroyDrag: function() {
this.timeGrid.destroyDrag();
if (this.dayGrid) {
this.dayGrid.destroyDrag();
}
},
/* Selection
------------------------------------------------------------------------------------------------------------------*/
// Renders a visual indication of a selection
renderSelection: function(start, end) {
if (start.hasTime() || end.hasTime()) {
this.timeGrid.renderSelection(start, end);
}
else if (this.dayGrid) {
this.dayGrid.renderSelection(start, end);
}
},
// Unrenders a visual indications of a selection
destroySelection: function() {
this.timeGrid.destroySelection();
if (this.dayGrid) {
this.dayGrid.destroySelection();
}
}
});
/* An abstract class for all agenda-related views. Displays one more columns with time slots running vertically.
----------------------------------------------------------------------------------------------------------------------*/
// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
// Responsible for managing width/height.
setDefaults({
allDaySlot: true,
allDayText: 'all-day',
scrollTime: '06:00:00',
slotDuration: '00:30:00',
axisFormat: generateAgendaAxisFormat,
timeFormat: {
agenda: generateAgendaTimeFormat
},
minTime: '00:00:00',
maxTime: '24:00:00',
slotEventOverlap: true
});
var AGENDA_ALL_DAY_EVENT_LIMIT = 5;
function generateAgendaAxisFormat(options, langData) {
return langData.longDateFormat('LT')
.replace(':mm', '(:mm)')
.replace(/(\Wmm)$/, '($1)') // like above, but for foreign langs
.replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand
}
function generateAgendaTimeFormat(options, langData) {
return langData.longDateFormat('LT')
.replace(/\s*a$/i, ''); // remove trailing AM/PM
}
function AgendaView(calendar) {
View.call(this, calendar); // call the super-constructor
this.timeGrid = new TimeGrid(this);
if (this.opt('allDaySlot')) { // should we display the "all-day" area?
this.dayGrid = new DayGrid(this); // the all-day subcomponent of this view
// the coordinate grid will be a combination of both subcomponents' grids
this.coordMap = new ComboCoordMap([
this.dayGrid.coordMap,
this.timeGrid.coordMap
]);
}
else {
this.coordMap = this.timeGrid.coordMap;
}
}
AgendaView.prototype = createObject(View.prototype); // define the super-class
$.extend(AgendaView.prototype, {
timeGrid: null, // the main time-grid subcomponent of this view
dayGrid: null, // the "all-day" subcomponent. if all-day is turned off, this will be null
axisWidth: null, // the width of the time axis running down the side
noScrollRowEls: null, // set of fake row elements that must compensate when scrollerEl has scrollbars
// when the time-grid isn't tall enough to occupy the given height, we render an <hr> underneath
bottomRuleEl: null,
bottomRuleHeight: null,
/* Rendering
------------------------------------------------------------------------------------------------------------------*/
// Renders the view into `this.el`, which has already been assigned.
// `colCnt` has been calculated by a subclass and passed here.
render: function(colCnt) {
// needed for cell-to-date and date-to-cell calculations in View
this.rowCnt = 1;
this.colCnt = colCnt;
this.el.addClass('fc-agenda-view').html(this.renderHtml());
// the element that wraps the time-grid that will probably scroll
this.scrollerEl = this.el.find('.fc-time-grid-container');
this.timeGrid.coordMap.containerEl = this.scrollerEl; // don't accept clicks/etc outside of this
this.timeGrid.el = this.el.find('.fc-time-grid');
this.timeGrid.render();
// the <hr> that sometimes displays under the time-grid
this.bottomRuleEl = $('<hr class="' + this.widgetHeaderClass + '"/>')
.appendTo(this.timeGrid.el); // inject it into the time-grid
if (this.dayGrid) {
this.dayGrid.el = this.el.find('.fc-day-grid');
this.dayGrid.render();
// have the day-grid extend it's coordinate area over the <hr> dividing the two grids
this.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight();
}
this.noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)'); // fake rows not within the scroller
View.prototype.render.call(this); // call the super-method
this.resetScroll(); // do this after sizes have been set
},
// Make subcomponents ready for cleanup
destroy: function() {
this.timeGrid.destroy();
if (this.dayGrid) {
this.dayGrid.destroy();
}
View.prototype.destroy.call(this); // call the super-method
},
// Builds the HTML skeleton for the view.
// The day-grid and time-grid components will render inside containers defined by this HTML.
renderHtml: function() {
return '' +
'<table>' +
'<thead>' +
'<tr>' +
'<td class="' + this.widgetHeaderClass + '">' +
this.timeGrid.headHtml() + // render the day-of-week headers
'</td>' +
'</tr>' +
'</thead>' +
'<tbody>' +
'<tr>' +
'<td class="' + this.widgetContentClass + '">' +
(this.dayGrid ?
'<div class="fc-day-grid"/>' +
'<hr class="' + this.widgetHeaderClass + '"/>' :
''
) +
'<div class="fc-time-grid-container">' +
'<div class="fc-time-grid"/>' +
'</div>' +
'</td>' +
'</tr>' +
'</tbody>' +
'</table>';
},
// Generates the HTML that will go before the day-of week header cells.
// Queried by the TimeGrid subcomponent when generating rows. Ordering depends on isRTL.
headIntroHtml: function() {
var date;
var weekNumber;
var weekTitle;
var weekText;
if (this.opt('weekNumbers')) {
date = this.cellToDate(0, 0);
weekNumber = this.calendar.calculateWeekNumber(date);
weekTitle = this.opt('weekNumberTitle');
if (this.opt('isRTL')) {
weekText = weekNumber + weekTitle;
}
else {
weekText = weekTitle + weekNumber;
}
return '' +
'<th class="fc-axis fc-week-number ' + this.widgetHeaderClass + '" ' + this.axisStyleAttr() + '>' +
'<span>' + // needed for matchCellWidths
htmlEscape(weekText) +
'</span>' +
'</th>';
}
else {
return '<th class="fc-axis ' + this.widgetHeaderClass + '" ' + this.axisStyleAttr() + '></th>';
}
},
// Generates the HTML that goes before the all-day cells.
// Queried by the DayGrid subcomponent when generating rows. Ordering depends on isRTL.
dayIntroHtml: function() {
return '' +
'<td class="fc-axis ' + this.widgetContentClass + '" ' + this.axisStyleAttr() + '>' +
'<span>' + // needed for matchCellWidths
(this.opt('allDayHtml') || htmlEscape(this.opt('allDayText'))) +
'</span>' +
'</td>';
},
// Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
slotBgIntroHtml: function() {
return '<td class="fc-axis ' + this.widgetContentClass + '" ' + this.axisStyleAttr() + '></td>';
},
// Generates the HTML that goes before all other types of cells.
// Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.
// Queried by the TimeGrid and DayGrid subcomponents when generating rows. Ordering depends on isRTL.
introHtml: function() {
return '<td class="fc-axis" ' + this.axisStyleAttr() + '></td>';
},
// Generates an HTML attribute string for setting the width of the axis, if it is known
axisStyleAttr: function() {
if (this.axisWidth !== null) {
return 'style="width:' + this.axisWidth + 'px"';
}
return '';
},
/* Dimensions
------------------------------------------------------------------------------------------------------------------*/
updateSize: function(isResize) {
if (isResize) {
this.timeGrid.resize();
}
View.prototype.updateSize.call(this, isResize);
},
// Refreshes the horizontal dimensions of the view
updateWidth: function() {
// make all axis cells line up, and record the width so newly created axis cells will have it
this.axisWidth = matchCellWidths(this.el.find('.fc-axis'));
},
// Adjusts the vertical dimensions of the view to the specified values
setHeight: function(totalHeight, isAuto) {
var eventLimit;
var scrollerHeight;
if (this.bottomRuleHeight === null) {
// calculate the height of the rule the very first time
this.bottomRuleHeight = this.bottomRuleEl.outerHeight();
}
this.bottomRuleEl.hide(); // .show() will be called later if this <hr> is necessary
// reset all dimensions back to the original state
this.scrollerEl.css('overflow', '');
unsetScroller(this.scrollerEl);
uncompensateScroll(this.noScrollRowEls);
// limit number of events in the all-day area
if (this.dayGrid) {
this.dayGrid.destroySegPopover(); // kill the "more" popover if displayed
eventLimit = this.opt('eventLimit');
if (eventLimit && typeof eventLimit !== 'number') {
eventLimit = AGENDA_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number
}
if (eventLimit) {
this.dayGrid.limitRows(eventLimit);
}
}
if (!isAuto) { // should we force dimensions of the scroll container, or let the contents be natural height?
scrollerHeight = this.computeScrollerHeight(totalHeight);
if (setPotentialScroller(this.scrollerEl, scrollerHeight)) { // using scrollbars?
// make the all-day and header rows lines up
compensateScroll(this.noScrollRowEls, getScrollbarWidths(this.scrollerEl));
// the scrollbar compensation might have changed text flow, which might affect height, so recalculate
// and reapply the desired height to the scroller.
scrollerHeight = this.computeScrollerHeight(totalHeight);
this.scrollerEl.height(scrollerHeight);
this.restoreScroll();
}
else { // no scrollbars
// still, force a height and display the bottom rule (marks the end of day)
this.scrollerEl.height(scrollerHeight).css('overflow', 'hidden'); // in case <hr> goes outside
this.bottomRuleEl.show();
}
}
},
// Sets the scroll value of the scroller to the intial pre-configured state prior to allowing the user to change it.
resetScroll: function() {
var _this = this;
var scrollTime = moment.duration(this.opt('scrollTime'));
var top = this.timeGrid.computeTimeTop(scrollTime);
// zoom can give weird floating-point values. rather scroll a little bit further
top = Math.ceil(top);
if (top) {
top++; // to overcome top border that slots beyond the first have. looks better
}
function scroll() {
_this.scrollerEl.scrollTop(top);
}
scroll();
setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
},
/* Events
------------------------------------------------------------------------------------------------------------------*/
// Renders events onto the view and populates the View's segment array
renderEvents: function(events) {
var dayEvents = [];
var timedEvents = [];
var daySegs = [];
var timedSegs;
var i;
// separate the events into all-day and timed
for (i = 0; i < events.length; i++) {
if (events[i].allDay) {
dayEvents.push(events[i]);
}
else {
timedEvents.push(events[i]);
}
}
// render the events in the subcomponents
timedSegs = this.timeGrid.renderEvents(timedEvents);
if (this.dayGrid) {
daySegs = this.dayGrid.renderEvents(dayEvents);
}
// the all-day area is flexible and might have a lot of events, so shift the height
this.updateHeight();
// /View.prototype.renderEvents.call(this, events); // call the super-method
},
// Retrieves all segment objects that are rendered in the view
getSegs: function() {
return this.timeGrid.getSegs().concat(
this.dayGrid ? this.dayGrid.getSegs() : []
);
},
// Unrenders all event elements and clears internal segment data
destroyEvents: function() {
View.prototype.destroyEvents.call(this); // do this before the grids' segs have been cleared
// if destroyEvents is being called as part of an event rerender, renderEvents will be called shortly
// after, so remember what the scroll value was so we can restore it.
this.recordScroll();
// destroy the events in the subcomponents
this.timeGrid.destroyEvents();
if (this.dayGrid) {
this.dayGrid.destroyEvents();
}
// we DON'T need to call updateHeight() because:
// A) a renderEvents() call always happens after this, which will eventually call updateHeight()
// B) in IE8, this causes a flash whenever events are rerendered
},
/* Event Dragging
------------------------------------------------------------------------------------------------------------------*/
// Renders a visual indication of an event being dragged over the view.
// A returned value of `true` signals that a mock "helper" event has been rendered.
renderDrag: function(start, end, seg) {
if (start.hasTime()) {
return this.timeGrid.renderDrag(start, end, seg);
}
else if (this.dayGrid) {
return this.dayGrid.renderDrag(start, end, seg);
}
},
// Unrenders a visual indications of an event being dragged over the view
destroyDrag: function() {
this.timeGrid.destroyDrag();
if (this.dayGrid) {
this.dayGrid.destroyDrag();
}
},
/* Selection
------------------------------------------------------------------------------------------------------------------*/
// Renders a visual indication of a selection
renderSelection: function(start, end) {
if (start.hasTime() || end.hasTime()) {
this.timeGrid.renderSelection(start, end);
}
else if (this.dayGrid) {
this.dayGrid.renderSelection(start, end);
}
},
// Unrenders a visual indications of a selection
destroySelection: function() {
this.timeGrid.destroySelection();
if (this.dayGrid) {
this.dayGrid.destroySelection();
}
}
});
+62 -34
View File
@@ -1,34 +1,62 @@
fcViews.resourceDay = ResourceDayView;
function ResourceDayView(element, calendar) { // TODO: make a DayView mixin
var t = this;
// exports
t.incrementDate = incrementDate;
t.render = render;
// imports
ResourceView.call(t, element, calendar, 'resourceDay');
var getResources = t.getResources;
function incrementDate(date, delta) {
var out = date.clone().stripTime().add(delta, 'days');
out = t.skipHiddenDays(out, delta < 0 ? -1 : 1);
return out;
}
function render(date) {
t.start = t.intervalStart = date.clone().stripTime();
t.end = t.intervalEnd = t.start.clone().add(1, 'days');
t.title = calendar.formatDate(t.start, t.opt('titleFormat'));
t.renderResource(getResources().length);
}
}
/* A day view with an all-day cell area at the top, and a time grid below by resource
----------------------------------------------------------------------------------------------------------------------*/
fcViews.resourceDay = ResourceDayView;
function ResourceDayView(calendar) { // TODO: make a ResourceView mixin
ResourceView.call(this, calendar); // call the super-constructor
}
ResourceDayView.prototype = createObject(ResourceView.prototype); // define the super-class
$.extend(ResourceDayView.prototype, {
name: 'resourceDay',
incrementDate: function(date, delta) {
var out = date.clone().stripTime().add(delta, 'days');
out = this.skipHiddenDays(out, delta < 0 ? -1 : 1);
return out;
},
render: function(date) {
this.start = this.intervalStart = date.clone().stripTime();
this.end = this.intervalEnd = this.start.clone().add(1, 'days');
this.title = this.calendar.formatDate(this.start, this.opt('titleFormat'));
ResourceView.prototype.render.call(this, this.calendar.fetchResources().length); // call the super-method
},
// Computes HTML classNames for a single-day cell
getDayClasses: function(date) {
var view = this.view;
var today = view.calendar.getNow().stripTime();
var classes = [ 'fc-' + dayIDs[date.day()] ];
if (
view.name === 'month' &&
date.month() != view.intervalStart.month()
) {
classes.push('fc-other-month');
}
if (date.isSame(today, 'day')) {
classes.push(
'fc-todaysss',
view.highlightStateClass
);
}
else if (date < today) {
classes.push('fc-past');
}
else {
classes.push('fc-future');
}
return classes;
}
});
File diff suppressed because it is too large Load Diff
+167 -211
View File
@@ -1,212 +1,168 @@
<!DOCTYPE html>
<html>
<head>
<link href='../dist/fullcalendar.css' rel='stylesheet' />
<link href='../dist/fullcalendar.print.css' rel='stylesheet' media='print' />
<style>
button {
font-size: 11px;
}
</style>
</head>
<body style='font-size:12px'>
<!-- <p>
<button onclick="cal.fullCalendar('prev')">prev</button>
<button onclick="cal.fullCalendar('next')">next</button>
<button onclick="cal.fullCalendar('today')">today</button>
<button onclick="cal.fullCalendar('gotoDate', 1999, 9, 31)">Oct 31 1999</button>
<button onclick="cal.fullCalendar('gotoDate', new Date(1999, 9, 30))">Oct 30 1999 (Date)</button>
<button onclick="cal.fullCalendar('incrementDate', 1, 1, 1)">+1 +1 +1</button>
<button onclick="cal.fullCalendar('incrementDate', -1, -1, -1)">-1 -1 -1</button>
<button onclick="updateEventStart()">update event start</button>
<button onclick="updateRepeatingEvent()">update repeating event</button>
<button onclick="renderEvent(false)">render new event</button>
<button onclick="renderEvent(true)">render new sticky event</button>
<br />
<button onclick="cal.fullCalendar('removeEvents')">remove all</button>
<button onclick="cal.fullCalendar('removeEvents', 999)">remove repeating events</button>
<button onclick="cal.fullCalendar('removeEvents', function(e){return !e.allDay})">remove timed events</button>
<button onclick="console.log(cal.fullCalendar('clientEvents'))">log events</button>
<button onclick="console.log(cal.fullCalendar('clientEvents', '999'))">log repeating events</button>
<button onclick="console.log(cal.fullCalendar('clientEvents', function(e){return e.allDay}))">log all-day events</button>
<br />
<button onclick="cal.fullCalendar('addEventSource', staticEvents)">+ static events</button>
<button onclick="cal.fullCalendar('removeEventSource', staticEvents)">- static events</button>
<button onclick="cal.fullCalendar('addEventSource', gcalFeed)">+ gcal</button>
<button onclick="cal.fullCalendar('removeEventSource', gcalFeed)">- gcal</button>
<button onclick="cal.fullCalendar('addEventSource', jsonFeed)">+ json</button>
<button onclick="cal.fullCalendar('removeEventSource', jsonFeed)">- json</button>
<button onclick="cal.fullCalendar('rerenderEvents')">rerender events</button>
<button onclick="cal.fullCalendar('refetchEvents')">refetch events</button>
<br />
<button onclick="cal.fullCalendar('changeView', 'month')">change to month</button>
<button onclick="cal.fullCalendar('changeView', 'basicWeek')">change to basicWeek</button>
<button onclick="cal.fullCalendar('changeView', 'basicDay')">change to basicDay</button>
<button onclick="getView()">getView</button>
<button onclick="getDate()">getDate</button>
<button onclick="optionGetter()">option getter</button>
<button onclick="cal.width(1100)">change width (passive)</button>
<button onclick="cal.fullCalendar('render')">render</button>
<button onclick="cal.fullCalendar('option', 'height', 1000)">change height</button>
</p> -->
<!-- <div id='loading' style='position:absolute;display:none'>loading...</div>-->
<div id='calendar' style='width:70%;margin:20px auto 0;font-family:arial'></div>
<script src='../lib/jquery/dist/jquery.js'></script>
<script src='../lib/jquery-ui/ui/jquery-ui.js'></script>
<script src='../lib/moment/moment.js'></script>
<script src='../src/defaults.js'></script>
<script src='../src/main.js'></script>
<script src='../src/lang.js'></script>
<script src='../src/Calendar.js'></script>
<script src='../src/Header.js'></script>
<script src='../src/EventManager.js'></script>
<script src='../src/ResourceManager.js'></script>
<script src='../src/util.js'></script>
<script src='../src/moment-ext.js'></script>
<script src='../src/date-formatting.js'></script>
<script src='../src/basic/MonthView.js'></script>
<script src='../src/basic/BasicWeekView.js'></script>
<script src='../src/basic/BasicDayView.js'></script>
<script src='../src/basic/BasicView.js'></script>
<script src='../src/basic/BasicEventRenderer.js'></script>
<script src='../src/agenda/AgendaWeekView.js'></script>
<script src='../src/agenda/AgendaDayView.js'></script>
<script src='../src/agenda/AgendaView.js'></script>
<script src='../src/agenda/AgendaEventRenderer.js'></script>
<script src='../src/resource/ResourceDayView.js'></script>
<script src='../src/resource/ResourceView.js'></script>
<script src='../src/resource/ResourceEventRenderer.js'></script>
<script src='../src/common/View.js'></script>
<script src='../src/common/DayEventRenderer.js'></script>
<script src='../src/common/SelectionManager.js'></script>
<script src='../src/common/OverlayManager.js'></script>
<script src='../src/common/CoordinateGrid.js'></script>
<script src='../src/common/HoverListener.js'></script>
<script src='../src/common/HorizontalPositionCache.js'></script>
<script src='../dist/gcal.js'></script>
<script>
var cal, staticEvents;
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$(document).ready(function () {
cal = $('#calendar').fullCalendar({
eventClick: function (event) {
console.log(event);
},
editable: true,
selectable: true,
selectHelper: true,
allDaySlot: true,
eventDrop: function (event, delta, revertFunc) {
//revertFunc();
},
eventResize: function (event, delta, revertFunc) {
//revertFunc();
},
// weekends: false,
header: {
left: 'prev,next today',
center: 'title',
right: 'resourceDay,agendaDay'
},
defaultView: 'resourceDay',
resources: [
{ 'id': 'resource1', 'name': 'Resource 1', 'className': 'css-class-as-string' },
{ 'id': 'resource2', 'name': 'Resource 2', 'className': ['green', 'another-css-class-name'] },
{ 'id': 'resource3', 'name': 'Resource 3' }],
events: [
{
title: 'R1: All day',
allDay: true,
start: new Date(y, m, d, 12, 0),
resources: 'resource1'
},
{
title: 'R2: All Day',
start: new Date(y, m, d, 12, 0),
allDay: true,
resources: 'resource2'
},
{
title: 'R1/R2: 12-14',
start: new Date(y, m, d, 12, 0),
end: new Date(y, m, d, 14, 0),
allDay: false,
resources: ['resource1', 'resource2']
},
{
title: 'R1: 14:30-16',
start: new Date(y, m, d, 14, 30),
end: new Date(y, m, d, 16, 0),
allDay: false,
resources: ['resource1']
},
{
title: 'R2: 10:00-10:30',
start: new Date(y, m, d, 10, 0),
end: new Date(y, m, d, 10, 30),
allDay: false,
resources: ['resource2']
}
]
});
});
function updateEventStart() {
var event = cal.fullCalendar('clientEvents', 777)[0];
event.start = new Date(y, m, d, 13, 30);
event.end = new Date(y, m, d, 14, 50);
//event.start = new Date(y, m, 25, 10, 30); // move big days
//event.end = new Date(y, m, 26);
//event.allDay = true;
cal.fullCalendar('updateEvent', event);
}
function updateRepeatingEvent() {
var event = cal.fullCalendar('clientEvents', 999)[0];
event.start = new Date(y, m, 4, 13, 30);
event.end = new Date(y, m, 5, 2, 0);
event.allDay = true;
event.title = "repeat yo";
//event.editable = false;
event.url = "http://google.com/";
event.color = 'red';
event.textColor = 'green';
cal.fullCalendar('updateEvent', event);
//console.log(cal.fullCalendar('clientEvents', 2));
}
function renderEvent(stick) {
cal.fullCalendar('renderEvent', {
start: new Date(y, m, 17),
title: 'heyman'
}, stick);
}
function getView() {
var view = cal.fullCalendar('getView');
console.log(view.start + ' --- ' + view.end + ' "' + view.title + '"');
}
function getDate() {
console.log(cal.fullCalendar('getDate'));
}
function optionGetter() {
console.log(cal.fullCalendar('option', 'editable'));
}
var gcalFeed = $.fullCalendar.gcalFeed("http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic");
var jsonFeed = "../demos/json-events.php";
</script>
</body>
<!DOCTYPE html>
<html>
<head>
<link href='../dist/fullcalendar.css' rel='stylesheet' />
<script src='../lib/jquery/dist/jquery.js'></script>
<script src='../lib/moment/moment.js'></script>
<script src='../src/defaults.js'></script>
<script src='../src/main.js'></script>
<script src='../src/lang.js'></script>
<script src='../src/Calendar.js'></script>
<script src='../src/Header.js'></script>
<script src='../src/EventManager.js'></script>
<script src='../src/ResourceManager.js'></script>
<script src='../src/util.js'></script>
<script src='../src/moment-ext.js'></script>
<script src='../src/date-formatting.js'></script>
<script src='../src/common/Popover.js'></script>
<script src='../src/common/CoordMap.js'></script>
<script src='../src/common/DragListener.js'></script>
<script src='../src/common/MouseFollower.js'></script>
<script src='../src/common/RowRenderer.js'></script>
<script src='../src/common/Grid.js'></script>
<script src='../src/common/Grid.events.js'></script>
<script src='../src/common/DayGrid.js'></script>
<script src='../src/common/DayGrid.events.js'></script>
<script src='../src/common/DayGrid.limit.js'></script>
<script src='../src/common/TimeGrid.js'></script>
<script src='../src/common/TimeGrid.events.js'></script>
<script src='../src/common/View.js'></script>
<script src='../src/basic/BasicView.js'></script>
<script src='../src/basic/MonthView.js'></script>
<script src='../src/basic/BasicWeekView.js'></script>
<script src='../src/basic/BasicDayView.js'></script>
<script src='../src/agenda/AgendaView.js'></script>
<script src='../src/agenda/AgendaWeekView.js'></script>
<script src='../src/agenda/AgendaDayView.js'></script>
<script src='../src/resource/ResourceView.js'></script>
<script src='../src/resource/ResourceDayView.js'></script>
<script src='../dist/gcal.js'></script>
<script>
var cal, staticEvents;
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$(document).ready(function () {
cal = $('#calendar').fullCalendar({
eventClick: function (event) {
console.log(event);
},
editable: true,
selectable: true,
selectHelper: true,
allDaySlot: true,
eventDrop: function (event, delta, revertFunc) {
//revertFunc();
},
eventResize: function (event, delta, revertFunc) {
//revertFunc();
},
// weekends: false,
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaDay,resourceDay'
},
defaultView: 'resourceDay',
resources: [
{ 'id': 'resource1', 'name': 'Resource 1', 'className': 'css-class-as-string' },
{ 'id': 'resource2', 'name': 'Resource 2', 'className': ['green', 'another-css-class-name'] },
{ 'id': 'resource3', 'name': 'Resource 3' }],
events: [
{
title: 'R1: All day',
allDay: true,
start: new Date(y, m, d, 12, 0),
resources: 'resource1'
},
{
title: 'R2: All Day',
start: new Date(y, m, d, 12, 0),
allDay: true,
resources: 'resource2'
},
{
title: 'R1/R2: 12-14',
start: new Date(y, m, d, 12, 0),
end: new Date(y, m, d, 14, 0),
allDay: false,
resources: ['resource1', 'resource2']
},
{
title: 'R1: 14:30-16',
start: new Date(y, m, d, 14, 30),
end: new Date(y, m, d, 16, 0),
allDay: false,
resources: ['resource1']
},
{
title: 'R2: 10:00-10:30',
start: new Date(y, m, d, 10, 0),
end: new Date(y, m, d, 10, 30),
allDay: false,
resources: ['resource2']
}
]
});
});
function updateEventStart() {
var event = cal.fullCalendar('clientEvents', 777)[0];
event.start = new Date(y, m, d, 13, 30);
event.end = new Date(y, m, d, 14, 50);
//event.start = new Date(y, m, 25, 10, 30); // move big days
//event.end = new Date(y, m, 26);
//event.allDay = true;
cal.fullCalendar('updateEvent', event);
}
function updateRepeatingEvent() {
var event = cal.fullCalendar('clientEvents', 999)[0];
event.start = new Date(y, m, 4, 13, 30);
event.end = new Date(y, m, 5, 2, 0);
event.allDay = true;
event.title = "repeat yo";
//event.editable = false;
event.url = "http://google.com/";
event.color = 'red';
event.textColor = 'green';
cal.fullCalendar('updateEvent', event);
//console.log(cal.fullCalendar('clientEvents', 2));
}
function renderEvent(stick) {
cal.fullCalendar('renderEvent', {
start: new Date(y, m, 17),
title: 'heyman'
}, stick);
}
function getView() {
var view = cal.fullCalendar('getView');
console.log(view.start + ' --- ' + view.end + ' "' + view.title + '"');
}
function getDate() {
console.log(cal.fullCalendar('getDate'));
}
function optionGetter() {
console.log(cal.fullCalendar('option', 'editable'));
}
var gcalFeed = $.fullCalendar.gcalFeed("http://www.google.com/calendar/feeds/usa__en%40holiday.calendar.google.com/public/basic");
var jsonFeed = "../demos/json-events.php";
</script>
</head>
<body>
<div id='calendar'></div>
</body>
</html>