Merge branch 'v1.4-speedup'
This commit is contained in:
commit
7158fc3470
485
src/agenda.js
485
src/agenda.js
|
@ -21,7 +21,7 @@ setDefaults({
|
||||||
|
|
||||||
views.agendaWeek = function(element, options) {
|
views.agendaWeek = function(element, options) {
|
||||||
return new Agenda(element, options, {
|
return new Agenda(element, options, {
|
||||||
render: function(date, delta, height, fetchEvents) {
|
render: function(date, delta, width, height, fetchEvents) {
|
||||||
if (delta) {
|
if (delta) {
|
||||||
addDays(date, delta * 7);
|
addDays(date, delta * 7);
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,19 @@ views.agendaWeek = function(element, options) {
|
||||||
this.option('titleFormat'),
|
this.option('titleFormat'),
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
this.renderAgenda(options.weekends ? 7 : 5, this.option('columnFormat'), height, fetchEvents);
|
this.renderAgenda(
|
||||||
|
options.weekends ? 7 : 5,
|
||||||
|
this.option('columnFormat'),
|
||||||
|
width, height,
|
||||||
|
fetchEvents
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
views.agendaDay = function(element, options) {
|
views.agendaDay = function(element, options) {
|
||||||
return new Agenda(element, options, {
|
return new Agenda(element, options, {
|
||||||
render: function(date, delta, height, fetchEvents) {
|
render: function(date, delta, width, height, fetchEvents) {
|
||||||
if (delta) {
|
if (delta) {
|
||||||
addDays(date, delta);
|
addDays(date, delta);
|
||||||
if (!options.weekends) {
|
if (!options.weekends) {
|
||||||
|
@ -58,7 +63,12 @@ views.agendaDay = function(element, options) {
|
||||||
this.title = formatDate(date, this.option('titleFormat'), options);
|
this.title = formatDate(date, this.option('titleFormat'), options);
|
||||||
this.start = this.visStart = cloneDate(date, true);
|
this.start = this.visStart = cloneDate(date, true);
|
||||||
this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
||||||
this.renderAgenda(1, this.option('columnFormat'), height, fetchEvents);
|
this.renderAgenda(
|
||||||
|
1,
|
||||||
|
this.option('columnFormat'),
|
||||||
|
width, height,
|
||||||
|
fetchEvents
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -68,18 +78,26 @@ function Agenda(element, options, methods) {
|
||||||
var head, body, bodyContent, bodyTable, bg,
|
var head, body, bodyContent, bodyTable, bg,
|
||||||
colCnt,
|
colCnt,
|
||||||
axisWidth, colWidth, slotHeight,
|
axisWidth, colWidth, slotHeight,
|
||||||
cachedDaySegs=[], cachedSlotSegs=[],
|
viewWidth, viewHeight,
|
||||||
cachedHeight,
|
cachedEvents=[],
|
||||||
|
daySegmentContainer,
|
||||||
|
daySegments=[],
|
||||||
|
slotSegmentContainer,
|
||||||
|
slotSegments=[],
|
||||||
tm, firstDay,
|
tm, firstDay,
|
||||||
nwe, // no weekends (int)
|
nwe, // no weekends (int)
|
||||||
rtl, dis, dit, // day index sign / translate
|
rtl, dis, dit, // day index sign / translate
|
||||||
minMinute, maxMinute,
|
minMinute, maxMinute,
|
||||||
|
colContentPositions = new HorizontalPositionCache(function(col) {
|
||||||
|
return bg.find('td:eq(' + col + ') div div');
|
||||||
|
}),
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
view = $.extend(this, viewMethods, methods, {
|
view = $.extend(this, viewMethods, methods, {
|
||||||
renderAgenda: renderAgenda,
|
renderAgenda: renderAgenda,
|
||||||
renderEvents: renderEvents,
|
renderEvents: renderEvents,
|
||||||
rerenderEvents: rerenderEvents,
|
rerenderEvents: rerenderEvents,
|
||||||
|
clearEvents: clearEvents,
|
||||||
updateSize: updateSize,
|
updateSize: updateSize,
|
||||||
shown: resetScroll,
|
shown: resetScroll,
|
||||||
defaultEventEnd: function(event) {
|
defaultEventEnd: function(event) {
|
||||||
|
@ -88,21 +106,6 @@ function Agenda(element, options, methods) {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
return addMinutes(start, options.defaultEventMinutes);
|
return addMinutes(start, options.defaultEventMinutes);
|
||||||
},
|
|
||||||
visEventEnd: function(event) {
|
|
||||||
if (event.allDay) {
|
|
||||||
if (event.end) {
|
|
||||||
var end = cloneDate(event.end);
|
|
||||||
return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
|
|
||||||
}else{
|
|
||||||
return addDays(cloneDate(event.start), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event.end) {
|
|
||||||
return cloneDate(event.end);
|
|
||||||
}else{
|
|
||||||
return addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
view.init(element, options);
|
view.init(element, options);
|
||||||
|
@ -118,7 +121,7 @@ function Agenda(element, options, methods) {
|
||||||
element.disableSelection();
|
element.disableSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAgenda(c, colFormat, height, fetchEvents) {
|
function renderAgenda(c, colFormat, width, height, fetchEvents) {
|
||||||
colCnt = c;
|
colCnt = c;
|
||||||
|
|
||||||
// update option-derived variables
|
// update option-derived variables
|
||||||
|
@ -175,6 +178,9 @@ function Agenda(element, options, methods) {
|
||||||
head = $(s).appendTo(element);
|
head = $(s).appendTo(element);
|
||||||
head.find('td').click(slotClick);
|
head.find('td').click(slotClick);
|
||||||
|
|
||||||
|
// all-day event container
|
||||||
|
daySegmentContainer = $("<div/>").appendTo(head);
|
||||||
|
|
||||||
// body
|
// body
|
||||||
d = zeroDate();
|
d = zeroDate();
|
||||||
var maxd = addMinutes(cloneDate(d), maxMinute);
|
var maxd = addMinutes(cloneDate(d), maxMinute);
|
||||||
|
@ -197,6 +203,9 @@ function Agenda(element, options, methods) {
|
||||||
.appendTo(element);
|
.appendTo(element);
|
||||||
body.find('td').click(slotClick);
|
body.find('td').click(slotClick);
|
||||||
|
|
||||||
|
// slot event container
|
||||||
|
slotSegmentContainer = $("<div/>").appendTo(bodyContent);
|
||||||
|
|
||||||
// background stripes
|
// background stripes
|
||||||
d = cloneDate(d0);
|
d = cloneDate(d0);
|
||||||
s = "<div class='fc-agenda-bg' style='position:absolute;z-index:1'>" +
|
s = "<div class='fc-agenda-bg' style='position:absolute;z-index:1'>" +
|
||||||
|
@ -218,7 +227,7 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
}else{ // skeleton already built, just modify it
|
}else{ // skeleton already built, just modify it
|
||||||
|
|
||||||
view.clearEvents();
|
clearEvents();
|
||||||
|
|
||||||
// redo column header text and class
|
// redo column header text and class
|
||||||
head.find('tr:first th').slice(1, -1).each(function() {
|
head.find('tr:first th').slice(1, -1).each(function() {
|
||||||
|
@ -253,7 +262,7 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSize(height);
|
updateSize(width, height);
|
||||||
resetScroll();
|
resetScroll();
|
||||||
fetchEvents(renderEvents);
|
fetchEvents(renderEvents);
|
||||||
|
|
||||||
|
@ -276,19 +285,19 @@ function Agenda(element, options, methods) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function updateSize(height) {
|
function updateSize(width, height) {
|
||||||
cachedHeight = height;
|
viewWidth = width;
|
||||||
|
viewHeight = height;
|
||||||
|
colContentPositions.clear();
|
||||||
|
|
||||||
bodyTable.width('');
|
body.width(width);
|
||||||
body.height(height - head.height());
|
body.height(height - head.height());
|
||||||
|
bodyTable.width('');
|
||||||
// need this for IE6/7. triggers clientWidth to be calculated for
|
|
||||||
// later user in this function. this is ridiculous
|
|
||||||
body[0].clientWidth;
|
|
||||||
|
|
||||||
var topTDs = head.find('tr:first th'),
|
var topTDs = head.find('tr:first th'),
|
||||||
stripeTDs = bg.find('td'),
|
stripeTDs = bg.find('td'),
|
||||||
contentWidth = body[0].clientWidth;
|
contentWidth = slotSegmentContainer.width(); // body[0].clientWidth isn't reliable here in IE6
|
||||||
|
|
||||||
bodyTable.width(contentWidth);
|
bodyTable.width(contentWidth);
|
||||||
|
|
||||||
// time-axis width
|
// time-axis width
|
||||||
|
@ -316,10 +325,6 @@ function Agenda(element, options, methods) {
|
||||||
});
|
});
|
||||||
|
|
||||||
slotHeight = body.find('tr:first div').height() + 1;
|
slotHeight = body.find('tr:first div').height() + 1;
|
||||||
|
|
||||||
// TODO:
|
|
||||||
//reportTBody(bodyTable.find('tbody'));
|
|
||||||
// Opera 9.25 doesn't detect the bug when called from agenda
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function slotClick(ev) {
|
function slotClick(ev) {
|
||||||
|
@ -342,10 +347,8 @@ function Agenda(element, options, methods) {
|
||||||
/* Event Rendering
|
/* Event Rendering
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
function renderEvents(events) {
|
function renderEvents(events) {
|
||||||
view.reportEvents(events);
|
view.reportEvents(cachedEvents = events);
|
||||||
|
|
||||||
var i, len=events.length,
|
var i, len=events.length,
|
||||||
dayEvents=[],
|
dayEvents=[],
|
||||||
slotEvents=[];
|
slotEvents=[];
|
||||||
|
@ -356,30 +359,32 @@ function Agenda(element, options, methods) {
|
||||||
slotEvents.push(events[i]);
|
slotEvents.push(events[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
renderDaySegs(daySegments = stackSegs(view.sliceSegs(dayEvents, $.map(dayEvents, visEventEnd), view.visStart, view.visEnd)));
|
||||||
renderDaySegs(cachedDaySegs = stackSegs(view.sliceSegs(dayEvents, view.visStart, view.visEnd)));
|
renderSlotSegs(slotSegments = compileSlotSegs(slotEvents));
|
||||||
renderSlotSegs(cachedSlotSegs = compileSlotSegs(slotEvents));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function rerenderEvents(skipCompile) {
|
function rerenderEvents() {
|
||||||
view.clearEvents();
|
clearEvents();
|
||||||
if (skipCompile) {
|
renderEvents(cachedEvents);
|
||||||
renderDaySegs(cachedDaySegs);
|
}
|
||||||
renderSlotSegs(cachedSlotSegs);
|
|
||||||
}else{
|
|
||||||
renderEvents(view.cachedEvents);
|
function clearEvents() {
|
||||||
}
|
daySegmentContainer.empty();
|
||||||
|
slotSegmentContainer.empty();
|
||||||
|
view._clearEvents(); // only clears the hashes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function compileSlotSegs(events) {
|
function compileSlotSegs(events) {
|
||||||
var d = addMinutes(cloneDate(view.visStart), minMinute),
|
var d = addMinutes(cloneDate(view.visStart), minMinute),
|
||||||
|
ends = $.map(events, visEventEnd),
|
||||||
levels,
|
levels,
|
||||||
segCols = [],
|
segCols = [],
|
||||||
i=0;
|
i=0;
|
||||||
for (; i<colCnt; i++) {
|
for (; i<colCnt; i++) {
|
||||||
levels = stackSegs(view.sliceSegs(events, d, addMinutes(cloneDate(d), maxMinute-minMinute)));
|
levels = stackSegs(view.sliceSegs(events, ends, d, addMinutes(cloneDate(d), maxMinute-minMinute)));
|
||||||
countForwardSegs(levels);
|
countForwardSegs(levels);
|
||||||
segCols.push(levels);
|
segCols.push(levels);
|
||||||
addDays(d, 1, true);
|
addDays(d, 1, true);
|
||||||
|
@ -389,94 +394,29 @@ function Agenda(element, options, methods) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// renders 'all-day' events at the top
|
// renders 'all-day' events at the top
|
||||||
|
|
||||||
function renderDaySegs(segRow) {
|
function renderDaySegs(segRow) {
|
||||||
if (options.allDaySlot) {
|
if (options.allDaySlot) {
|
||||||
var td = head.find('td'),
|
_renderDaySegs(
|
||||||
tdInner = td.find('div div'),
|
[segRow],
|
||||||
tr = td.parent(),
|
view,
|
||||||
top = safePosition(tdInner, td, tr, tr.parent()).top,
|
axisWidth,
|
||||||
rowContentHeight = 0,
|
viewWidth,
|
||||||
i, len=segRow.length, level,
|
function() {
|
||||||
levelHeight,
|
return head.find('tr.fc-all-day')
|
||||||
j, seg,
|
},
|
||||||
event,
|
function(dayOfWeek) {
|
||||||
className,
|
return axisWidth + colContentPositions.left(day2col(dayOfWeek));
|
||||||
leftDay, leftRounded,
|
},
|
||||||
rightDay, rightRounded,
|
function(dayOfWeek) {
|
||||||
left, right,
|
return axisWidth + colContentPositions.right(day2col(dayOfWeek));
|
||||||
eventElement, anchorElement,
|
},
|
||||||
triggerRes;
|
daySegmentContainer,
|
||||||
for (i=0; i<len; i++) {
|
bootstrapDayEventHandlers
|
||||||
level = segRow[i];
|
);
|
||||||
levelHeight = 0;
|
updateSize(viewWidth, viewHeight); // might have pushed the body down, so resize
|
||||||
for (j=0; j<level.length; j++) {
|
|
||||||
seg = level[j];
|
|
||||||
event = seg.event;
|
|
||||||
className = 'fc-event fc-event-hori ';
|
|
||||||
if (rtl) {
|
|
||||||
leftDay = seg.end.getDay() - 1;
|
|
||||||
leftRounded = seg.isEnd;
|
|
||||||
rightDay = seg.start.getDay();
|
|
||||||
rightRounded = seg.isStart;
|
|
||||||
}else{
|
|
||||||
leftDay = seg.start.getDay();
|
|
||||||
leftRounded = seg.isStart;
|
|
||||||
rightDay = seg.end.getDay() - 1;
|
|
||||||
rightRounded = seg.isEnd;
|
|
||||||
}
|
|
||||||
if (leftRounded) {
|
|
||||||
className += 'fc-corner-left ';
|
|
||||||
left = bg.find('td:eq('+(((leftDay-Math.max(firstDay,nwe)+colCnt)%colCnt)*dis+dit)+') div div').position().left + axisWidth;
|
|
||||||
}else{
|
|
||||||
left = axisWidth;
|
|
||||||
}
|
|
||||||
if (rightRounded) {
|
|
||||||
className += 'fc-corner-right ';
|
|
||||||
right = bg.find('td:eq('+(((rightDay-Math.max(firstDay,nwe)+colCnt)%colCnt)*dis+dit)+') div div');
|
|
||||||
right = right.position().left + right.width() + axisWidth;
|
|
||||||
}else{
|
|
||||||
right = axisWidth + bg.width();
|
|
||||||
}
|
|
||||||
eventElement = $("<div class='" + className + event.className.join(' ') + "'/>")
|
|
||||||
.append(anchorElement = $("<a/>")
|
|
||||||
.append($("<span class='fc-event-title' />")
|
|
||||||
.text(event.title)));
|
|
||||||
if (event.url) {
|
|
||||||
anchorElement.attr('href', event.url);
|
|
||||||
}
|
|
||||||
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
|
||||||
if (triggerRes !== false) {
|
|
||||||
if (triggerRes && typeof triggerRes != 'boolean') {
|
|
||||||
eventElement = $(triggerRes);
|
|
||||||
}
|
|
||||||
eventElement
|
|
||||||
.css({
|
|
||||||
position: 'absolute',
|
|
||||||
top: top,
|
|
||||||
left: left,
|
|
||||||
zIndex: 8
|
|
||||||
})
|
|
||||||
.appendTo(head);
|
|
||||||
setOuterWidth(eventElement, right-left, true);
|
|
||||||
view.eventElementHandlers(event, eventElement);
|
|
||||||
if (event.editable || event.editable == undefined && options.editable) {
|
|
||||||
draggableDayEvent(event, eventElement, seg.isStart);
|
|
||||||
if (seg.isEnd) {
|
|
||||||
view.resizableDayEvent(event, eventElement, colWidth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.reportEventElement(event, eventElement);
|
|
||||||
view.trigger('eventAfterRender', event, event, eventElement);
|
|
||||||
levelHeight = Math.max(levelHeight, eventElement.outerHeight(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
top += levelHeight;
|
|
||||||
rowContentHeight += levelHeight;
|
|
||||||
}
|
|
||||||
tdInner.height(rowContentHeight);
|
|
||||||
updateSize(cachedHeight); // tdInner might have pushed the body down, so resize
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,94 +425,182 @@ 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(segCols) {
|
||||||
var colI, colLen=segCols.length, col,
|
|
||||||
levelI, level,
|
var event,
|
||||||
segI, seg,
|
|
||||||
forward,
|
|
||||||
event,
|
|
||||||
top, bottom,
|
|
||||||
tdInner,
|
|
||||||
width, left,
|
|
||||||
className,
|
className,
|
||||||
eventElement, anchorElement, timeElement, titleElement,
|
top,
|
||||||
triggerRes;
|
bottom,
|
||||||
for (colI=0; colI<colLen; colI++) {
|
leftmost,
|
||||||
col = segCols[colI];
|
availWidth,
|
||||||
for (levelI=0; levelI<col.length; levelI++) {
|
forward,
|
||||||
level = col[levelI];
|
width,
|
||||||
for (segI=0; segI<level.length; segI++) {
|
left,
|
||||||
seg = level[segI];
|
eventTops=[],
|
||||||
forward = seg.forward || 0;
|
eventLefts=[],
|
||||||
event = seg.event;
|
eventOuterWidths=[],
|
||||||
top = timePosition(seg.start, seg.start);
|
eventOuterHeights=[],
|
||||||
bottom = timePosition(seg.start, seg.end);
|
html='',
|
||||||
tdInner = bg.find('td:eq(' + (colI*dis + dit) + ') div div');
|
eventElements,
|
||||||
availWidth = tdInner.width();
|
eventElement,
|
||||||
availWidth = Math.min(availWidth-6, availWidth*.95); // TODO: move this to CSS
|
triggerRes,
|
||||||
if (levelI) {
|
eventVSides=[],
|
||||||
// indented and thin
|
eventHSides=[],
|
||||||
width = availWidth / (levelI + forward + 1);
|
eventTitleTops=[],
|
||||||
}else{
|
height;
|
||||||
if (forward) {
|
|
||||||
// moderately wide, aligned left still
|
// calculate desired position/dimensions, create html
|
||||||
width = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
eachLeaf(segCols, function(l, seg, segI, levelI, colI) {
|
||||||
}else{
|
event = seg.event;
|
||||||
// can be entire width, aligned left
|
className = 'fc-event fc-event-vert ';
|
||||||
width = availWidth;
|
if (seg.isStart) {
|
||||||
}
|
className += 'fc-corner-top ';
|
||||||
}
|
}
|
||||||
left = axisWidth + tdInner.position().left + // leftmost possible
|
if (seg.isEnd) {
|
||||||
(availWidth / (levelI + forward + 1) * levelI) // indentation
|
className += 'fc-corner-bottom ';
|
||||||
* dis + (rtl ? availWidth - width : 0); // rtl
|
}
|
||||||
className = 'fc-event fc-event-vert ';
|
top = timePosition(seg.start, seg.start);
|
||||||
if (seg.isStart) {
|
bottom = timePosition(seg.start, seg.end);
|
||||||
className += 'fc-corner-top ';
|
leftmost = axisWidth + colContentPositions.left(colI*dis + dit);
|
||||||
}
|
availWidth = axisWidth + colContentPositions.right(colI*dis + dit) - leftmost;
|
||||||
if (seg.isEnd) {
|
availWidth = Math.min(availWidth-6, availWidth*.95); // TODO: move this to CSS
|
||||||
className += 'fc-corner-bottom ';
|
forward = seg.forward || 0;
|
||||||
}
|
if (levelI) {
|
||||||
eventElement = $("<div class='" + className + event.className.join(' ') + "' />")
|
// indented and thin
|
||||||
.append(anchorElement = $("<a><span class='fc-event-bg'/></a>")
|
width = availWidth / (levelI + forward + 1);
|
||||||
.append(timeElement = $("<span class='fc-event-time'/>")
|
}else{
|
||||||
.text(formatDates(event.start, event.end, view.option('timeFormat'))))
|
if (forward) {
|
||||||
.append(titleElement = $("<span class='fc-event-title'/>")
|
// moderately wide, aligned left still
|
||||||
.text(event.title)))
|
width = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
||||||
if (event.url) {
|
}else{
|
||||||
anchorElement.attr('href', event.url);
|
// can be entire width, aligned left
|
||||||
}
|
width = availWidth;
|
||||||
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
|
||||||
if (triggerRes !== false) {
|
|
||||||
if (triggerRes && typeof triggerRes != 'boolean') {
|
|
||||||
eventElement = $(triggerRes);
|
|
||||||
}
|
|
||||||
eventElement
|
|
||||||
.css({
|
|
||||||
position: 'absolute',
|
|
||||||
zIndex: 8,
|
|
||||||
top: top,
|
|
||||||
left: left
|
|
||||||
})
|
|
||||||
.appendTo(bodyContent);
|
|
||||||
setOuterWidth(eventElement, width, true);
|
|
||||||
setOuterHeight(eventElement, bottom-top, true);
|
|
||||||
if (eventElement.height() - titleElement.position().top < 10) {
|
|
||||||
// event title doesn't have enough room, put next to the time
|
|
||||||
timeElement.text(formatDate(event.start, view.option('timeFormat')) + ' - ' + event.title);
|
|
||||||
titleElement.remove();
|
|
||||||
}
|
|
||||||
view.eventElementHandlers(event, eventElement);
|
|
||||||
if (event.editable || event.editable == undefined && options.editable) {
|
|
||||||
draggableSlotEvent(event, eventElement, timeElement);
|
|
||||||
if (seg.isEnd) {
|
|
||||||
resizableSlotEvent(event, eventElement, timeElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.reportEventElement(event, eventElement);
|
|
||||||
view.trigger('eventAfterRender', event, event, eventElement);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
left = leftmost + // leftmost possible
|
||||||
|
(availWidth / (levelI + forward + 1) * levelI) // indentation
|
||||||
|
* dis + (rtl ? availWidth - width : 0); // rtl
|
||||||
|
eventTops[l] = top;
|
||||||
|
eventLefts[l] = left;
|
||||||
|
eventOuterWidths[l] = width;
|
||||||
|
eventOuterHeights[l] = bottom - top;
|
||||||
|
html +=
|
||||||
|
"<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) + "'" : '') + ">" +
|
||||||
|
"<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-bg'/>" +
|
||||||
|
"</a>" +
|
||||||
|
((event.editable || event.editable == undefined && options.editable) && !options.disableResizing && $.fn.resizable ?
|
||||||
|
"<div class='ui-resizable-handle ui-resizable-s'>=</div>"
|
||||||
|
: '') +
|
||||||
|
"</div>";
|
||||||
|
});
|
||||||
|
slotSegmentContainer.html(html);
|
||||||
|
eventElements = slotSegmentContainer.children();
|
||||||
|
|
||||||
|
// retrieve elements, run through eventRender callback, record outer-edge dimensions
|
||||||
|
eachLeaf(segCols, function(l, seg) {
|
||||||
|
event = seg.event;
|
||||||
|
eventElement = eventElements.eq(l);
|
||||||
|
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
||||||
|
if (triggerRes === false) {
|
||||||
|
eventElement.remove();
|
||||||
|
}else{
|
||||||
|
if (triggerRes && triggerRes !== true) {
|
||||||
|
eventElement.remove();
|
||||||
|
eventElement = $(triggerRes)
|
||||||
|
.css({
|
||||||
|
top: eventTops[l],
|
||||||
|
left: eventLefts[l]
|
||||||
|
})
|
||||||
|
.appendTo(slotSegmentContainer);
|
||||||
|
}
|
||||||
|
seg.element = eventElement;
|
||||||
|
eventVSides[l] = vsides(eventElement, true);
|
||||||
|
eventHSides[l] = hsides(eventElement, true);
|
||||||
|
eventTitleTops[l] = eventElement.find('span.fc-event-title').position().top;
|
||||||
|
bootstrapSlotEventHandlers(event, seg, eventElement);
|
||||||
|
view.reportEventElement(event, eventElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// set all positions/dimensions at once
|
||||||
|
eachLeaf(segCols, function(l, seg) {
|
||||||
|
if (eventElement = seg.element) {
|
||||||
|
eventElement
|
||||||
|
.width(eventOuterWidths[l] - eventHSides[l])
|
||||||
|
.height(height = eventOuterHeights[l] - eventVSides[l]);
|
||||||
|
event = seg.event;
|
||||||
|
if (height - eventTitleTops[l] < 10) {
|
||||||
|
// not enough room for title, put it in the time header
|
||||||
|
eventElement.find('span.fc-event-time')
|
||||||
|
.text(formatDate(event.start, view.option('timeFormat')) + ' - ' + event.title);
|
||||||
|
eventElement.find('span.fc-event-title')
|
||||||
|
.remove();
|
||||||
|
}
|
||||||
|
view.trigger('eventAfterRender', event, event, eventElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function visEventEnd(event) { // returns exclusive 'visible' end, for rendering
|
||||||
|
if (event.allDay) {
|
||||||
|
if (event.end) {
|
||||||
|
var end = cloneDate(event.end);
|
||||||
|
return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
|
||||||
|
}else{
|
||||||
|
return addDays(cloneDate(event.start), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (event.end) {
|
||||||
|
return cloneDate(event.end);
|
||||||
|
}else{
|
||||||
|
return addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function bootstrapDayEventHandlers(event, seg, eventElement) {
|
||||||
|
var attached = false;
|
||||||
|
eventElement.mouseover(function(ev) {
|
||||||
|
if (!attached) {
|
||||||
|
view.eventElementHandlers(event, eventElement);
|
||||||
|
if (event.editable || event.editable == undefined && options.editable) {
|
||||||
|
draggableDayEvent(event, eventElement, seg.isStart);
|
||||||
|
if (seg.isEnd) {
|
||||||
|
view.resizableDayEvent(event, eventElement, colWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attached = true;
|
||||||
|
view.trigger('eventMouseover', this, event, ev);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function bootstrapSlotEventHandlers(event, seg, eventElement) {
|
||||||
|
var attached = false;
|
||||||
|
eventElement.mouseover(function(ev) {
|
||||||
|
if (!attached) {
|
||||||
|
view.eventElementHandlers(event, eventElement);
|
||||||
|
if (event.editable || event.editable == undefined && options.editable) {
|
||||||
|
var timeElement = eventElement.find('span.fc-event-time');
|
||||||
|
draggableSlotEvent(event, eventElement, timeElement);
|
||||||
|
if (seg.isEnd) {
|
||||||
|
resizableSlotEvent(event, eventElement, timeElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attached = true;
|
||||||
|
view.trigger('eventMouseover', this, event, ev);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -798,7 +826,9 @@ function Agenda(element, options, methods) {
|
||||||
var slotDelta, prevSlotDelta;
|
var slotDelta, prevSlotDelta;
|
||||||
eventElement
|
eventElement
|
||||||
.resizable({
|
.resizable({
|
||||||
handles: 's',
|
handles: {
|
||||||
|
s: 'div.ui-resizable-s'
|
||||||
|
},
|
||||||
grid: slotHeight,
|
grid: slotHeight,
|
||||||
start: function(ev, ui) {
|
start: function(ev, ui) {
|
||||||
slotDelta = prevSlotDelta = 0;
|
slotDelta = prevSlotDelta = 0;
|
||||||
|
@ -834,15 +864,11 @@ function Agenda(element, options, methods) {
|
||||||
// BUG: if event was really short, need to put title back in span
|
// BUG: if event was really short, need to put title back in span
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.find('div.ui-resizable-s').text('=');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ALL-DAY event resizing w/ 'view' methods...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Misc
|
/* Misc
|
||||||
|
@ -865,9 +891,16 @@ function Agenda(element, options, methods) {
|
||||||
td = tr.find('td'),
|
td = tr.find('td'),
|
||||||
innerDiv = td.find('div');
|
innerDiv = td.find('div');
|
||||||
return Math.max(0, Math.round(
|
return Math.max(0, Math.round(
|
||||||
safePosition(innerDiv, td, tr, tr.parent()).top - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
innerDiv.position().top + topCorrect(td) - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function day2col(dayOfWeek) {
|
||||||
|
return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
350
src/grid.js
350
src/grid.js
|
@ -8,7 +8,7 @@ setDefaults({
|
||||||
|
|
||||||
views.month = function(element, options) {
|
views.month = function(element, options) {
|
||||||
return new Grid(element, options, {
|
return new Grid(element, options, {
|
||||||
render: function(date, delta, height, fetchEvents) {
|
render: function(date, delta, width, height, fetchEvents) {
|
||||||
if (delta) {
|
if (delta) {
|
||||||
addMonths(date, delta);
|
addMonths(date, delta);
|
||||||
date.setDate(1);
|
date.setDate(1);
|
||||||
|
@ -44,7 +44,7 @@ views.month = function(element, options) {
|
||||||
rowCnt, options.weekends ? 7 : 5,
|
rowCnt, options.weekends ? 7 : 5,
|
||||||
this.option('columnFormat'),
|
this.option('columnFormat'),
|
||||||
true,
|
true,
|
||||||
height,
|
width, height,
|
||||||
fetchEvents
|
fetchEvents
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ views.month = function(element, options) {
|
||||||
|
|
||||||
views.basicWeek = function(element, options) {
|
views.basicWeek = function(element, options) {
|
||||||
return new Grid(element, options, {
|
return new Grid(element, options, {
|
||||||
render: function(date, delta, height, fetchEvents) {
|
render: function(date, delta, width, height, fetchEvents) {
|
||||||
if (delta) {
|
if (delta) {
|
||||||
addDays(date, delta * 7);
|
addDays(date, delta * 7);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ views.basicWeek = function(element, options) {
|
||||||
1, options.weekends ? 7 : 5,
|
1, options.weekends ? 7 : 5,
|
||||||
this.option('columnFormat'),
|
this.option('columnFormat'),
|
||||||
false,
|
false,
|
||||||
height,
|
width, height,
|
||||||
fetchEvents
|
fetchEvents
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ views.basicWeek = function(element, options) {
|
||||||
|
|
||||||
views.basicDay = function(element, options) {
|
views.basicDay = function(element, options) {
|
||||||
return new Grid(element, options, {
|
return new Grid(element, options, {
|
||||||
render: function(date, delta, height, fetchEvents) {
|
render: function(date, delta, width, height, fetchEvents) {
|
||||||
if (delta) {
|
if (delta) {
|
||||||
addDays(date, delta);
|
addDays(date, delta);
|
||||||
if (!options.weekends) {
|
if (!options.weekends) {
|
||||||
|
@ -96,7 +96,13 @@ views.basicDay = function(element, options) {
|
||||||
this.title = formatDate(date, this.option('titleFormat'), options);
|
this.title = formatDate(date, this.option('titleFormat'), options);
|
||||||
this.start = this.visStart = cloneDate(date, true);
|
this.start = this.visStart = cloneDate(date, true);
|
||||||
this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
||||||
this.renderGrid(1, 1, this.option('columnFormat'), false, height, fetchEvents);
|
this.renderGrid(
|
||||||
|
1, 1,
|
||||||
|
this.option('columnFormat'),
|
||||||
|
false,
|
||||||
|
width, height,
|
||||||
|
fetchEvents
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -104,7 +110,7 @@ views.basicDay = function(element, options) {
|
||||||
|
|
||||||
// rendering bugs
|
// rendering bugs
|
||||||
|
|
||||||
var tdHeightBug, rtlLeftDiff;
|
var tdHeightBug;
|
||||||
|
|
||||||
|
|
||||||
function Grid(element, options, methods) {
|
function Grid(element, options, methods) {
|
||||||
|
@ -112,27 +118,27 @@ function Grid(element, options, methods) {
|
||||||
var tm, firstDay,
|
var tm, firstDay,
|
||||||
nwe, // no weekends (int)
|
nwe, // no weekends (int)
|
||||||
rtl, dis, dit, // day index sign / translate
|
rtl, dis, dit, // day index sign / translate
|
||||||
|
viewWidth, viewHeight,
|
||||||
rowCnt, colCnt,
|
rowCnt, colCnt,
|
||||||
colWidth,
|
colWidth,
|
||||||
thead, tbody,
|
thead, tbody,
|
||||||
cachedSegs=[], //...
|
cachedEvents=[],
|
||||||
|
segments=[],
|
||||||
|
segmentContainer,
|
||||||
|
dayContentPositions = new HorizontalPositionCache(function(dayOfWeek) {
|
||||||
|
return tbody.find('td:eq(' + ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt) + ') div div')
|
||||||
|
}),
|
||||||
|
// ...
|
||||||
|
|
||||||
// initialize superclass
|
// initialize superclass
|
||||||
view = $.extend(this, viewMethods, methods, {
|
view = $.extend(this, viewMethods, methods, {
|
||||||
renderGrid: renderGrid,
|
renderGrid: renderGrid,
|
||||||
renderEvents: renderEvents,
|
renderEvents: renderEvents,
|
||||||
rerenderEvents: rerenderEvents,
|
rerenderEvents: rerenderEvents,
|
||||||
|
clearEvents: clearEvents,
|
||||||
updateSize: updateSize,
|
updateSize: updateSize,
|
||||||
defaultEventEnd: function(event) { // calculates an end if event doesnt have one, mostly for resizing
|
defaultEventEnd: function(event) { // calculates an end if event doesnt have one, mostly for resizing
|
||||||
return cloneDate(event.start);
|
return cloneDate(event.start);
|
||||||
},
|
|
||||||
visEventEnd: function(event) { // returns exclusive 'visible' end, for rendering
|
|
||||||
if (event.end) {
|
|
||||||
var end = cloneDate(event.end);
|
|
||||||
return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
|
|
||||||
}else{
|
|
||||||
return addDays(cloneDate(event.start), 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
view.init(element, options);
|
view.init(element, options);
|
||||||
|
@ -148,7 +154,7 @@ function Grid(element, options, methods) {
|
||||||
element.disableSelection();
|
element.disableSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderGrid(r, c, colFormat, showNumbers, height, fetchEvents) {
|
function renderGrid(r, c, colFormat, showNumbers, width, height, fetchEvents) {
|
||||||
rowCnt = r;
|
rowCnt = r;
|
||||||
colCnt = c;
|
colCnt = c;
|
||||||
|
|
||||||
|
@ -210,10 +216,12 @@ 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);
|
||||||
|
|
||||||
}else{ // NOT first time, reuse as many cells as possible
|
}else{ // NOT first time, reuse as many cells as possible
|
||||||
|
|
||||||
view.clearEvents();
|
clearEvents();
|
||||||
|
|
||||||
var prevRowCnt = tbody.find('tr').length;
|
var prevRowCnt = tbody.find('tr').length;
|
||||||
if (rowCnt < prevRowCnt) {
|
if (rowCnt < prevRowCnt) {
|
||||||
|
@ -296,7 +304,7 @@ function Grid(element, options, methods) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSize(height);
|
updateSize(width, height);
|
||||||
fetchEvents(renderEvents);
|
fetchEvents(renderEvents);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -312,10 +320,13 @@ function Grid(element, options, methods) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function updateSize(height) {
|
function updateSize(width, height) { // does not render/position the events
|
||||||
|
viewWidth = width;
|
||||||
|
viewHeight = height;
|
||||||
|
dayContentPositions.clear();
|
||||||
|
|
||||||
var leftTDs = tbody.find('tr td:first-child'),
|
var leftTDs = tbody.find('tr td:first-child'),
|
||||||
tbodyHeight = height - thead.height(),
|
tbodyHeight = viewHeight - thead.height(),
|
||||||
rowHeight1, rowHeight2;
|
rowHeight1, rowHeight2;
|
||||||
|
|
||||||
if (options.weekMode == 'variable') {
|
if (options.weekMode == 'variable') {
|
||||||
|
@ -325,8 +336,6 @@ function Grid(element, options, methods) {
|
||||||
rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1);
|
rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
reportTBody(tbody);
|
|
||||||
|
|
||||||
if (tdHeightBug == undefined) {
|
if (tdHeightBug == undefined) {
|
||||||
// bug in firefox where cell height includes padding
|
// bug in firefox where cell height includes padding
|
||||||
var tr = tbody.find('tr:first'),
|
var tr = tbody.find('tr:first'),
|
||||||
|
@ -345,11 +354,11 @@ function Grid(element, options, methods) {
|
||||||
|
|
||||||
setOuterWidth(
|
setOuterWidth(
|
||||||
thead.find('th').slice(0, -1),
|
thead.find('th').slice(0, -1),
|
||||||
colWidth = Math.floor(element.width() / colCnt)
|
colWidth = Math.floor(viewWidth / colCnt)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Event Rendering
|
/* Event Rendering
|
||||||
|
@ -357,18 +366,20 @@ function Grid(element, options, methods) {
|
||||||
|
|
||||||
|
|
||||||
function renderEvents(events) {
|
function renderEvents(events) {
|
||||||
view.reportEvents(events);
|
view.reportEvents(cachedEvents = events);
|
||||||
renderSegs(cachedSegs = compileSegs(events));
|
renderSegs(segments = compileSegs(events));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function rerenderEvents(skipCompile) {
|
function rerenderEvents() {
|
||||||
view.clearEvents();
|
clearEvents();
|
||||||
if (skipCompile) {
|
renderSegs(segments = compileSegs(cachedEvents));
|
||||||
renderSegs(cachedSegs);
|
}
|
||||||
}else{
|
|
||||||
renderEvents(view.cachedEvents);
|
|
||||||
}
|
function clearEvents() {
|
||||||
|
view._clearEvents(); // only clears the hashes
|
||||||
|
segmentContainer.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -378,7 +389,7 @@ function Grid(element, options, methods) {
|
||||||
rows = [],
|
rows = [],
|
||||||
i=0;
|
i=0;
|
||||||
for (; i<rowCnt; i++) {
|
for (; i<rowCnt; i++) {
|
||||||
rows.push(stackSegs(view.sliceSegs(events, d1, d2)));
|
rows.push(stackSegs(view.sliceSegs(events, $.map(events, visEventEnd), d1, d2)));
|
||||||
addDays(d1, 7);
|
addDays(d1, 7);
|
||||||
addDays(d2, 7);
|
addDays(d2, 7);
|
||||||
}
|
}
|
||||||
|
@ -386,108 +397,51 @@ function Grid(element, options, methods) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function renderSegs(segRows) {
|
|
||||||
var i, len = segRows.length, levels,
|
function renderSegs(segCols) {
|
||||||
tr, td,
|
_renderDaySegs(
|
||||||
innerDiv,
|
segCols,
|
||||||
top,
|
view,
|
||||||
rowContentHeight,
|
0,
|
||||||
j, segs,
|
viewWidth,
|
||||||
levelHeight,
|
function(i) {
|
||||||
k, seg,
|
return tbody.find('tr:eq('+i+')');
|
||||||
event,
|
},
|
||||||
className,
|
dayContentPositions.left,
|
||||||
startElm, endElm,
|
dayContentPositions.right,
|
||||||
left, right,
|
segmentContainer,
|
||||||
eventElement, eventAnchor,
|
bootstrapEventHandlers
|
||||||
triggerRes;
|
);
|
||||||
for (i=0; i<len; i++) {
|
}
|
||||||
levels = segRows[i];
|
|
||||||
tr = tbody.find('tr:eq('+i+')');
|
|
||||||
td = tr.find('td:first');
|
|
||||||
innerDiv = td.find('div.fc-day-content div').css('position', 'relative');
|
function visEventEnd(event) { // returns exclusive 'visible' end, for rendering
|
||||||
top = safePosition(innerDiv, td, tr, tbody).top;
|
if (event.end) {
|
||||||
rowContentHeight = 0;
|
var end = cloneDate(event.end);
|
||||||
for (j=0; j<levels.length; j++) {
|
return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
|
||||||
segs = levels[j];
|
}else{
|
||||||
levelHeight = 0;
|
return addDays(cloneDate(event.start), 1);
|
||||||
for (k=0; k<segs.length; k++) {
|
}
|
||||||
seg = segs[k];
|
}
|
||||||
event = seg.event;
|
|
||||||
className = 'fc-event fc-event-hori ';
|
|
||||||
startElm = seg.isStart ?
|
|
||||||
tr.find('td:eq('+((seg.start.getDay()-Math.max(firstDay,nwe)+colCnt)%colCnt)+') div div') :
|
function bootstrapEventHandlers(event, seg, eventElement) {
|
||||||
tbody;
|
var attached = false;
|
||||||
endElm = seg.isEnd ?
|
eventElement.mouseover(function(ev) {
|
||||||
tr.find('td:eq('+((seg.end.getDay()-Math.max(firstDay,nwe)+colCnt-1)%colCnt)+') div div') :
|
if (!attached) {
|
||||||
tbody;
|
view.eventElementHandlers(event, eventElement);
|
||||||
if (rtl) {
|
if (event.editable || event.editable == undefined && options.editable) {
|
||||||
left = endElm.position().left;
|
draggableEvent(event, eventElement);
|
||||||
right = startElm.position().left + startElm.width();
|
if (seg.isEnd) {
|
||||||
if (seg.isStart) {
|
view.resizableDayEvent(event, eventElement, colWidth);
|
||||||
className += 'fc-corner-right ';
|
|
||||||
}
|
|
||||||
if (seg.isEnd) {
|
|
||||||
className += 'fc-corner-left ';
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
left = startElm.position().left;
|
|
||||||
right = endElm.position().left + endElm.width();
|
|
||||||
if (seg.isStart) {
|
|
||||||
className += 'fc-corner-left ';
|
|
||||||
}
|
|
||||||
if (seg.isEnd) {
|
|
||||||
className += 'fc-corner-right ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eventElement = $("<div class='" + className + event.className.join(' ') + "'/>")
|
|
||||||
.append(eventAnchor = $("<a/>")
|
|
||||||
.append(event.allDay || !seg.isStart ? null :
|
|
||||||
$("<span class='fc-event-time'/>")
|
|
||||||
.html(formatDates(event.start, event.end, view.option('timeFormat'), options)))
|
|
||||||
.append($("<span class='fc-event-title'/>")
|
|
||||||
.text(event.title)));
|
|
||||||
if (event.url) {
|
|
||||||
eventAnchor.attr('href', event.url);
|
|
||||||
}
|
|
||||||
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
|
||||||
if (triggerRes !== false) {
|
|
||||||
if (triggerRes && typeof triggerRes != 'boolean') {
|
|
||||||
eventElement = $(triggerRes);
|
|
||||||
}
|
|
||||||
eventElement
|
|
||||||
.css({
|
|
||||||
position: 'absolute',
|
|
||||||
top: top,
|
|
||||||
left: left + (rtlLeftDiff||0),
|
|
||||||
zIndex: 8
|
|
||||||
})
|
|
||||||
.appendTo(element);
|
|
||||||
setOuterWidth(eventElement, right-left, true);
|
|
||||||
if (rtl && rtlLeftDiff == undefined) {
|
|
||||||
// bug in IE6 where offsets are miscalculated with direction:rtl
|
|
||||||
rtlLeftDiff = left - eventElement.position().left;
|
|
||||||
if (rtlLeftDiff) {
|
|
||||||
eventElement.css('left', left + rtlLeftDiff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.eventElementHandlers(event, eventElement);
|
|
||||||
if (event.editable || event.editable == undefined && options.editable) {
|
|
||||||
draggableEvent(event, eventElement);
|
|
||||||
if (seg.isEnd) {
|
|
||||||
view.resizableDayEvent(event, eventElement, colWidth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.reportEventElement(event, eventElement);
|
|
||||||
view.trigger('eventAfterRender', event, event, eventElement);
|
|
||||||
levelHeight = Math.max(levelHeight, eventElement.outerHeight(true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rowContentHeight += levelHeight;
|
attached = true;
|
||||||
top += levelHeight;
|
view.trigger('eventMouseover', this, event, ev); // TODO: make sure this isn't being fired twice
|
||||||
}
|
}
|
||||||
innerDiv.height(rowContentHeight);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -553,3 +507,131 @@ function Grid(element, options, methods) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function _renderDaySegs(segRows, view, minLeft, maxLeft, getTr, dayContentLeft, dayContentRight, segmentContainer, bootstrapEventHandlers) {
|
||||||
|
|
||||||
|
var options=view.options,
|
||||||
|
rtl=options.isRTL,
|
||||||
|
event,
|
||||||
|
className,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
eventLefts=[],
|
||||||
|
eventRights=[],
|
||||||
|
html='',
|
||||||
|
eventElements,
|
||||||
|
eventElement,
|
||||||
|
triggerRes,
|
||||||
|
eventOuterHeights=[],
|
||||||
|
eventHSides=[],
|
||||||
|
l=0,
|
||||||
|
i=0, len=segRows.length, levels,
|
||||||
|
tr,
|
||||||
|
td,
|
||||||
|
innerDiv,
|
||||||
|
top,
|
||||||
|
rowContentHeight,
|
||||||
|
j, segs,
|
||||||
|
k, seg;
|
||||||
|
|
||||||
|
// calculate desired position/dimensions, create html
|
||||||
|
eachLeaf(segRows, function(l, seg) {
|
||||||
|
event = seg.event;
|
||||||
|
className = 'fc-event fc-event-hori ';
|
||||||
|
if (rtl) {
|
||||||
|
if (seg.isStart) {
|
||||||
|
className += 'fc-corner-right ';
|
||||||
|
}
|
||||||
|
if (seg.isEnd) {
|
||||||
|
className += 'fc-corner-left ';
|
||||||
|
}
|
||||||
|
left = seg.isEnd ? dayContentLeft(seg.end.getDay()-1) : minLeft;
|
||||||
|
right = seg.isStart ? dayContentRight(seg.start.getDay()) : maxLeft;
|
||||||
|
}else{
|
||||||
|
if (seg.isStart) {
|
||||||
|
className += 'fc-corner-left ';
|
||||||
|
}
|
||||||
|
if (seg.isEnd) {
|
||||||
|
className += 'fc-corner-right ';
|
||||||
|
}
|
||||||
|
left = seg.isStart ? dayContentLeft(seg.start.getDay()) : minLeft;
|
||||||
|
right = seg.isEnd ? dayContentRight(seg.end.getDay()-1) : maxLeft;
|
||||||
|
}
|
||||||
|
eventLefts[l] = left;
|
||||||
|
eventRights[l] = right;
|
||||||
|
html +=
|
||||||
|
"<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;left:"+left+"px'>" +
|
||||||
|
"<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
||||||
|
(!event.allDay && seg.isStart ?
|
||||||
|
"<span class='fc-event-time'>" +
|
||||||
|
htmlEscape(formatDates(event.start, event.end, view.option('timeFormat'), options)) +
|
||||||
|
"</span>"
|
||||||
|
:'') +
|
||||||
|
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
||||||
|
"</a>" +
|
||||||
|
"</div>";
|
||||||
|
});
|
||||||
|
segmentContainer.html(html);
|
||||||
|
eventElements = segmentContainer.children();
|
||||||
|
|
||||||
|
// retrieve elements, run through eventRender callback, record outer-edge dimensions
|
||||||
|
eachLeaf(segRows, function(l, seg) {
|
||||||
|
event = seg.event;
|
||||||
|
eventElement = eventElements.eq(l);
|
||||||
|
triggerRes = view.trigger('eventRender', event, event, eventElement);
|
||||||
|
if (triggerRes === false) {
|
||||||
|
eventElement.remove();
|
||||||
|
}else{
|
||||||
|
if (triggerRes && triggerRes !== true) {
|
||||||
|
eventElement.remove();
|
||||||
|
eventElement = $(triggerRes)
|
||||||
|
.css('left', eventLefts[l])
|
||||||
|
.appendTo(segmentContainer);
|
||||||
|
}
|
||||||
|
seg.element = eventElement;
|
||||||
|
eventOuterHeights[l] = eventElement.outerHeight(true);
|
||||||
|
eventHSides[l] = hsides(eventElement, true);
|
||||||
|
bootstrapEventHandlers(event, seg, eventElement);
|
||||||
|
view.reportEventElement(event, eventElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// set all positions/dimensions at once
|
||||||
|
for (; i<len; i++) {
|
||||||
|
levels = segRows[i];
|
||||||
|
tr = getTr(i);
|
||||||
|
td = tr.find('td:first');
|
||||||
|
innerDiv = td.find('div.fc-day-content div')
|
||||||
|
.css('position', 'relative')
|
||||||
|
.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++) {
|
||||||
|
segs = levels[j];
|
||||||
|
levelHeight = 0;
|
||||||
|
for (k=0; k<segs.length; k++) {
|
||||||
|
seg = segs[k];
|
||||||
|
if (eventElement = seg.element) {
|
||||||
|
eventElement.css('top', top);
|
||||||
|
//if (rtl && rtlLeftDiff == undefined) {
|
||||||
|
// // bug in IE6 where offsets are miscalculated with direction:rtl
|
||||||
|
// rtlLeftDiff = eventLefts[l] - eventElement.position().left;
|
||||||
|
// if (rtlLeftDiff) {
|
||||||
|
// eventElement.css('left', eventLefts[l] + rtlLeftDiff);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
eventElement.width(eventRights[l] - eventLefts[l] - eventHSides[l]);
|
||||||
|
event = seg.event;
|
||||||
|
view.trigger('eventAfterRender', event, event, eventElement);
|
||||||
|
levelHeight = Math.max(levelHeight, eventOuterHeights[l]);
|
||||||
|
}
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
rowContentHeight += levelHeight;
|
||||||
|
top += levelHeight;
|
||||||
|
}
|
||||||
|
innerDiv.height(rowContentHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
4376
src/jquery/jquery-uncompressed.js
vendored
Normal file
4376
src/jquery/jquery-uncompressed.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
26
src/main.js
26
src/main.js
|
@ -149,7 +149,9 @@ $.fn.fullCalendar = function(options) {
|
||||||
element = $(_element).addClass('fc'),
|
element = $(_element).addClass('fc'),
|
||||||
elementWidth,
|
elementWidth,
|
||||||
content = $("<div class='fc-content " + tm + "-widget-content' style='position:relative'/>").prependTo(_element), // relative for ie6
|
content = $("<div class='fc-content " + tm + "-widget-content' style='position:relative'/>").prependTo(_element), // relative for ie6
|
||||||
|
contentWidth,
|
||||||
contentHeight;
|
contentHeight;
|
||||||
|
|
||||||
if (options.isRTL) {
|
if (options.isRTL) {
|
||||||
element.addClass('fc-rtl');
|
element.addClass('fc-rtl');
|
||||||
}
|
}
|
||||||
|
@ -214,11 +216,12 @@ $.fn.fullCalendar = function(options) {
|
||||||
function render(inc, forceUpdateSize) {
|
function render(inc, forceUpdateSize) {
|
||||||
if ((elementWidth = _element.offsetWidth) !== 0) { // visible on the screen
|
if ((elementWidth = _element.offsetWidth) !== 0) { // visible on the screen
|
||||||
if (!contentHeight) {
|
if (!contentHeight) {
|
||||||
|
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.visStart || date > view.visEnd ) { // !view.date means it hasn't been rendered yet
|
||||||
fixContentSize();
|
fixContentSize();
|
||||||
view.render(date, inc || 0, 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)
|
||||||
if (!eventStart || view.visStart < eventStart || view.visEnd > eventEnd) {
|
if (!eventStart || view.visStart < eventStart || view.visEnd > eventEnd) {
|
||||||
fetchEvents(callback);
|
fetchEvents(callback);
|
||||||
|
@ -230,12 +233,14 @@ $.fn.fullCalendar = function(options) {
|
||||||
view.date = cloneDate(date);
|
view.date = cloneDate(date);
|
||||||
}
|
}
|
||||||
else if (view.sizeDirty || forceUpdateSize) {
|
else if (view.sizeDirty || forceUpdateSize) {
|
||||||
view.updateSize(contentHeight);
|
view.updateSize(contentWidth, contentHeight);
|
||||||
view.rerenderEvents();
|
view.rerenderEvents(); // TODO: could probably skip recompile??
|
||||||
}
|
}
|
||||||
else if (view.eventsDirty) {
|
else if (view.eventsDirty) {
|
||||||
// ensure events are rerendered if another view messed with them
|
// ensure events are rerendered if another view messed with them
|
||||||
// pass in 'events' b/c event might have been added/removed
|
// pass in 'events' b/c event might have been added/removed
|
||||||
|
// executed on a switchView
|
||||||
|
// TODO: should this be inclusive with sizeDirty and forceUpdateSize??
|
||||||
view.clearEvents();
|
view.clearEvents();
|
||||||
view.renderEvents(events);
|
view.renderEvents(events);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +262,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// marks other views' events as dirty
|
// marks other views' events as dirty
|
||||||
function eventsDirtyExcept(exceptView) {
|
function eventsDirtyExcept(exceptView) { // TODO: otherViewsEventsDirty
|
||||||
$.each(viewInstances, function() {
|
$.each(viewInstances, function() {
|
||||||
if (this != exceptView) {
|
if (this != exceptView) {
|
||||||
this.eventsDirty = true;
|
this.eventsDirty = true;
|
||||||
|
@ -283,16 +288,17 @@ $.fn.fullCalendar = function(options) {
|
||||||
|
|
||||||
// called when we know the element size has changed
|
// called when we know the element size has changed
|
||||||
function sizeChanged(fix) {
|
function sizeChanged(fix) {
|
||||||
|
contentWidth = content.width();
|
||||||
contentHeight = calculateContentHeight();
|
contentHeight = calculateContentHeight();
|
||||||
if (fix) {
|
if (fix) {
|
||||||
fixContentSize();
|
fixContentSize();
|
||||||
}
|
}
|
||||||
view.updateSize(contentHeight);
|
view.updateSize(contentWidth, contentHeight);
|
||||||
if (fix) {
|
if (fix) {
|
||||||
unfixContentSize();
|
unfixContentSize();
|
||||||
}
|
}
|
||||||
sizesDirtyExcept(view);
|
sizesDirtyExcept(view);
|
||||||
view.rerenderEvents(true);
|
view.rerenderEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate what the height of the content should be
|
// calculate what the height of the content should be
|
||||||
|
@ -301,9 +307,9 @@ $.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) - horizontalSides(content);
|
return options.height - (header ? header.height() : 0) - horizontalSides(content); // TODO: shouldn't this be vertical sides??
|
||||||
}
|
}
|
||||||
return elementWidth / Math.max(options.aspectRatio, .5);
|
return Math.round(contentWidth / Math.max(options.aspectRatio, .5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -776,7 +782,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$(window).resize(windowResize);
|
//$(window).resize(windowResize);
|
||||||
|
|
||||||
|
|
||||||
// let's begin...
|
// let's begin...
|
||||||
|
@ -787,7 +793,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
render();
|
render();
|
||||||
content.hide().show(); // needed for IE 6
|
content.hide().show(); // needed for IE 6
|
||||||
view.rerenderEvents(); // needed for IE 7
|
view.rerenderEvents(); // needed for IE 7 // TODO: could probably skip recompile
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
135
src/util.js
135
src/util.js
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
var DAY_MS = 86400000,
|
var DAY_MS = 86400000,
|
||||||
HOUR_MS = 3600000,
|
HOUR_MS = 3600000,
|
||||||
MINUTE_MS = 60000;
|
MINUTE_MS = 60000,
|
||||||
|
arrayPop = Array.prototype.pop; // for eachLeaf
|
||||||
|
|
||||||
function addYears(d, n, keepTime) {
|
function addYears(d, n, keepTime) {
|
||||||
d.setFullYear(d.getFullYear() + n);
|
d.setFullYear(d.getFullYear() + n);
|
||||||
|
@ -300,39 +301,35 @@ var dateFormatters = {
|
||||||
function setOuterWidth(element, width, includeMargins) {
|
function setOuterWidth(element, width, includeMargins) {
|
||||||
element.each(function() {
|
element.each(function() {
|
||||||
var e = $(this);
|
var e = $(this);
|
||||||
var w = width - horizontalSides(e);
|
e.width(width - hsides(e, includeMargins));
|
||||||
if (includeMargins) {
|
|
||||||
w -= (parseInt(e.css('margin-left')) || 0) +
|
|
||||||
(parseInt(e.css('margin-right')) || 0);
|
|
||||||
}
|
|
||||||
e.width(w);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function horizontalSides(e) {
|
function hsides(e, includeMargins) {
|
||||||
return (parseInt(e.css('border-left-width')) || 0) +
|
return (parseInt(e.css('border-left-width')) || 0) +
|
||||||
(parseInt(e.css('padding-left')) || 0) +
|
(parseInt(e.css('padding-left')) || 0) +
|
||||||
(parseInt(e.css('padding-right')) || 0) +
|
(parseInt(e.css('padding-right')) || 0) +
|
||||||
(parseInt(e.css('border-right-width')) || 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() {
|
||||||
var e = $(this);
|
var e = $(this);
|
||||||
var h = height - verticalSides(e);
|
e.height(height - vsides(e, includeMargins));
|
||||||
if (includeMargins) {
|
|
||||||
h -= (parseInt(e.css('margin-top')) || 0) +
|
|
||||||
(parseInt(e.css('margin-bottom')) || 0);
|
|
||||||
}
|
|
||||||
e.height(h);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function verticalSides(e) {
|
function vsides(e, includeMargins) {
|
||||||
return (parseInt(e.css('border-top-width')) || 0) +
|
return (parseInt(e.css('border-top-width')) || 0) +
|
||||||
(parseInt(e.css('padding-top')) || 0) +
|
(parseInt(e.css('padding-top')) || 0) +
|
||||||
(parseInt(e.css('padding-bottom')) || 0) +
|
(parseInt(e.css('padding-bottom')) || 0) +
|
||||||
(parseInt(e.css('border-bottom-width')) || 0);
|
(parseInt(e.css('border-bottom-width')) || 0) +
|
||||||
|
(includeMargins ?
|
||||||
|
(parseInt(e.css('margin-top')) || 0) + (parseInt(e.css('margin-bottom')) || 0)
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -340,22 +337,24 @@ function verticalSides(e) {
|
||||||
/* Position Calculation
|
/* Position Calculation
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
// nasty bugs in opera 9.25
|
// nasty bugs in opera 9.25
|
||||||
// position() returning relative to direct parent
|
// position()'s top returning incorrectly with TR/TD or elements within TD
|
||||||
|
|
||||||
var operaPositionBug;
|
var topBug;
|
||||||
|
|
||||||
function reportTBody(tbody) {
|
function topCorrect(tr) { // tr/th/td or anything else
|
||||||
if (operaPositionBug == undefined) {
|
if (topBug !== false) {
|
||||||
operaPositionBug = tbody.position().top != tbody.find('tr').position().top;
|
var cell;
|
||||||
|
if (tr.is('th,td')) {
|
||||||
|
tr = (cell = tr).parent();
|
||||||
|
}
|
||||||
|
if (topBug == undefined && tr.is('tr')) {
|
||||||
|
topBug = tr.position().top != tr.children().position().top;
|
||||||
|
}
|
||||||
|
if (topBug) {
|
||||||
|
return tr.parent().position().top + (cell ? tr.position().top - cell.position().top : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
function safePosition(element, td, tr, tbody) {
|
|
||||||
var position = element.position();
|
|
||||||
if (operaPositionBug) {
|
|
||||||
position.top += tbody.position().top + tr.position().top - td.position().top;
|
|
||||||
}
|
|
||||||
return position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -365,24 +364,23 @@ function safePosition(element, td, tr, tbody) {
|
||||||
|
|
||||||
function HoverMatrix(changeCallback) {
|
function HoverMatrix(changeCallback) {
|
||||||
|
|
||||||
var tops=[], lefts=[],
|
var t=this,
|
||||||
|
tops=[], lefts=[],
|
||||||
prevRowE, prevColE,
|
prevRowE, prevColE,
|
||||||
origRow, origCol,
|
origRow, origCol,
|
||||||
currRow, currCol;
|
currRow, currCol;
|
||||||
|
|
||||||
this.row = function(e, topBug) {
|
t.row = function(e) {
|
||||||
prevRowE = $(e);
|
prevRowE = $(e);
|
||||||
tops.push(prevRowE.offset().top + (
|
tops.push(prevRowE.offset().top + topCorrect(prevRowE));
|
||||||
(operaPositionBug && prevRowE.is('tr')) ? prevRowE.parent().position().top : 0
|
|
||||||
));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.col = function(e) {
|
t.col = function(e) {
|
||||||
prevColE = $(e);
|
prevColE = $(e);
|
||||||
lefts.push(prevColE.offset().left);
|
lefts.push(prevColE.offset().left);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.mouse = function(x, y) {
|
t.mouse = function(x, y) {
|
||||||
if (origRow == undefined) {
|
if (origRow == undefined) {
|
||||||
tops.push(tops[tops.length-1] + prevRowE.outerHeight());
|
tops.push(tops[tops.length-1] + prevRowE.outerHeight());
|
||||||
lefts.push(lefts[lefts.length-1] + prevColE.outerWidth());
|
lefts.push(lefts[lefts.length-1] + prevColE.outerWidth());
|
||||||
|
@ -397,13 +395,13 @@ function HoverMatrix(changeCallback) {
|
||||||
currRow = r;
|
currRow = r;
|
||||||
currCol = c;
|
currCol = c;
|
||||||
if (r == -1 || c == -1) {
|
if (r == -1 || c == -1) {
|
||||||
this.cell = null;
|
t.cell = null;
|
||||||
}else{
|
}else{
|
||||||
if (origRow == undefined) {
|
if (origRow == undefined) {
|
||||||
origRow = r;
|
origRow = r;
|
||||||
origCol = c;
|
origCol = c;
|
||||||
}
|
}
|
||||||
this.cell = {
|
t.cell = {
|
||||||
row: r,
|
row: r,
|
||||||
col: c,
|
col: c,
|
||||||
top: tops[r],
|
top: tops[r],
|
||||||
|
@ -415,7 +413,7 @@ function HoverMatrix(changeCallback) {
|
||||||
colDelta: c-origCol
|
colDelta: c-origCol
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
changeCallback(this.cell);
|
changeCallback(t.cell);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -433,7 +431,7 @@ function zeroPad(n) {
|
||||||
return (n < 10 ? '0' : '') + n;
|
return (n < 10 ? '0' : '') + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
function smartProperty(obj, name) { // get a camel-cased/namespaced property
|
function smartProperty(obj, name) { // get a camel-cased/namespaced property of an object
|
||||||
if (obj[name] != undefined) {
|
if (obj[name] != undefined) {
|
||||||
return obj[name];
|
return obj[name];
|
||||||
}
|
}
|
||||||
|
@ -448,4 +446,59 @@ function smartProperty(obj, name) { // get a camel-cased/namespaced property
|
||||||
return obj[''];
|
return obj[''];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function htmlEscape(s) {
|
||||||
|
return s
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.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) {
|
||||||
|
|
||||||
|
var t = this,
|
||||||
|
elements = {},
|
||||||
|
lefts = {},
|
||||||
|
rights = {};
|
||||||
|
|
||||||
|
function e(i) {
|
||||||
|
return elements[i] =
|
||||||
|
elements[i] || getElement(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
t.left = function(i) {
|
||||||
|
return lefts[i] =
|
||||||
|
lefts[i] == undefined ? e(i).position().left : lefts[i];
|
||||||
|
};
|
||||||
|
|
||||||
|
t.right = function(i) {
|
||||||
|
return rights[i] =
|
||||||
|
rights[i] == undefined ? t.left(i) + e(i).width() : rights[i];
|
||||||
|
};
|
||||||
|
|
||||||
|
t.clear = function() {
|
||||||
|
elements = {};
|
||||||
|
lefts = {};
|
||||||
|
rights = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
17
src/view.js
17
src/view.js
|
@ -14,7 +14,6 @@ var viewMethods = {
|
||||||
* - visStart
|
* - visStart
|
||||||
* - visEnd
|
* - visEnd
|
||||||
* - defaultEventEnd(event)
|
* - defaultEventEnd(event)
|
||||||
* - visEventEnd(event)
|
|
||||||
* - render(events)
|
* - render(events)
|
||||||
* - rerenderEvents()
|
* - rerenderEvents()
|
||||||
*
|
*
|
||||||
|
@ -31,7 +30,6 @@ var viewMethods = {
|
||||||
init: function(element, options) {
|
init: function(element, options) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.cachedEvents = [];
|
|
||||||
this.eventsByID = {};
|
this.eventsByID = {};
|
||||||
this.eventElements = [];
|
this.eventElements = [];
|
||||||
this.eventElementsByID = {};
|
this.eventElementsByID = {};
|
||||||
|
@ -61,8 +59,7 @@ var viewMethods = {
|
||||||
|
|
||||||
reportEvents: function(events) { // events are already normalized at this point
|
reportEvents: function(events) { // events are already normalized at this point
|
||||||
var i, len=events.length, event,
|
var i, len=events.length, event,
|
||||||
eventsByID = this.eventsByID = {},
|
eventsByID = this.eventsByID = {};
|
||||||
cachedEvents = this.cachedEvents = [];
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
event = events[i];
|
event = events[i];
|
||||||
if (eventsByID[event._id]) {
|
if (eventsByID[event._id]) {
|
||||||
|
@ -70,7 +67,6 @@ var viewMethods = {
|
||||||
}else{
|
}else{
|
||||||
eventsByID[event._id] = [event];
|
eventsByID[event._id] = [event];
|
||||||
}
|
}
|
||||||
cachedEvents.push(event);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -92,10 +88,7 @@ var viewMethods = {
|
||||||
|
|
||||||
// event element manipulation
|
// event element manipulation
|
||||||
|
|
||||||
clearEvents: function() { // only remove ELEMENTS
|
_clearEvents: function() { // only resets hashes
|
||||||
$.each(this.eventElements, function() {
|
|
||||||
this.remove();
|
|
||||||
});
|
|
||||||
this.eventElements = [];
|
this.eventElements = [];
|
||||||
this.eventElementsByID = {};
|
this.eventElementsByID = {};
|
||||||
},
|
},
|
||||||
|
@ -273,7 +266,7 @@ var viewMethods = {
|
||||||
|
|
||||||
// event rendering utilities
|
// event rendering utilities
|
||||||
|
|
||||||
sliceSegs: function(events, start, end) {
|
sliceSegs: function(events, visEventEnds, start, end) {
|
||||||
var segs = [],
|
var segs = [],
|
||||||
i, len=events.length, event,
|
i, len=events.length, event,
|
||||||
eventStart, eventEnd,
|
eventStart, eventEnd,
|
||||||
|
@ -282,7 +275,7 @@ var viewMethods = {
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
event = events[i];
|
event = events[i];
|
||||||
eventStart = event.start;
|
eventStart = event.start;
|
||||||
eventEnd = this.visEventEnd(event);
|
eventEnd = visEventEnds[i];
|
||||||
if (eventEnd > start && eventStart < end) {
|
if (eventEnd > start && eventStart < end) {
|
||||||
if (eventStart < start) {
|
if (eventStart < start) {
|
||||||
segStart = cloneDate(start);
|
segStart = cloneDate(start);
|
||||||
|
@ -359,3 +352,5 @@ function segsCollide(seg1, seg2) {
|
||||||
return seg1.end > seg2.start && seg1.start < seg2.end;
|
return seg1.end > seg2.start && seg1.start < seg2.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ else if (_build) {
|
||||||
includeJS('../build/fullcalendar/jquery/ui.resizable.js');
|
includeJS('../build/fullcalendar/jquery/ui.resizable.js');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
includeJS('../src/jquery/jquery.js');
|
includeJS('../src/jquery/jquery-uncompressed.js');
|
||||||
includeJS('../src/jquery/ui.core.js');
|
includeJS('../src/jquery/ui.core.js');
|
||||||
includeJS('../src/jquery/ui.draggable.js');
|
includeJS('../src/jquery/ui.draggable.js');
|
||||||
includeJS('../src/jquery/ui.resizable.js');
|
includeJS('../src/jquery/ui.resizable.js');
|
||||||
|
|
47
tests/many_agenda_events.html
Normal file
47
tests/many_agenda_events.html
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||||
|
<script type='text/javascript'>DISABLE_FIREBUG_LITE=true</script>
|
||||||
|
<script type='text/javascript' src='loader.js'></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
$('#calendar').fullCalendar({
|
||||||
|
defaultView: 'agendaWeek',
|
||||||
|
year: 2009,
|
||||||
|
month: 11,
|
||||||
|
date: 16,
|
||||||
|
header: {
|
||||||
|
left: 'prev,next today',
|
||||||
|
center: 'title',
|
||||||
|
right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
|
||||||
|
},
|
||||||
|
editable: true,
|
||||||
|
events: 'many_agenda_events_json.txt'
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style type='text/css'>
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin-top: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calendar {
|
||||||
|
width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='calendar'></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
2046
tests/many_agenda_events_json.txt
Normal file
2046
tests/many_agenda_events_json.txt
Normal file
File diff suppressed because it is too large
Load diff
|
@ -7,19 +7,16 @@
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
var date = new Date();
|
|
||||||
var d = date.getDate();
|
|
||||||
var m = date.getMonth();
|
|
||||||
var y = date.getFullYear();
|
|
||||||
|
|
||||||
$('#calendar').fullCalendar({
|
$('#calendar').fullCalendar({
|
||||||
|
year: 2009,
|
||||||
|
month: 11,
|
||||||
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'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue