final round of optimizations for event rendering. fixed some new bugs
This commit is contained in:
parent
1fbb7f64cd
commit
0e3e04bbdf
9 changed files with 274 additions and 200 deletions
177
src/agenda.js
177
src/agenda.js
|
@ -89,6 +89,7 @@ function Agenda(element, options, methods) {
|
||||||
colContentPositions = new HorizontalPositionCache(function(col) {
|
colContentPositions = new HorizontalPositionCache(function(col) {
|
||||||
return bg.find('td:eq(' + col + ') div div');
|
return bg.find('td:eq(' + col + ') div div');
|
||||||
}),
|
}),
|
||||||
|
slotTopCache = {},
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
view = $.extend(this, viewMethods, methods, {
|
view = $.extend(this, viewMethods, methods, {
|
||||||
|
@ -167,7 +168,7 @@ function Agenda(element, options, methods) {
|
||||||
s += "<tr class='fc-all-day'>" +
|
s += "<tr class='fc-all-day'>" +
|
||||||
"<th class='fc-axis fc-leftmost " + tm + "-state-default'>" + options.allDayText + "</th>" +
|
"<th class='fc-axis fc-leftmost " + tm + "-state-default'>" + options.allDayText + "</th>" +
|
||||||
"<td colspan='" + colCnt + "' class='" + tm + "-state-default'>" +
|
"<td colspan='" + colCnt + "' class='" + tm + "-state-default'>" +
|
||||||
"<div class='fc-day-content'><div> </div></div></td>" +
|
"<div class='fc-day-content'><div style='position:relative'> </div></div></td>" +
|
||||||
"<th class='" + tm + "-state-default'> </th>" +
|
"<th class='" + tm + "-state-default'> </th>" +
|
||||||
"</tr><tr class='fc-divider fc-last'><th colspan='" + (colCnt+2) + "' class='" +
|
"</tr><tr class='fc-divider fc-last'><th colspan='" + (colCnt+2) + "' class='" +
|
||||||
tm + "-state-default fc-leftmost'><div/></th></tr>";
|
tm + "-state-default fc-leftmost'><div/></th></tr>";
|
||||||
|
@ -177,7 +178,7 @@ function Agenda(element, options, methods) {
|
||||||
head.find('td').click(slotClick);
|
head.find('td').click(slotClick);
|
||||||
|
|
||||||
// all-day event container
|
// all-day event container
|
||||||
daySegmentContainer = $("<div/>").appendTo(head);
|
daySegmentContainer = $("<div style='position:absolute;top:0;left:0'/>").appendTo(head);
|
||||||
|
|
||||||
// body
|
// body
|
||||||
d = zeroDate();
|
d = zeroDate();
|
||||||
|
@ -191,7 +192,7 @@ function Agenda(element, options, methods) {
|
||||||
"'><th class='fc-axis fc-leftmost " + tm + "-state-default'>" +
|
"'><th class='fc-axis fc-leftmost " + tm + "-state-default'>" +
|
||||||
((!slotNormal || minutes==0) ? formatDate(d, options.axisFormat) : ' ') +
|
((!slotNormal || minutes==0) ? formatDate(d, options.axisFormat) : ' ') +
|
||||||
"</th><td class='fc-slot" + i + ' ' +
|
"</th><td class='fc-slot" + i + ' ' +
|
||||||
tm + "-state-default'><div> </div></td></tr>";
|
tm + "-state-default'><div style='position:relative'> </div></td></tr>";
|
||||||
addMinutes(d, options.slotMinutes);
|
addMinutes(d, options.slotMinutes);
|
||||||
}
|
}
|
||||||
s += "</table>";
|
s += "</table>";
|
||||||
|
@ -287,6 +288,7 @@ function Agenda(element, options, methods) {
|
||||||
viewWidth = width;
|
viewWidth = width;
|
||||||
viewHeight = height;
|
viewHeight = height;
|
||||||
colContentPositions.clear();
|
colContentPositions.clear();
|
||||||
|
slotTopCache = {};
|
||||||
|
|
||||||
body.width(width);
|
body.width(width);
|
||||||
body.height(height - head.height());
|
body.height(height - head.height());
|
||||||
|
@ -357,7 +359,7 @@ function Agenda(element, options, methods) {
|
||||||
slotEvents.push(events[i]);
|
slotEvents.push(events[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderDaySegs(stackSegs(view.sliceSegs(dayEvents, $.map(dayEvents, visEventEnd), view.visStart, view.visEnd)));
|
renderDaySegs(compileDaySegs(dayEvents));
|
||||||
renderSlotSegs(compileSlotSegs(slotEvents));
|
renderSlotSegs(compileSlotSegs(slotEvents));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,19 +377,49 @@ function Agenda(element, options, methods) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function compileDaySegs(events) {
|
||||||
|
var levels = stackSegs(view.sliceSegs(events, $.map(events, visEventEnd), view.visStart, view.visEnd)),
|
||||||
|
i, levelCnt=levels.length, level,
|
||||||
|
j, seg,
|
||||||
|
segs=[];
|
||||||
|
for (i=0; i<levelCnt; i++) {
|
||||||
|
level = levels[i];
|
||||||
|
for (j=0; j<level.length; j++) {
|
||||||
|
seg = level[j];
|
||||||
|
seg.row = 0;
|
||||||
|
seg.level = i;
|
||||||
|
segs.push(seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function compileSlotSegs(events) {
|
function compileSlotSegs(events) {
|
||||||
var d = addMinutes(cloneDate(view.visStart), minMinute),
|
var d = addMinutes(cloneDate(view.visStart), minMinute),
|
||||||
ends = $.map(events, visEventEnd),
|
visEventEnds = $.map(events, visEventEnd),
|
||||||
levels,
|
i, col,
|
||||||
segCols = [],
|
j, level,
|
||||||
i=0;
|
k, seg,
|
||||||
for (; i<colCnt; i++) {
|
segs=[];
|
||||||
levels = stackSegs(view.sliceSegs(events, ends, d, addMinutes(cloneDate(d), maxMinute-minMinute)));
|
for (i=0; i<colCnt; i++) {
|
||||||
countForwardSegs(levels);
|
col = stackSegs(view.sliceSegs(events, visEventEnds, d, addMinutes(cloneDate(d), maxMinute-minMinute)));
|
||||||
segCols.push(levels);
|
countForwardSegs(col);
|
||||||
|
for (j=0; j<col.length; j++) {
|
||||||
|
level = col[j];
|
||||||
|
for (k=0; k<level.length; k++) {
|
||||||
|
seg = level[k];
|
||||||
|
seg.col = i;
|
||||||
|
seg.level = j;
|
||||||
|
segs.push(seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
addDays(d, 1, true);
|
addDays(d, 1, true);
|
||||||
}
|
}
|
||||||
return segCols;
|
return segs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -395,10 +427,11 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
// renders 'all-day' events at the top
|
// renders 'all-day' events at the top
|
||||||
|
|
||||||
function renderDaySegs(segRow) {
|
function renderDaySegs(segs) {
|
||||||
if (options.allDaySlot) {
|
if (options.allDaySlot) {
|
||||||
_renderDaySegs(
|
_renderDaySegs(
|
||||||
[segRow],
|
segs,
|
||||||
|
1,
|
||||||
view,
|
view,
|
||||||
axisWidth,
|
axisWidth,
|
||||||
viewWidth,
|
viewWidth,
|
||||||
|
@ -422,32 +455,30 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
// renders events in the 'time slots' at the bottom
|
// renders events in the 'time slots' at the bottom
|
||||||
|
|
||||||
function renderSlotSegs(segCols) {
|
function renderSlotSegs(segs) {
|
||||||
|
|
||||||
var event,
|
var i, segCnt=segs.length, seg,
|
||||||
|
event,
|
||||||
className,
|
className,
|
||||||
top,
|
top, bottom,
|
||||||
bottom,
|
colI, levelI, forward,
|
||||||
leftmost,
|
leftmost,
|
||||||
availWidth,
|
availWidth,
|
||||||
forward,
|
outerWidth,
|
||||||
width,
|
|
||||||
left,
|
left,
|
||||||
eventTops=[],
|
|
||||||
eventLefts=[],
|
|
||||||
eventOuterWidths=[],
|
|
||||||
eventOuterHeights=[],
|
|
||||||
html='',
|
html='',
|
||||||
eventElements,
|
_eventElements,
|
||||||
eventElement,
|
eventElement,
|
||||||
triggerRes,
|
triggerRes,
|
||||||
eventVSides=[],
|
vsideCache={},
|
||||||
eventHSides=[],
|
hsideCache={},
|
||||||
eventTitlePositions=[],
|
key, val,
|
||||||
|
titleSpan,
|
||||||
height;
|
height;
|
||||||
|
|
||||||
// calculate desired position/dimensions, create html
|
// calculate position/dimensions, create html
|
||||||
eachLeaf(segCols, function(l, seg, segI, levelI, colI) {
|
for (i=0; i<segCnt; i++) {
|
||||||
|
seg = segs[i];
|
||||||
event = seg.event;
|
event = seg.event;
|
||||||
className = 'fc-event fc-event-vert ';
|
className = 'fc-event fc-event-vert ';
|
||||||
if (seg.isStart) {
|
if (seg.isStart) {
|
||||||
|
@ -458,48 +489,51 @@ function Agenda(element, options, methods) {
|
||||||
}
|
}
|
||||||
top = timePosition(seg.start, seg.start);
|
top = timePosition(seg.start, seg.start);
|
||||||
bottom = timePosition(seg.start, seg.end);
|
bottom = timePosition(seg.start, seg.end);
|
||||||
|
colI = seg.col;
|
||||||
|
levelI = seg.level;
|
||||||
|
forward = seg.forward || 0;
|
||||||
leftmost = axisWidth + colContentPositions.left(colI*dis + dit);
|
leftmost = axisWidth + colContentPositions.left(colI*dis + dit);
|
||||||
availWidth = axisWidth + colContentPositions.right(colI*dis + dit) - leftmost;
|
availWidth = axisWidth + colContentPositions.right(colI*dis + dit) - leftmost;
|
||||||
availWidth = Math.min(availWidth-6, availWidth*.95); // TODO: move this to CSS
|
availWidth = Math.min(availWidth-6, availWidth*.95); // TODO: move this to CSS
|
||||||
forward = seg.forward || 0;
|
|
||||||
if (levelI) {
|
if (levelI) {
|
||||||
// indented and thin
|
// indented and thin
|
||||||
width = availWidth / (levelI + forward + 1);
|
outerWidth = availWidth / (levelI + forward + 1);
|
||||||
}else{
|
}else{
|
||||||
if (forward) {
|
if (forward) {
|
||||||
// moderately wide, aligned left still
|
// moderately wide, aligned left still
|
||||||
width = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
outerWidth = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
||||||
}else{
|
}else{
|
||||||
// can be entire width, aligned left
|
// can be entire width, aligned left
|
||||||
width = availWidth;
|
outerWidth = availWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
left = leftmost + // leftmost possible
|
left = leftmost + // leftmost possible
|
||||||
(availWidth / (levelI + forward + 1) * levelI) // indentation
|
(availWidth / (levelI + forward + 1) * levelI) // indentation
|
||||||
* dis + (rtl ? availWidth - width : 0); // rtl
|
* dis + (rtl ? availWidth - outerWidth : 0); // rtl
|
||||||
eventTops[l] = top;
|
seg.top = top;
|
||||||
eventLefts[l] = left;
|
seg.left = left;
|
||||||
eventOuterWidths[l] = width;
|
seg.outerWidth = outerWidth;
|
||||||
eventOuterHeights[l] = bottom - top;
|
seg.outerHeight = bottom - top;
|
||||||
html +=
|
html +=
|
||||||
"<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;top:" + top + "px;left:" + left + "px'>" +
|
"<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;top:" + top + "px;left:" + left + "px'>" +
|
||||||
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
||||||
|
"<span class='fc-event-bg'></span>" +
|
||||||
"<span class='fc-event-time'>" + htmlEscape(formatDates(event.start, event.end, view.option('timeFormat'))) + "</span>" +
|
"<span class='fc-event-time'>" + htmlEscape(formatDates(event.start, event.end, view.option('timeFormat'))) + "</span>" +
|
||||||
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
||||||
"<span class='fc-event-bg'/>" +
|
|
||||||
"</a>" +
|
"</a>" +
|
||||||
((event.editable || event.editable == undefined && options.editable) && !options.disableResizing && $.fn.resizable ?
|
((event.editable || event.editable == undefined && options.editable) && !options.disableResizing && $.fn.resizable ?
|
||||||
"<div class='ui-resizable-handle ui-resizable-s'>=</div>"
|
"<div class='ui-resizable-handle ui-resizable-s'>=</div>"
|
||||||
: '') +
|
: '') +
|
||||||
"</div>";
|
"</div>";
|
||||||
});
|
}
|
||||||
slotSegmentContainer.html(html);
|
slotSegmentContainer[0].innerHTML = html;
|
||||||
eventElements = slotSegmentContainer.children();
|
_eventElements = $.makeArray(slotSegmentContainer[0].childNodes); // TODO: look at .children() again
|
||||||
|
|
||||||
// retrieve elements, run through eventRender callback, record outer-edge dimensions
|
// retrieve elements, run through eventRender callback, bind event handlers
|
||||||
eachLeaf(segCols, function(l, seg) {
|
for (i=0; i<segCnt; i++) {
|
||||||
|
seg = segs[i];
|
||||||
event = seg.event;
|
event = seg.event;
|
||||||
eventElement = eventElements.eq(l);
|
eventElement = $(_eventElements[i]);
|
||||||
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
||||||
if (triggerRes === false) {
|
if (triggerRes === false) {
|
||||||
eventElement.remove();
|
eventElement.remove();
|
||||||
|
@ -509,28 +543,40 @@ function Agenda(element, options, methods) {
|
||||||
eventElement = $(triggerRes)
|
eventElement = $(triggerRes)
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: eventTops[l],
|
top: seg.top,
|
||||||
left: eventLefts[l]
|
left: seg.left
|
||||||
})
|
})
|
||||||
.appendTo(slotSegmentContainer);
|
.appendTo(slotSegmentContainer);
|
||||||
}
|
}
|
||||||
seg.element = eventElement;
|
seg.element = eventElement;
|
||||||
eventVSides[l] = vsides(eventElement, true);
|
|
||||||
eventHSides[l] = hsides(eventElement, true);
|
|
||||||
eventTitlePositions[l] = eventElement.find('span.fc-event-title').position();
|
|
||||||
bootstrapSlotEventHandlers(event, seg, eventElement);
|
bootstrapSlotEventHandlers(event, seg, eventElement);
|
||||||
view.reportEventElement(event, eventElement);
|
view.reportEventElement(event, eventElement);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// record event sides and title positions
|
||||||
|
for (i=0; i<segCnt; i++) {
|
||||||
|
seg = segs[i];
|
||||||
|
if (eventElement = seg.element) {
|
||||||
|
val = vsideCache[key = seg.key = cssKey(eventElement[0])];
|
||||||
|
seg.vsides = val == undefined ? (vsideCache[key] = vsides(eventElement[0], true)) : val;
|
||||||
|
val = hsideCache[key];
|
||||||
|
seg.hsides = val == undefined ? (hsideCache[key] = hsides(eventElement[0], true)) : val;
|
||||||
|
titleSpan = eventElement.find('span.fc-event-title');
|
||||||
|
if (titleSpan.length) {
|
||||||
|
seg.titleTop = titleSpan[0].offsetTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set all positions/dimensions at once
|
// set all positions/dimensions at once
|
||||||
eachLeaf(segCols, function(l, seg) {
|
for (i=0; i<segCnt; i++) {
|
||||||
|
seg = segs[i];
|
||||||
if (eventElement = seg.element) {
|
if (eventElement = seg.element) {
|
||||||
eventElement
|
eventElement[0].style.width = seg.outerWidth - seg.hsides + 'px';
|
||||||
.width(eventOuterWidths[l] - eventHSides[l])
|
eventElement[0].style.height = (height = seg.outerHeight - seg.vsides) + 'px';
|
||||||
.height(height = eventOuterHeights[l] - eventVSides[l]);
|
|
||||||
event = seg.event;
|
event = seg.event;
|
||||||
if (eventTitlePositions[l] && height - eventTitlePositions[l].top < 10) {
|
if (seg.titleTop != undefined && height - seg.titleTop < 10) {
|
||||||
// not enough room for title, put it in the time header
|
// not enough room for title, put it in the time header
|
||||||
eventElement.find('span.fc-event-time')
|
eventElement.find('span.fc-event-time')
|
||||||
.text(formatDate(event.start, view.option('timeFormat')) + ' - ' + event.title);
|
.text(formatDate(event.start, view.option('timeFormat')) + ' - ' + event.title);
|
||||||
|
@ -539,7 +585,7 @@ function Agenda(element, options, methods) {
|
||||||
}
|
}
|
||||||
view.trigger('eventAfterRender', event, event, eventElement);
|
view.trigger('eventAfterRender', event, event, eventElement);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,7 +920,7 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
// get the Y coordinate of the given time on the given day (both Date objects)
|
// get the Y coordinate of the given time on the given day (both Date objects)
|
||||||
|
|
||||||
function timePosition(day, time) { // both date object. day holds 00:00 of current day
|
function timePosition(day, time) { // both date objects. day holds 00:00 of current day
|
||||||
day = cloneDate(day, true);
|
day = cloneDate(day, true);
|
||||||
if (time < addMinutes(cloneDate(day), minMinute)) {
|
if (time < addMinutes(cloneDate(day), minMinute)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -885,15 +931,18 @@ function Agenda(element, options, methods) {
|
||||||
var slotMinutes = options.slotMinutes,
|
var slotMinutes = options.slotMinutes,
|
||||||
minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
||||||
slotI = Math.floor(minutes / slotMinutes),
|
slotI = Math.floor(minutes / slotMinutes),
|
||||||
td = body.find('tr:eq(' + slotI + ') td'),
|
slotTop = slotTopCache[slotI];
|
||||||
innerDiv = td.find('div');
|
if (slotTop == undefined) {
|
||||||
|
slotTop = slotTopCache[slotI] = body.find('tr:eq(' + slotI + ') td div')[0].offsetTop;
|
||||||
|
}
|
||||||
return Math.max(0, Math.round(
|
return Math.max(0, Math.round(
|
||||||
innerDiv.position().top + topCorrect(td) - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function day2col(dayOfWeek) {
|
function day2col(dayOfWeek) {
|
||||||
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
||||||
}
|
}
|
||||||
|
|
200
src/grid.js
200
src/grid.js
|
@ -205,7 +205,7 @@ function Grid(element, options, methods) {
|
||||||
' fc-today '+tm+'-state-highlight' :
|
' fc-today '+tm+'-state-highlight' :
|
||||||
' fc-not-today') + "'>" +
|
' fc-not-today') + "'>" +
|
||||||
(showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') +
|
(showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') +
|
||||||
"<div class='fc-day-content'><div> </div></div></td>";
|
"<div class='fc-day-content'><div style='position:relative'> </div></div></td>";
|
||||||
addDays(d, 1);
|
addDays(d, 1);
|
||||||
if (nwe) {
|
if (nwe) {
|
||||||
skipWeekend(d);
|
skipWeekend(d);
|
||||||
|
@ -216,7 +216,7 @@ function Grid(element, options, methods) {
|
||||||
tbody = $(s + "</tbody>").appendTo(table);
|
tbody = $(s + "</tbody>").appendTo(table);
|
||||||
tbody.find('td').click(dayClick);
|
tbody.find('td').click(dayClick);
|
||||||
|
|
||||||
segmentContainer = $("<div/>").appendTo(element);
|
segmentContainer = $("<div/>").appendTo(element); // style='position:absolute;top:0;left:0' // made it a little slower for some reason
|
||||||
|
|
||||||
}else{ // NOT first time, reuse as many cells as possible
|
}else{ // NOT first time, reuse as many cells as possible
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ function Grid(element, options, methods) {
|
||||||
tm + '-state-default fc-new fc-day' + (i*colCnt+j) +
|
tm + '-state-default fc-new fc-day' + (i*colCnt+j) +
|
||||||
(j==dit ? ' fc-leftmost' : '') + "'>" +
|
(j==dit ? ' fc-leftmost' : '') + "'>" +
|
||||||
(showNumbers ? "<div class='fc-day-number'></div>" : '') +
|
(showNumbers ? "<div class='fc-day-number'></div>" : '') +
|
||||||
"<div class='fc-day-content'><div> </div></div>" +
|
"<div class='fc-day-content'><div style='position:relative'> </div></div>" +
|
||||||
"</td>";
|
"</td>";
|
||||||
addDays(d, 1);
|
addDays(d, 1);
|
||||||
if (nwe) {
|
if (nwe) {
|
||||||
|
@ -385,31 +385,42 @@ function Grid(element, options, methods) {
|
||||||
function compileSegs(events) {
|
function compileSegs(events) {
|
||||||
var d1 = cloneDate(view.visStart),
|
var d1 = cloneDate(view.visStart),
|
||||||
d2 = addDays(cloneDate(d1), colCnt),
|
d2 = addDays(cloneDate(d1), colCnt),
|
||||||
rows = [],
|
visEventsEnds = $.map(events, visEventEnd),
|
||||||
i=0;
|
i, row,
|
||||||
for (; i<rowCnt; i++) {
|
j, level,
|
||||||
rows.push(stackSegs(view.sliceSegs(events, $.map(events, visEventEnd), d1, d2)));
|
k, seg,
|
||||||
|
segs=[];
|
||||||
|
for (i=0; i<rowCnt; i++) {
|
||||||
|
row = stackSegs(view.sliceSegs(events, visEventsEnds, d1, d2));
|
||||||
|
for (j=0; j<row.length; j++) {
|
||||||
|
level = row[j];
|
||||||
|
for (k=0; k<level.length; k++) {
|
||||||
|
seg = level[k];
|
||||||
|
seg.row = i;
|
||||||
|
seg.level = j;
|
||||||
|
segs.push(seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
addDays(d1, 7);
|
addDays(d1, 7);
|
||||||
addDays(d2, 7);
|
addDays(d2, 7);
|
||||||
}
|
}
|
||||||
return rows;
|
return segs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function renderSegs(segCols) {
|
function renderSegs(segs) {
|
||||||
_renderDaySegs(
|
_renderDaySegs(
|
||||||
segCols,
|
segs,
|
||||||
|
rowCnt,
|
||||||
view,
|
view,
|
||||||
0,
|
0,
|
||||||
viewWidth,
|
viewWidth,
|
||||||
function(i) {
|
function(i) { return tbody.find('tr:eq('+i+')') },
|
||||||
return tbody.find('tr:eq('+i+')');
|
|
||||||
},
|
|
||||||
dayContentPositions.left,
|
dayContentPositions.left,
|
||||||
dayContentPositions.right,
|
dayContentPositions.right,
|
||||||
segmentContainer,
|
segmentContainer,
|
||||||
bootstrapEventHandlers
|
mouseoverBind
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,11 +437,12 @@ function Grid(element, options, methods) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function bootstrapEventHandlers(event, seg, eventElement) {
|
|
||||||
|
function mouseoverBind(event, seg, eventElement) {
|
||||||
function mouseover(ev) {
|
function mouseover(ev) {
|
||||||
view.trigger('eventMouseover', this, event, ev);
|
|
||||||
eventElement.unbind('mouseover', mouseover);
|
eventElement.unbind('mouseover', mouseover);
|
||||||
setTimeout(function() { // because IE will immediately trigger eventElementHandlers's mouseover
|
view.trigger('eventMouseover', this, event, ev);
|
||||||
|
setTimeout(function() { // because IE will immediately trigger the new mouseover handlers
|
||||||
view.eventElementHandlers(event, eventElement);
|
view.eventElementHandlers(event, eventElement);
|
||||||
if (event.editable || event.editable == undefined && options.editable) {
|
if (event.editable || event.editable == undefined && options.editable) {
|
||||||
draggableEvent(event, eventElement);
|
draggableEvent(event, eventElement);
|
||||||
|
@ -507,34 +519,28 @@ function Grid(element, options, methods) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function _renderDaySegs(segRows, view, minLeft, maxLeft, getTr, dayContentLeft, dayContentRight, segmentContainer, bootstrapEventHandlers) {
|
function _renderDaySegs(segs, rowCnt, view, minLeft, maxLeft, getRow, dayContentLeft, dayContentRight, segmentContainer, mouseoverBind) {
|
||||||
|
|
||||||
var options=view.options,
|
var options=view.options,
|
||||||
rtl=options.isRTL,
|
rtl=options.isRTL,
|
||||||
|
i, segCnt=segs.length, seg,
|
||||||
event,
|
event,
|
||||||
className,
|
className,
|
||||||
left,
|
left, right,
|
||||||
right,
|
|
||||||
eventLefts=[],
|
|
||||||
eventRights=[],
|
|
||||||
html='',
|
html='',
|
||||||
eventElements,
|
_eventElements,
|
||||||
eventElement,
|
eventElement,
|
||||||
triggerRes,
|
triggerRes,
|
||||||
eventOuterHeights=[],
|
hsideCache={},
|
||||||
eventHSides=[],
|
vmarginCache={},
|
||||||
l=0,
|
key, val,
|
||||||
i=0, len=segRows.length, levels,
|
rowI, top, levelI, levelHeight,
|
||||||
td,
|
rowDivs=[],
|
||||||
innerDiv,
|
rowDivTops=[];
|
||||||
top,
|
|
||||||
rowContentHeight,
|
|
||||||
j, segs,
|
|
||||||
levelHeight,
|
|
||||||
k, seg;
|
|
||||||
|
|
||||||
// calculate desired position/dimensions, create html
|
// calculate desired position/dimensions, create html
|
||||||
eachLeaf(segRows, function(l, seg) {
|
for (i=0; i<segCnt; i++) {
|
||||||
|
seg = segs[i];
|
||||||
event = seg.event;
|
event = seg.event;
|
||||||
className = 'fc-event fc-event-hori ';
|
className = 'fc-event fc-event-hori ';
|
||||||
if (rtl) {
|
if (rtl) {
|
||||||
|
@ -556,8 +562,6 @@ function _renderDaySegs(segRows, view, minLeft, maxLeft, getTr, dayContentLeft,
|
||||||
left = seg.isStart ? dayContentLeft(seg.start.getDay()) : minLeft;
|
left = seg.isStart ? dayContentLeft(seg.start.getDay()) : minLeft;
|
||||||
right = seg.isEnd ? dayContentRight(seg.end.getDay()-1) : maxLeft;
|
right = seg.isEnd ? dayContentRight(seg.end.getDay()-1) : maxLeft;
|
||||||
}
|
}
|
||||||
eventLefts[l] = left;
|
|
||||||
eventRights[l] = right;
|
|
||||||
html +=
|
html +=
|
||||||
"<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;left:"+left+"px'>" +
|
"<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;left:"+left+"px'>" +
|
||||||
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
||||||
|
@ -569,14 +573,17 @@ function _renderDaySegs(segRows, view, minLeft, maxLeft, getTr, dayContentLeft,
|
||||||
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
||||||
"</a>" +
|
"</a>" +
|
||||||
"</div>";
|
"</div>";
|
||||||
});
|
seg.left = left;
|
||||||
segmentContainer.html(html);
|
seg.outerWidth = right - left;
|
||||||
eventElements = segmentContainer.children();
|
}
|
||||||
|
segmentContainer[0].innerHTML = html;
|
||||||
|
_eventElements = $.makeArray(segmentContainer[0].childNodes); // TODO: look at .children() again
|
||||||
|
|
||||||
// retrieve elements, run through eventRender callback, record outer-edge dimensions
|
// retrieve elements, run through eventRender callback, bind handlers
|
||||||
eachLeaf(segRows, function(l, seg) {
|
for (i=0; i<segCnt; i++) {
|
||||||
|
seg = segs[i];
|
||||||
|
eventElement = $(_eventElements[i]);
|
||||||
event = seg.event;
|
event = seg.event;
|
||||||
eventElement = eventElements.eq(l);
|
|
||||||
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
||||||
if (triggerRes === false) {
|
if (triggerRes === false) {
|
||||||
eventElement.remove();
|
eventElement.remove();
|
||||||
|
@ -586,54 +593,81 @@ function _renderDaySegs(segRows, view, minLeft, maxLeft, getTr, dayContentLeft,
|
||||||
eventElement = $(triggerRes)
|
eventElement = $(triggerRes)
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: eventLefts[l]
|
left: seg.left
|
||||||
})
|
})
|
||||||
.appendTo(segmentContainer);
|
.appendTo(segmentContainer);
|
||||||
}
|
}
|
||||||
seg.element = eventElement; // will be useful for future rerender optimizations
|
seg.element = eventElement;
|
||||||
eventOuterHeights[l] = eventElement.outerHeight(true);
|
mouseoverBind(event, seg, eventElement);
|
||||||
eventHSides[l] = hsides(eventElement, true);
|
|
||||||
bootstrapEventHandlers(event, seg, eventElement);
|
|
||||||
view.reportEventElement(event, eventElement);
|
view.reportEventElement(event, eventElement);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
// set all positions/dimensions at once
|
// record event horizontal sides
|
||||||
for (; i<len; i++) {
|
for (i=0; i<segCnt; i++) {
|
||||||
levels = segRows[i];
|
seg = segs[i];
|
||||||
td = getTr(i).find('td:first');
|
if (eventElement = seg.element) {
|
||||||
innerDiv = td.find('div.fc-day-content div')
|
val = hsideCache[key = seg.key = cssKey(eventElement[0])];
|
||||||
.css('position', 'relative')
|
seg.hsides = val == undefined ? (hsideCache[key] = hsides(eventElement[0], true)) : val;
|
||||||
.height(''); // this is needed for IE7 to get an accurate position
|
}
|
||||||
top = innerDiv.position().top + topCorrect(td);
|
}
|
||||||
rowContentHeight = 0;
|
|
||||||
for (j=0; j<levels.length; j++) {
|
// set event widths
|
||||||
segs = levels[j];
|
for (i=0; i<segCnt; i++) {
|
||||||
levelHeight = 0;
|
seg = segs[i];
|
||||||
for (k=0; k<segs.length; k++) {
|
if (eventElement = seg.element) {
|
||||||
seg = segs[k];
|
eventElement[0].style.width = seg.outerWidth - seg.hsides + 'px';
|
||||||
if (eventElement = seg.element) {
|
}
|
||||||
eventElement.css('top', top);
|
}
|
||||||
//IE6 right-to-left sort-of-off-by-one bug
|
|
||||||
//if (rtl && rtlLeftDiff == undefined) {
|
// record event heights
|
||||||
// // bug in IE6 where offsets are miscalculated with direction:rtl
|
for (i=0; i<segCnt; i++) {
|
||||||
// rtlLeftDiff = eventLefts[l] - eventElement.position().left;
|
seg = segs[i];
|
||||||
// if (rtlLeftDiff) {
|
if (eventElement = seg.element) {
|
||||||
// eventElement.css('left', eventLefts[l] + rtlLeftDiff);
|
val = vmarginCache[key = seg.key];
|
||||||
// }
|
seg.outerHeight = eventElement[0].offsetHeight + (
|
||||||
//}
|
val == undefined ? (vmarginCache[key] = vmargins(eventElement[0])) : val
|
||||||
eventElement.width(eventRights[l] - eventLefts[l] - eventHSides[l]);
|
);
|
||||||
event = seg.event;
|
}
|
||||||
view.trigger('eventAfterRender', event, event, eventElement);
|
}
|
||||||
levelHeight = Math.max(levelHeight, eventOuterHeights[l]);
|
|
||||||
}
|
// set row heights, calculate event tops (in relation to row top)
|
||||||
l++;
|
for (i=0, rowI=0; rowI<rowCnt; rowI++) {
|
||||||
}
|
top = levelI = levelHeight = 0;
|
||||||
rowContentHeight += levelHeight;
|
while (i<segCnt && (seg = segs[i]).row == rowI) {
|
||||||
top += levelHeight;
|
if (seg.level != levelI) {
|
||||||
|
top += levelHeight;
|
||||||
|
levelHeight = 0;
|
||||||
|
levelI++;
|
||||||
|
}
|
||||||
|
levelHeight = Math.max(levelHeight, seg.outerHeight||0);
|
||||||
|
seg.top = top;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
rowDivs[rowI] = getRow(rowI).find('td:first div.fc-day-content > div') // > is optimal???
|
||||||
|
.height(top + levelHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate row tops
|
||||||
|
for (rowI=0; rowI<rowCnt; rowI++) {
|
||||||
|
rowDivTops[rowI] = rowDivs[rowI][0].offsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set event tops
|
||||||
|
for (i=0; i<segCnt; i++) {
|
||||||
|
seg = segs[i];
|
||||||
|
if (eventElement = seg.element) {
|
||||||
|
eventElement[0].style.top = rowDivTops[seg.row] + seg.top + 'px';
|
||||||
|
event = seg.event;
|
||||||
|
view.trigger('eventAfterRender', event, event, eventElement);
|
||||||
}
|
}
|
||||||
innerDiv.height(rowContentHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function cssKey(_element) {
|
||||||
|
return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
contentWidth = content.width();
|
contentWidth = content.width();
|
||||||
contentHeight = calculateContentHeight();
|
contentHeight = calculateContentHeight();
|
||||||
}
|
}
|
||||||
if (inc || !view.date || date < view.visStart || date >= view.visEnd) { // !view.date means it hasn't been rendered yet
|
if (inc || !view.date || date < view.start || date >= view.end) { // !view.date means it hasn't been rendered yet
|
||||||
fixContentSize();
|
fixContentSize();
|
||||||
view.render(date, inc || 0, contentWidth, contentHeight, function(callback) {
|
view.render(date, inc || 0, contentWidth, contentHeight, function(callback) {
|
||||||
// dont refetch if new view contains the same events (or a subset)
|
// dont refetch if new view contains the same events (or a subset)
|
||||||
|
@ -307,7 +307,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
return options.contentHeight;
|
return options.contentHeight;
|
||||||
}
|
}
|
||||||
else if (options.height) {
|
else if (options.height) {
|
||||||
return options.height - (header ? header.height() : 0) - vsides(content);
|
return options.height - (header ? header.height() : 0) - vsides(content[0]);
|
||||||
}
|
}
|
||||||
return Math.round(contentWidth / Math.max(options.aspectRatio, .5));
|
return Math.round(contentWidth / Math.max(options.aspectRatio, .5));
|
||||||
}
|
}
|
||||||
|
|
66
src/util.js
66
src/util.js
|
@ -298,37 +298,42 @@ var dateFormatters = {
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
function setOuterWidth(element, width, includeMargins) {
|
function setOuterWidth(element, width, includeMargins) {
|
||||||
element.each(function() {
|
element.each(function(i, _element) {
|
||||||
var e = $(this);
|
_element.style.width = width - hsides(_element, includeMargins) + 'px';
|
||||||
e.width(width - hsides(e, includeMargins));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function hsides(e, includeMargins) {
|
|
||||||
return (parseInt(e.css('border-left-width')) || 0) +
|
|
||||||
(parseInt(e.css('padding-left')) || 0) +
|
|
||||||
(parseInt(e.css('padding-right')) || 0) +
|
|
||||||
(parseInt(e.css('border-right-width')) || 0) +
|
|
||||||
(includeMargins ?
|
|
||||||
(parseInt(e.css('margin-left')) || 0) + (parseInt(e.css('margin-right')) || 0)
|
|
||||||
: 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setOuterHeight(element, height, includeMargins) {
|
function setOuterHeight(element, height, includeMargins) {
|
||||||
element.each(function() {
|
element.each(function(i, _element) {
|
||||||
var e = $(this);
|
_element.style.height = height - vsides(_element, includeMargins) + 'px';
|
||||||
e.height(height - vsides(e, includeMargins));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function vsides(e, includeMargins) {
|
|
||||||
return (parseInt(e.css('border-top-width')) || 0) +
|
function hsides(_element, includeMargins) {
|
||||||
(parseInt(e.css('padding-top')) || 0) +
|
return (parseFloat(jQuery.curCSS(_element, 'paddingLeft', true)) || 0) +
|
||||||
(parseInt(e.css('padding-bottom')) || 0) +
|
(parseFloat(jQuery.curCSS(_element, 'paddingRight', true)) || 0) +
|
||||||
(parseInt(e.css('border-bottom-width')) || 0) +
|
(parseFloat(jQuery.curCSS(_element, 'borderLeftWidth', true)) || 0) +
|
||||||
(includeMargins ?
|
(parseFloat(jQuery.curCSS(_element, 'borderRightWidth', true)) || 0) +
|
||||||
(parseInt(e.css('margin-top')) || 0) + (parseInt(e.css('margin-bottom')) || 0)
|
(includeMargins ? hmargins(_element) : 0);
|
||||||
: 0);
|
}
|
||||||
|
|
||||||
|
function hmargins(_element) {
|
||||||
|
return (parseFloat(jQuery.curCSS(_element, 'marginLeft', true)) || 0) +
|
||||||
|
(parseFloat(jQuery.curCSS(_element, 'marginRight', true)) || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function vsides(_element, includeMargins) {
|
||||||
|
return (parseFloat(jQuery.curCSS(_element, 'paddingTop', true)) || 0) +
|
||||||
|
(parseFloat(jQuery.curCSS(_element, 'paddingBottom', true)) || 0) +
|
||||||
|
(parseFloat(jQuery.curCSS(_element, 'borderTopWidth', true)) || 0) +
|
||||||
|
(parseFloat(jQuery.curCSS(_element, 'borderBottomWidth', true)) || 0) +
|
||||||
|
(includeMargins ? vmargins(_element) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function vmargins(_element) {
|
||||||
|
return (parseFloat(jQuery.curCSS(_element, 'marginTop', true)) || 0) +
|
||||||
|
(parseFloat(jQuery.curCSS(_element, 'marginBottom', true)) || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -455,18 +460,6 @@ function htmlEscape(s) {
|
||||||
.replace(/"/g, '"')
|
.replace(/"/g, '"')
|
||||||
}
|
}
|
||||||
|
|
||||||
function eachLeaf(node, callback, leafIndex, indexTrail) {
|
|
||||||
if (node.pop == arrayPop) { // is an array?
|
|
||||||
for (var i=0, len=node.length; i<len; i++) {
|
|
||||||
leafIndex = eachLeaf(node[i], callback, leafIndex||0, [i].concat(indexTrail||[]));
|
|
||||||
}
|
|
||||||
return leafIndex;
|
|
||||||
}
|
|
||||||
callback.apply(node, [leafIndex, node].concat(indexTrail));
|
|
||||||
return leafIndex + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function HorizontalPositionCache(getElement) {
|
function HorizontalPositionCache(getElement) {
|
||||||
|
@ -501,4 +494,3 @@ function HorizontalPositionCache(getElement) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ var viewMethods = {
|
||||||
var elements = this.eventElementsByID[event._id],
|
var elements = this.eventElementsByID[event._id],
|
||||||
i, len = elements.length;
|
i, len = elements.length;
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
if (elements[i] != exceptElement) {
|
if (elements[i][0] != exceptElement[0]) { // AHAHAHAHAHAHAHAH
|
||||||
elements[i][funcName]();
|
elements[i][funcName]();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,15 @@
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
$('#calendar').fullCalendar({
|
$('#calendar').fullCalendar({
|
||||||
year: 2009,
|
year: 2010,
|
||||||
month: 11,
|
month: 0,
|
||||||
header: {
|
header: {
|
||||||
left: 'prev,next today',
|
left: 'prev,next today',
|
||||||
center: 'title',
|
center: 'title',
|
||||||
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
||||||
},
|
},
|
||||||
editable: true,
|
editable: true,
|
||||||
events: 'many_events_json.txt'
|
events: "many_events_json.txt"
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -50,14 +50,13 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (event.id == 777) {
|
else if (event.id == 777) {
|
||||||
return $("<div style='background:green'/>").text(event.title);
|
return $("<div style='background:green'>").text(event.title);
|
||||||
}
|
}
|
||||||
else if (event.id == 999) {
|
else if (event.id == 999) {
|
||||||
element.css('border-color', 'red');
|
element.css('border-color', 'red');
|
||||||
//console.log('renderEvent (' + event.title + ') - ' + view.title);
|
//console.log('renderEvent (' + event.title + ') - ' + view.title);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
eventAfterRender: function(event, element, view) {
|
eventAfterRender: function(event, element, view) {
|
||||||
//console.log('after render for "' + event.title + '":');
|
//console.log('after render for "' + event.title + '":');
|
||||||
//console.log(element);
|
//console.log(element);
|
||||||
|
@ -99,9 +98,9 @@
|
||||||
console.log(dayDelta + ' days');
|
console.log(dayDelta + ' days');
|
||||||
console.log(minuteDelta + ' minutes');
|
console.log(minuteDelta + ' minutes');
|
||||||
console.log('allday: ' + allDay);
|
console.log('allday: ' + allDay);
|
||||||
/*setTimeout(function() {
|
//setTimeout(function() {
|
||||||
revertFunc();
|
// revertFunc();
|
||||||
}, 2000);*/
|
//}, 2000);
|
||||||
//console.log(jsEvent);
|
//console.log(jsEvent);
|
||||||
//console.log(ui);
|
//console.log(ui);
|
||||||
//console.log(view.title);
|
//console.log(view.title);
|
||||||
|
@ -120,9 +119,9 @@
|
||||||
console.log('RESIZE!! ' + event.title);
|
console.log('RESIZE!! ' + event.title);
|
||||||
console.log(dayDelta + ' days');
|
console.log(dayDelta + ' days');
|
||||||
console.log(minuteDelta + ' minutes');
|
console.log(minuteDelta + ' minutes');
|
||||||
/*setTimeout(function() {
|
//setTimeout(function() {
|
||||||
revertFunc();
|
// revertFunc();
|
||||||
}, 2000);*/
|
//}, 2000);
|
||||||
//console.log(jsEvent);
|
//console.log(jsEvent);
|
||||||
//console.log(ui);
|
//console.log(ui);
|
||||||
//console.log(view.title);
|
//console.log(view.title);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
1.4.3
|
1.4.4
|
||||||
|
|
Loading…
Reference in a new issue