2010-09-19 07:54:35 +02:00
|
|
|
|
|
|
|
setDefaults({
|
|
|
|
allDaySlot: true,
|
|
|
|
allDayText: 'all-day',
|
|
|
|
firstHour: 6,
|
|
|
|
slotMinutes: 30,
|
|
|
|
defaultEventMinutes: 120,
|
|
|
|
axisFormat: 'h(:mm)tt',
|
|
|
|
timeFormat: {
|
|
|
|
agenda: 'h:mm{ - h:mm}'
|
|
|
|
},
|
|
|
|
dragOpacity: {
|
|
|
|
agenda: .5
|
|
|
|
},
|
|
|
|
minTime: 0,
|
|
|
|
maxTime: 24
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
// TODO: make it work in quirks mode (event corners, all-day height)
|
|
|
|
// TODO: test liquid width, especially in IE6
|
|
|
|
|
|
|
|
|
2010-09-19 07:54:35 +02:00
|
|
|
function AgendaView(element, calendar, viewName) {
|
|
|
|
var t = this;
|
|
|
|
|
|
|
|
|
|
|
|
// exports
|
|
|
|
t.renderAgenda = renderAgenda;
|
|
|
|
t.setWidth = setWidth;
|
|
|
|
t.setHeight = setHeight;
|
|
|
|
t.beforeHide = beforeHide;
|
|
|
|
t.afterShow = afterShow;
|
|
|
|
t.defaultEventEnd = defaultEventEnd;
|
|
|
|
t.timePosition = timePosition;
|
|
|
|
t.dayOfWeekCol = dayOfWeekCol;
|
2010-11-10 07:54:41 +01:00
|
|
|
t.dateCell = dateCell;
|
2010-09-19 07:54:35 +02:00
|
|
|
t.cellDate = cellDate;
|
|
|
|
t.cellIsAllDay = cellIsAllDay;
|
2011-01-24 08:10:25 +01:00
|
|
|
t.allDayRow = getAllDayRow;
|
2010-09-19 07:54:35 +02:00
|
|
|
t.allDayBounds = allDayBounds;
|
|
|
|
t.getHoverListener = function() { return hoverListener };
|
|
|
|
t.colContentLeft = colContentLeft;
|
|
|
|
t.colContentRight = colContentRight;
|
|
|
|
t.getDaySegmentContainer = function() { return daySegmentContainer };
|
|
|
|
t.getSlotSegmentContainer = function() { return slotSegmentContainer };
|
|
|
|
t.getMinMinute = function() { return minMinute };
|
|
|
|
t.getMaxMinute = function() { return maxMinute };
|
2011-01-24 08:10:25 +01:00
|
|
|
t.getBodyContent = function() { return slotContent }; // !!??
|
2010-09-19 07:54:35 +02:00
|
|
|
t.getRowCnt = function() { return 1 };
|
|
|
|
t.getColCnt = function() { return colCnt };
|
|
|
|
t.getColWidth = function() { return colWidth };
|
|
|
|
t.getSlotHeight = function() { return slotHeight };
|
|
|
|
t.defaultSelectionEnd = defaultSelectionEnd;
|
|
|
|
t.renderDayOverlay = renderDayOverlay;
|
|
|
|
t.renderSelection = renderSelection;
|
|
|
|
t.clearSelection = clearSelection;
|
2011-01-24 08:10:25 +01:00
|
|
|
t.reportDayClick = reportDayClick; // selection mousedown hack
|
2010-09-19 07:54:35 +02:00
|
|
|
t.dragStart = dragStart;
|
|
|
|
t.dragStop = dragStop;
|
|
|
|
|
|
|
|
|
|
|
|
// imports
|
|
|
|
View.call(t, element, calendar, viewName);
|
|
|
|
OverlayManager.call(t);
|
|
|
|
SelectionManager.call(t);
|
|
|
|
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;
|
|
|
|
var unselect = t.unselect;
|
|
|
|
var daySelectionMousedown = t.daySelectionMousedown;
|
|
|
|
var slotSegHtml = t.slotSegHtml;
|
|
|
|
var formatDate = calendar.formatDate;
|
|
|
|
|
|
|
|
|
|
|
|
// locals
|
2011-01-24 08:10:25 +01:00
|
|
|
|
|
|
|
var dayTable;
|
|
|
|
var dayHead;
|
|
|
|
var dayHeadCells;
|
|
|
|
var dayBody;
|
|
|
|
var dayBodyCells;
|
|
|
|
var dayBodyCellInners;
|
|
|
|
var dayBodyFirstCell;
|
|
|
|
var dayBodyFirstCellStretcher;
|
|
|
|
var slotLayer;
|
|
|
|
var daySegmentContainer;
|
|
|
|
var allDayTable;
|
|
|
|
var allDayRow;
|
|
|
|
var slotScroller;
|
|
|
|
var slotContent;
|
|
|
|
var slotSegmentContainer;
|
|
|
|
var slotTable;
|
|
|
|
var slotTableFirstInner;
|
|
|
|
var axisFirstCells;
|
|
|
|
var gutterCells;
|
|
|
|
var selectionHelper;
|
|
|
|
|
|
|
|
var viewWidth;
|
|
|
|
var viewHeight;
|
|
|
|
var axisWidth;
|
|
|
|
var colWidth;
|
|
|
|
var gutterWidth;
|
|
|
|
var slotHeight; // TODO: what if slotHeight changes? (see issue 650)
|
2010-09-19 07:54:35 +02:00
|
|
|
var savedScrollTop;
|
2011-01-24 08:10:25 +01:00
|
|
|
|
|
|
|
var colCnt;
|
|
|
|
var slotCnt;
|
2010-09-19 07:54:35 +02:00
|
|
|
var coordinateGrid;
|
|
|
|
var hoverListener;
|
|
|
|
var colContentPositions;
|
|
|
|
var slotTopCache = {};
|
2011-01-24 08:10:25 +01:00
|
|
|
|
|
|
|
var tm;
|
|
|
|
var firstDay;
|
|
|
|
var nwe; // no weekends (int)
|
|
|
|
var rtl, dis, dit; // day index sign / translate
|
|
|
|
var minMinute, maxMinute;
|
|
|
|
var colFormat;
|
2010-09-19 07:54:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Rendering
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
disableTextSelection(element.addClass('fc-agenda'));
|
|
|
|
|
|
|
|
|
|
|
|
function renderAgenda(c) {
|
|
|
|
colCnt = c;
|
2011-01-24 08:10:25 +01:00
|
|
|
updateOptions();
|
|
|
|
if (!dayTable) {
|
|
|
|
buildSkeleton();
|
|
|
|
}else{
|
|
|
|
clearEvents();
|
|
|
|
}
|
|
|
|
updateCells();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function updateOptions() {
|
2010-09-19 07:54:35 +02:00
|
|
|
tm = opt('theme') ? 'ui' : 'fc';
|
|
|
|
nwe = opt('weekends') ? 0 : 1;
|
|
|
|
firstDay = opt('firstDay');
|
|
|
|
if (rtl = opt('isRTL')) {
|
|
|
|
dis = -1;
|
|
|
|
dit = colCnt - 1;
|
|
|
|
}else{
|
|
|
|
dis = 1;
|
|
|
|
dit = 0;
|
|
|
|
}
|
|
|
|
minMinute = parseTime(opt('minTime'));
|
|
|
|
maxMinute = parseTime(opt('maxTime'));
|
2011-01-24 08:10:25 +01:00
|
|
|
colFormat = opt('columnFormat');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function buildSkeleton() {
|
|
|
|
var headerClass = tm + "-widget-header";
|
|
|
|
var contentClass = tm + "-widget-content";
|
|
|
|
var s;
|
|
|
|
var i;
|
|
|
|
var d;
|
|
|
|
var maxd;
|
|
|
|
var minutes;
|
|
|
|
var slotNormal = opt('slotMinutes') % 15 == 0;
|
|
|
|
|
|
|
|
s =
|
|
|
|
"<table style='width:100%' class='fc-agenda-days fc-border-separate' cellspacing='0'>" +
|
|
|
|
"<thead>" +
|
|
|
|
"<tr>" +
|
|
|
|
"<th class='fc-agenda-axis " + headerClass + "'> </th>";
|
|
|
|
for (i=0; i<colCnt; i++) {
|
|
|
|
s +=
|
2011-03-20 02:48:20 +01:00
|
|
|
"<th class='fc- fc-col" + i + ' ' + headerClass + "'/>"; // fc- needed for setDayID
|
2011-01-24 08:10:25 +01:00
|
|
|
}
|
|
|
|
s +=
|
|
|
|
"<th class='fc-agenda-gutter " + headerClass + "'> </th>" +
|
|
|
|
"</tr>" +
|
|
|
|
"</thead>" +
|
|
|
|
"<tbody>" +
|
|
|
|
"<tr>" +
|
|
|
|
"<th class='fc-agenda-axis " + headerClass + "'> </th>";
|
|
|
|
for (i=0; i<colCnt; i++) {
|
|
|
|
s +=
|
2011-03-20 02:48:20 +01:00
|
|
|
"<td class='fc- fc-col" + i + ' ' + contentClass + "'>" + // fc- needed for setDayID
|
2011-01-24 08:10:25 +01:00
|
|
|
"<div>" +
|
|
|
|
"<div class='fc-day-content'>" +
|
|
|
|
"<div style='position:relative'> </div>" +
|
|
|
|
"</div>" +
|
|
|
|
"</div>" +
|
|
|
|
"</td>";
|
|
|
|
}
|
|
|
|
s +=
|
|
|
|
"<td class='fc-agenda-gutter " + contentClass + "'> </td>" +
|
|
|
|
"</tr>" +
|
|
|
|
"</tbody>" +
|
|
|
|
"</table>";
|
|
|
|
dayTable = $(s).appendTo(element);
|
|
|
|
dayHead = dayTable.find('thead');
|
|
|
|
dayHeadCells = dayHead.find('th').slice(1, -1);
|
|
|
|
dayBody = dayTable.find('tbody');
|
|
|
|
dayBodyCells = dayBody.find('td').slice(0, -1);
|
|
|
|
dayBodyCellInners = dayBodyCells.find('div.fc-day-content div');
|
|
|
|
dayBodyFirstCell = dayBodyCells.eq(0);
|
|
|
|
dayBodyFirstCellStretcher = dayBodyFirstCell.find('> div');
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
markFirstLast(dayHead.add(dayHead.find('tr')));
|
|
|
|
markFirstLast(dayBody.add(dayBody.find('tr')));
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
axisFirstCells = dayHead.find('th:first');
|
|
|
|
gutterCells = dayTable.find('.fc-agenda-gutter');
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
slotLayer =
|
|
|
|
$("<div style='position:absolute;z-index:2;left:0;width:100%'/>")
|
2010-09-19 07:54:35 +02:00
|
|
|
.appendTo(element);
|
2011-01-24 08:10:25 +01:00
|
|
|
|
|
|
|
if (opt('allDaySlot')) {
|
|
|
|
|
|
|
|
daySegmentContainer =
|
|
|
|
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
|
|
|
|
.appendTo(slotLayer);
|
|
|
|
|
|
|
|
s =
|
|
|
|
"<table style='width:100%' class='fc-agenda-allday' cellspacing='0'>" +
|
|
|
|
"<tr>" +
|
|
|
|
"<th class='" + headerClass + " fc-agenda-axis'>" + opt('allDayText') + "</th>" +
|
|
|
|
"<td>" +
|
|
|
|
"<div class='fc-day-content'><div style='position:relative'/></div>" +
|
|
|
|
"</td>" +
|
|
|
|
"<th class='" + headerClass + " fc-agenda-gutter'> </th>" +
|
|
|
|
"</tr>" +
|
|
|
|
"</table>";
|
|
|
|
allDayTable = $(s).appendTo(slotLayer);
|
|
|
|
allDayRow = allDayTable.find('tr');
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
dayBind(allDayRow.find('td'));
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
axisFirstCells = axisFirstCells.add(allDayTable.find('th:first'));
|
|
|
|
gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter'));
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
slotLayer.append(
|
|
|
|
"<div class='fc-agenda-divider " + headerClass + "'>" +
|
|
|
|
"<div class='fc-agenda-divider-inner'/>" +
|
|
|
|
"</div>"
|
|
|
|
);
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
}else{
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
daySegmentContainer = $([]); // in jQuery 1.4, we can just do $()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
slotScroller =
|
2011-02-01 22:09:32 +01:00
|
|
|
$("<div style='position:absolute;width:100%;overflow-x:hidden;overflow-y:auto'/>")
|
2011-01-24 08:10:25 +01:00
|
|
|
.appendTo(slotLayer);
|
|
|
|
|
|
|
|
slotContent =
|
|
|
|
$("<div style='position:relative;width:100%;overflow:hidden'/>")
|
|
|
|
.appendTo(slotScroller);
|
|
|
|
|
|
|
|
slotSegmentContainer =
|
|
|
|
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
|
|
|
|
.appendTo(slotContent);
|
|
|
|
|
|
|
|
s =
|
|
|
|
"<table class='fc-agenda-slots' style='width:100%' cellspacing='0'>" +
|
|
|
|
"<tbody>";
|
|
|
|
d = zeroDate();
|
|
|
|
maxd = addMinutes(cloneDate(d), maxMinute);
|
|
|
|
addMinutes(d, minMinute);
|
|
|
|
slotCnt = 0;
|
|
|
|
for (i=0; d < maxd; i++) {
|
|
|
|
minutes = d.getMinutes();
|
|
|
|
s +=
|
|
|
|
"<tr class='fc-slot" + i + ' ' + (!minutes ? '' : 'fc-minor') + "'>" +
|
|
|
|
"<th class='fc-agenda-axis " + headerClass + "'>" +
|
|
|
|
((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') +
|
|
|
|
"</th>" +
|
|
|
|
"<td class='" + contentClass + "'>" +
|
|
|
|
"<div style='position:relative'> </div>" +
|
|
|
|
"</td>" +
|
|
|
|
"</tr>";
|
|
|
|
addMinutes(d, opt('slotMinutes'));
|
|
|
|
slotCnt++;
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
2011-01-24 08:10:25 +01:00
|
|
|
s +=
|
|
|
|
"</tbody>" +
|
|
|
|
"</table>";
|
|
|
|
slotTable = $(s).appendTo(slotContent);
|
|
|
|
slotTableFirstInner = slotTable.find('div:first');
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
slotBind(slotTable.find('td'));
|
|
|
|
|
|
|
|
axisFirstCells = axisFirstCells.add(slotTable.find('th:first'));
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function updateCells() {
|
|
|
|
var i;
|
|
|
|
var headCell;
|
|
|
|
var bodyCell;
|
|
|
|
var date;
|
|
|
|
var today = clearTime(new Date());
|
|
|
|
for (i=0; i<colCnt; i++) {
|
|
|
|
date = colDate(i);
|
|
|
|
headCell = dayHeadCells.eq(i);
|
|
|
|
headCell.html(formatDate(date, colFormat));
|
|
|
|
bodyCell = dayBodyCells.eq(i);
|
|
|
|
if (+date == +today) {
|
|
|
|
bodyCell.addClass(tm + '-state-highlight fc-today');
|
|
|
|
}else{
|
|
|
|
bodyCell.removeClass(tm + '-state-highlight fc-today');
|
|
|
|
}
|
|
|
|
setDayID(headCell.add(bodyCell), date);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
|
|
|
|
function setHeight(height, dateChanged) {
|
2010-09-19 07:54:35 +02:00
|
|
|
if (height === undefined) {
|
|
|
|
height = viewHeight;
|
|
|
|
}
|
|
|
|
viewHeight = height;
|
|
|
|
slotTopCache = {};
|
2011-01-24 08:10:25 +01:00
|
|
|
|
|
|
|
var headHeight = dayBody.position().top;
|
|
|
|
var allDayHeight = slotScroller.position().top; // including divider
|
|
|
|
var bodyHeight = Math.min( // total body height, including borders
|
|
|
|
height - headHeight, // when scrollbars
|
|
|
|
slotTable.height() + allDayHeight + 1 // when no scrollbars. +1 for bottom border
|
|
|
|
);
|
|
|
|
|
|
|
|
dayBodyFirstCellStretcher
|
|
|
|
.height(bodyHeight - vsides(dayBodyFirstCell));
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
slotLayer.css('top', headHeight);
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
slotScroller.height(bodyHeight - allDayHeight - 1);
|
|
|
|
|
|
|
|
slotHeight = slotTableFirstInner.height() + 1; // +1 for border
|
2010-09-19 07:54:35 +02:00
|
|
|
|
|
|
|
if (dateChanged) {
|
|
|
|
resetScroll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function setWidth(width) {
|
|
|
|
viewWidth = width;
|
|
|
|
colContentPositions.clear();
|
|
|
|
|
|
|
|
axisWidth = 0;
|
|
|
|
setOuterWidth(
|
2011-01-24 08:10:25 +01:00
|
|
|
axisFirstCells
|
|
|
|
.width('')
|
|
|
|
.each(function(i, _cell) {
|
|
|
|
axisWidth = Math.max(axisWidth, $(_cell).outerWidth());
|
2010-09-19 07:54:35 +02:00
|
|
|
}),
|
|
|
|
axisWidth
|
|
|
|
);
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
var slotTableWidth = slotScroller[0].clientWidth; // needs to be done after axisWidth (for IE7)
|
|
|
|
//slotTable.width(slotTableWidth);
|
2010-09-27 02:45:34 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
gutterWidth = slotScroller.width() - slotTableWidth;
|
|
|
|
if (gutterWidth) {
|
|
|
|
setOuterWidth(gutterCells, gutterWidth);
|
|
|
|
gutterCells
|
|
|
|
.show()
|
|
|
|
.prev()
|
|
|
|
.removeClass('fc-last');
|
2010-09-27 02:45:34 +02:00
|
|
|
}else{
|
2011-01-24 08:10:25 +01:00
|
|
|
gutterCells
|
|
|
|
.hide()
|
|
|
|
.prev()
|
|
|
|
.addClass('fc-last');
|
2010-09-27 02:45:34 +02:00
|
|
|
}
|
2010-09-19 07:54:35 +02:00
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
colWidth = Math.floor((slotTableWidth - axisWidth) / colCnt);
|
|
|
|
setOuterWidth(dayHeadCells.slice(0, -1), colWidth);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
|
|
|
|
|
2010-09-19 07:54:35 +02:00
|
|
|
function resetScroll() {
|
2011-01-24 08:10:25 +01:00
|
|
|
var d0 = zeroDate();
|
|
|
|
var scrollDate = cloneDate(d0);
|
2010-09-19 07:54:35 +02:00
|
|
|
scrollDate.setHours(opt('firstHour'));
|
2011-01-24 08:10:25 +01:00
|
|
|
var top = timePosition(d0, scrollDate) + 1; // +1 for the border
|
|
|
|
function scroll() {
|
|
|
|
slotScroller.scrollTop(top);
|
|
|
|
}
|
2010-09-19 07:54:35 +02:00
|
|
|
scroll();
|
|
|
|
setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function beforeHide() {
|
2011-01-24 08:10:25 +01:00
|
|
|
savedScrollTop = slotScroller.scrollTop();
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function afterShow() {
|
2011-01-24 08:10:25 +01:00
|
|
|
slotScroller.scrollTop(savedScrollTop);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Slot/Day clicking and binding
|
|
|
|
-----------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function dayBind(cells) {
|
|
|
|
cells.click(slotClick)
|
2010-09-19 07:54:35 +02:00
|
|
|
.mousedown(daySelectionMousedown);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function slotBind(cells) {
|
|
|
|
cells.click(slotClick)
|
2010-09-19 07:54:35 +02:00
|
|
|
.mousedown(slotSelectionMousedown);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function slotClick(ev) {
|
2011-03-20 02:48:20 +01:00
|
|
|
if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
|
2011-01-24 08:10:25 +01:00
|
|
|
var col = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth));
|
|
|
|
var date = colDate(col);
|
|
|
|
var rowMatch = this.parentNode.className.match(/fc-slot(\d+)/); // TODO: maybe use data
|
2010-09-19 07:54:35 +02:00
|
|
|
if (rowMatch) {
|
2011-01-24 08:10:25 +01:00
|
|
|
var mins = parseInt(rowMatch[1]) * opt('slotMinutes');
|
|
|
|
var hours = Math.floor(mins/60);
|
2010-09-19 07:54:35 +02:00
|
|
|
date.setHours(hours);
|
|
|
|
date.setMinutes(mins%60 + minMinute);
|
2011-01-24 08:10:25 +01:00
|
|
|
trigger('dayClick', dayBodyCells[col], date, false, ev);
|
2010-09-19 07:54:35 +02:00
|
|
|
}else{
|
2011-01-24 08:10:25 +01:00
|
|
|
trigger('dayClick', dayBodyCells[col], date, true, ev);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Semi-transparent Overlay Helpers
|
|
|
|
-----------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
function renderDayOverlay(startDate, endDate, refreshCoordinateGrid) { // endDate is exclusive
|
|
|
|
if (refreshCoordinateGrid) {
|
|
|
|
coordinateGrid.build();
|
|
|
|
}
|
|
|
|
var visStart = cloneDate(t.visStart);
|
|
|
|
var startCol, endCol;
|
|
|
|
if (rtl) {
|
|
|
|
startCol = dayDiff(endDate, visStart)*dis+dit+1;
|
|
|
|
endCol = dayDiff(startDate, visStart)*dis+dit+1;
|
|
|
|
}else{
|
|
|
|
startCol = dayDiff(startDate, visStart);
|
|
|
|
endCol = dayDiff(endDate, visStart);
|
|
|
|
}
|
|
|
|
startCol = Math.max(0, startCol);
|
|
|
|
endCol = Math.min(colCnt, endCol);
|
|
|
|
if (startCol < endCol) {
|
|
|
|
dayBind(
|
|
|
|
renderCellOverlay(0, startCol, 0, endCol-1)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function renderCellOverlay(row0, col0, row1, col1) { // only for all-day?
|
|
|
|
var rect = coordinateGrid.rect(row0, col0, row1, col1, slotLayer);
|
|
|
|
return renderOverlay(rect, slotLayer);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderSlotOverlay(overlayStart, overlayEnd) {
|
|
|
|
var dayStart = cloneDate(t.visStart);
|
|
|
|
var dayEnd = addDays(cloneDate(dayStart), 1);
|
|
|
|
for (var i=0; i<colCnt; i++) {
|
|
|
|
var stretchStart = new Date(Math.max(dayStart, overlayStart));
|
|
|
|
var stretchEnd = new Date(Math.min(dayEnd, overlayEnd));
|
|
|
|
if (stretchStart < stretchEnd) {
|
|
|
|
var col = i*dis+dit;
|
2011-01-24 08:10:25 +01:00
|
|
|
var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only use it for horizontal coords
|
2010-09-19 07:54:35 +02:00
|
|
|
var top = timePosition(dayStart, stretchStart);
|
|
|
|
var bottom = timePosition(dayStart, stretchEnd);
|
|
|
|
rect.top = top;
|
|
|
|
rect.height = bottom - top;
|
|
|
|
slotBind(
|
2011-01-24 08:10:25 +01:00
|
|
|
renderOverlay(rect, slotContent)
|
2010-09-19 07:54:35 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
addDays(dayStart, 1);
|
|
|
|
addDays(dayEnd, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Coordinate Utilities
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
|
|
|
var e, n, p;
|
2011-01-24 08:10:25 +01:00
|
|
|
dayHeadCells.each(function(i, _e) {
|
2010-09-19 07:54:35 +02:00
|
|
|
e = $(_e);
|
|
|
|
n = e.offset().left;
|
|
|
|
if (i) {
|
|
|
|
p[1] = n;
|
|
|
|
}
|
|
|
|
p = [n];
|
|
|
|
cols[i] = p;
|
|
|
|
});
|
|
|
|
p[1] = n + e.outerWidth();
|
|
|
|
if (opt('allDaySlot')) {
|
2011-01-24 08:10:25 +01:00
|
|
|
e = allDayRow;
|
2010-09-19 07:54:35 +02:00
|
|
|
n = e.offset().top;
|
|
|
|
rows[0] = [n, n+e.outerHeight()];
|
|
|
|
}
|
2011-01-24 08:10:25 +01:00
|
|
|
var slotTableTop = slotContent.offset().top;
|
|
|
|
var slotScrollerTop = slotScroller.offset().top;
|
|
|
|
var slotScrollerBottom = slotScrollerTop + slotScroller.outerHeight();
|
2010-09-19 07:54:35 +02:00
|
|
|
function constrain(n) {
|
2011-01-24 08:10:25 +01:00
|
|
|
return Math.max(slotScrollerTop, Math.min(slotScrollerBottom, n));
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
for (var i=0; i<slotCnt; i++) {
|
|
|
|
rows.push([
|
2011-01-24 08:10:25 +01:00
|
|
|
constrain(slotTableTop + slotHeight*i),
|
|
|
|
constrain(slotTableTop + slotHeight*(i+1))
|
2010-09-19 07:54:35 +02:00
|
|
|
]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
hoverListener = new HoverListener(coordinateGrid);
|
|
|
|
|
|
|
|
|
|
|
|
colContentPositions = new HorizontalPositionCache(function(col) {
|
2011-01-24 08:10:25 +01:00
|
|
|
return dayBodyCellInners.eq(col);
|
2010-09-19 07:54:35 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function colContentLeft(col) {
|
2011-01-24 08:10:25 +01:00
|
|
|
return colContentPositions.left(col);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function colContentRight(col) {
|
2011-01-24 08:10:25 +01:00
|
|
|
return colContentPositions.right(col);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-10 07:54:41 +01:00
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function dateCell(date) { // "cell" terminology is now confusing
|
2010-11-10 07:54:41 +01:00
|
|
|
return {
|
|
|
|
row: Math.floor(dayDiff(date, t.visStart) / 7),
|
|
|
|
col: dayOfWeekCol(date.getDay())
|
|
|
|
};
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function cellDate(cell) {
|
|
|
|
var d = colDate(cell.col);
|
|
|
|
var slotIndex = cell.row;
|
|
|
|
if (opt('allDaySlot')) {
|
|
|
|
slotIndex--;
|
|
|
|
}
|
|
|
|
if (slotIndex >= 0) {
|
|
|
|
addMinutes(d, minMinute + slotIndex * opt('slotMinutes'));
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function colDate(col) { // returns dates with 00:00:00
|
|
|
|
return addDays(cloneDate(t.visStart), col*dis+dit);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function cellIsAllDay(cell) {
|
|
|
|
return opt('allDaySlot') && !cell.row;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function dayOfWeekCol(dayOfWeek) {
|
|
|
|
return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt)*dis+dit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-09-19 07:54:35 +02:00
|
|
|
// get the Y coordinate of the given time on the given day (both Date objects)
|
|
|
|
function timePosition(day, time) { // both date objects. day holds 00:00 of current day
|
|
|
|
day = cloneDate(day, true);
|
|
|
|
if (time < addMinutes(cloneDate(day), minMinute)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (time >= addMinutes(cloneDate(day), maxMinute)) {
|
2011-01-24 08:10:25 +01:00
|
|
|
return slotTable.height();
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
var slotMinutes = opt('slotMinutes'),
|
|
|
|
minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
|
|
|
slotI = Math.floor(minutes / slotMinutes),
|
|
|
|
slotTop = slotTopCache[slotI];
|
|
|
|
if (slotTop === undefined) {
|
2011-01-24 08:10:25 +01:00
|
|
|
slotTop = slotTopCache[slotI] = slotTable.find('tr:eq(' + slotI + ') td div')[0].offsetTop; //.position().top; // need this optimization???
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
return Math.max(0, Math.round(
|
|
|
|
slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function allDayBounds() {
|
|
|
|
return {
|
|
|
|
left: axisWidth,
|
2011-01-24 08:10:25 +01:00
|
|
|
right: viewWidth - gutterWidth
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function getAllDayRow(index) {
|
|
|
|
return allDayRow;
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function defaultEventEnd(event) {
|
|
|
|
var start = cloneDate(event.start);
|
|
|
|
if (event.allDay) {
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
return addMinutes(start, opt('defaultEventMinutes'));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Selection
|
|
|
|
---------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
function defaultSelectionEnd(startDate, allDay) {
|
|
|
|
if (allDay) {
|
|
|
|
return cloneDate(startDate);
|
|
|
|
}
|
|
|
|
return addMinutes(cloneDate(startDate), opt('slotMinutes'));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function renderSelection(startDate, endDate, allDay) { // only for all-day
|
2010-09-19 07:54:35 +02:00
|
|
|
if (allDay) {
|
|
|
|
if (opt('allDaySlot')) {
|
|
|
|
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true);
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
renderSlotSelection(startDate, endDate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderSlotSelection(startDate, endDate) {
|
|
|
|
var helperOption = opt('selectHelper');
|
|
|
|
coordinateGrid.build();
|
|
|
|
if (helperOption) {
|
|
|
|
var col = dayDiff(startDate, t.visStart) * dis + dit;
|
|
|
|
if (col >= 0 && col < colCnt) { // only works when times are on same day
|
2011-01-24 08:10:25 +01:00
|
|
|
var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only for horizontal coords
|
2010-09-19 07:54:35 +02:00
|
|
|
var top = timePosition(startDate, startDate);
|
|
|
|
var bottom = timePosition(startDate, endDate);
|
|
|
|
if (bottom > top) { // protect against selections that are entirely before or after visible range
|
|
|
|
rect.top = top;
|
|
|
|
rect.height = bottom - top;
|
|
|
|
rect.left += 2;
|
|
|
|
rect.width -= 5;
|
|
|
|
if ($.isFunction(helperOption)) {
|
|
|
|
var helperRes = helperOption(startDate, endDate);
|
|
|
|
if (helperRes) {
|
|
|
|
rect.position = 'absolute';
|
|
|
|
rect.zIndex = 8;
|
|
|
|
selectionHelper = $(helperRes)
|
|
|
|
.css(rect)
|
2011-01-24 08:10:25 +01:00
|
|
|
.appendTo(slotContent);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
}else{
|
2011-02-20 00:47:23 +01:00
|
|
|
rect.isStart = true; // conside rect a "seg" now
|
|
|
|
rect.isEnd = true; //
|
2010-09-19 07:54:35 +02:00
|
|
|
selectionHelper = $(slotSegHtml(
|
|
|
|
{
|
|
|
|
title: '',
|
|
|
|
start: startDate,
|
|
|
|
end: endDate,
|
2011-03-20 02:48:20 +01:00
|
|
|
className: ['fc-select-helper'],
|
|
|
|
editable: false
|
2010-09-19 07:54:35 +02:00
|
|
|
},
|
2011-02-20 00:47:23 +01:00
|
|
|
rect
|
2010-09-19 07:54:35 +02:00
|
|
|
));
|
|
|
|
selectionHelper.css('opacity', opt('dragOpacity'));
|
|
|
|
}
|
|
|
|
if (selectionHelper) {
|
|
|
|
slotBind(selectionHelper);
|
2011-01-24 08:10:25 +01:00
|
|
|
slotContent.append(selectionHelper);
|
2010-09-19 07:54:35 +02:00
|
|
|
setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended
|
|
|
|
setOuterHeight(selectionHelper, rect.height, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
renderSlotOverlay(startDate, endDate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function clearSelection() {
|
|
|
|
clearOverlays();
|
|
|
|
if (selectionHelper) {
|
|
|
|
selectionHelper.remove();
|
|
|
|
selectionHelper = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function slotSelectionMousedown(ev) {
|
2010-10-13 06:13:21 +02:00
|
|
|
if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button
|
2010-09-19 07:54:35 +02:00
|
|
|
unselect(ev);
|
|
|
|
var dates;
|
|
|
|
hoverListener.start(function(cell, origCell) {
|
|
|
|
clearSelection();
|
|
|
|
if (cell && cell.col == origCell.col && !cellIsAllDay(cell)) {
|
|
|
|
var d1 = cellDate(origCell);
|
|
|
|
var d2 = cellDate(cell);
|
|
|
|
dates = [
|
|
|
|
d1,
|
|
|
|
addMinutes(cloneDate(d1), opt('slotMinutes')),
|
|
|
|
d2,
|
|
|
|
addMinutes(cloneDate(d2), opt('slotMinutes'))
|
|
|
|
].sort(cmp);
|
|
|
|
renderSlotSelection(dates[0], dates[3]);
|
|
|
|
}else{
|
|
|
|
dates = null;
|
|
|
|
}
|
|
|
|
}, ev);
|
|
|
|
$(document).one('mouseup', function(ev) {
|
|
|
|
hoverListener.stop();
|
|
|
|
if (dates) {
|
|
|
|
if (+dates[0] == +dates[1]) {
|
2011-01-24 08:10:25 +01:00
|
|
|
reportDayClick(dates[0], false, ev);
|
2010-09-19 07:54:35 +02:00
|
|
|
}
|
|
|
|
reportSelection(dates[0], dates[3], false, ev);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 08:10:25 +01:00
|
|
|
function reportDayClick(date, allDay, ev) {
|
|
|
|
trigger('dayClick', dayBodyCells[dayOfWeekCol(date.getDay())], date, allDay, ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-19 07:54:35 +02:00
|
|
|
|
|
|
|
/* External Dragging
|
|
|
|
--------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
function dragStart(_dragElement, ev, ui) {
|
|
|
|
hoverListener.start(function(cell) {
|
|
|
|
clearOverlays();
|
|
|
|
if (cell) {
|
|
|
|
if (cellIsAllDay(cell)) {
|
|
|
|
renderCellOverlay(cell.row, cell.col, cell.row, cell.col);
|
|
|
|
}else{
|
|
|
|
var d1 = cellDate(cell);
|
|
|
|
var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes'));
|
|
|
|
renderSlotOverlay(d1, d2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function dragStop(_dragElement, ev, ui) {
|
|
|
|
var cell = hoverListener.stop();
|
|
|
|
clearOverlays();
|
|
|
|
if (cell) {
|
|
|
|
trigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|