first round of commits for 1.4, agenda view
This commit is contained in:
parent
1cb53661fd
commit
8e0312a750
488
src/agenda.js
488
src/agenda.js
|
@ -1,199 +1,194 @@
|
||||||
|
|
||||||
function segAfters(levels) { // TODO: put in agenda.js
|
/* Agenda Views: agendaWeek/agendaDay
|
||||||
var i, j, k, level, seg, seg2;
|
-----------------------------------------------------------------------------*/
|
||||||
for (i=levels.length-1; i>0; i--) {
|
|
||||||
level = levels[i];
|
|
||||||
for (j=0; j<level.length; j++) {
|
|
||||||
seg = level[j];
|
|
||||||
for (k=0; k<segLevels[i-1].length; k++) {
|
|
||||||
seg2 = segLevels[i-1][k];
|
|
||||||
if (segsCollide(seg, seg2)) {
|
|
||||||
seg2.after = Math.max(seg2.after, seg.after+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************* week view ***********************************/
|
setDefaults({
|
||||||
|
slotMinutes: 30,
|
||||||
$.fullCalendar.views.week = function(element, options) {
|
defaultEventMinutes: 120,
|
||||||
|
agendaTimeFormat: 'g:i{ - g:i}', // todo: merge into object w/ timeFormat
|
||||||
var agenda = new Agenda(element, options);
|
axisFormat: 'htt',
|
||||||
|
agendaDragOpacity: .5 // maybe merge into object
|
||||||
safeExtend(options, {
|
});
|
||||||
weekTitleFormat: 'M j Y{ - M j Y}' // TODO: shift around
|
|
||||||
});
|
|
||||||
|
|
||||||
agenda.render = function(date, delta, fetchEvents) {
|
|
||||||
|
|
||||||
|
views.agendaWeek = function(element, options) {
|
||||||
|
return new Agenda(element, options, {
|
||||||
|
render: function(date, delta, fetchEvents) {
|
||||||
if (delta) {
|
if (delta) {
|
||||||
addDays(date, delta * 7);
|
addDays(date, delta * 7);
|
||||||
}
|
}
|
||||||
|
this.title = formatDates(
|
||||||
this.start = addDays(cloneDate(date), -date.getDay());
|
this.start = this.visStart = addDays(cloneDate(date), -((date.getDay() - options.firstDay + 7) % 7)),
|
||||||
this.end = addDays(cloneDate(this.start), 7);
|
addDays(cloneDate(this.end = this.visEnd = addDays(cloneDate(this.start), 7)), -1),
|
||||||
this.title = formatDates(this.start, this.end, options.weekTitleFormat);
|
strProp(options.titleFormat, 'week'),
|
||||||
|
options
|
||||||
this.renderAgenda(fetchEvents);
|
);
|
||||||
|
this.renderAgenda(7, strProp(options.columnFormat, 'week'), fetchEvents);
|
||||||
};
|
}
|
||||||
|
});
|
||||||
return agenda;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************* day view *************************************/
|
views.agendaDay = function(element, options) {
|
||||||
|
return new Agenda(element, options, {
|
||||||
$.fullCalendar.views.day = function(element, options) {
|
render: function(date, delta, fetchEvents) {
|
||||||
|
|
||||||
var agenda = new Agenda(element, options);
|
|
||||||
|
|
||||||
safeExtend(options, {
|
|
||||||
dayTitleFormat: 'l F j Y' // TODO: shift around
|
|
||||||
});
|
|
||||||
|
|
||||||
agenda.render = function(date, delta, fetchEvents) {
|
|
||||||
|
|
||||||
if (delta) {
|
if (delta) {
|
||||||
addDays(date, delta);
|
addDays(date, delta);
|
||||||
}
|
}
|
||||||
|
this.title = formatDate(date, strProp(options.titleFormat, 'day'), options);
|
||||||
this.start = cloneDate(date, true);
|
this.start = this.visStart = cloneDate(date, true);
|
||||||
this.end = addDays(cloneDate(date), 1);
|
this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
||||||
this.title = formatDate(date, options.dayTitleFormat);
|
this.renderAgenda(1, strProp(options.columnFormat, 'day'), fetchEvents);
|
||||||
|
}
|
||||||
this.renderAgenda(fetchEvents);
|
});
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return agenda;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*********************** shared by month and day views *************************/
|
function Agenda(element, options, methods) {
|
||||||
|
|
||||||
function Agenda(element, options) {
|
var head, body, bodyContent, bodyTable, bg,
|
||||||
|
colCnt,
|
||||||
safeExtend(options, {
|
timeWidth, colWidth, rowHeight,
|
||||||
slotMinutes: 30,
|
|
||||||
defaultEventMinutes: 120,
|
|
||||||
agendaEventTimeFormat: 'g:i{ - g:i}',
|
|
||||||
agendaSideTimeFormat: 'ga',
|
|
||||||
agendaEventDragOpacity: .5
|
|
||||||
});
|
|
||||||
|
|
||||||
var view = this,
|
|
||||||
head, body, panel, bg,
|
|
||||||
dayCnt,
|
|
||||||
dayWidth, slotHeight,
|
|
||||||
timeWidth,
|
|
||||||
cachedEvents,
|
|
||||||
cachedSlotSegs, cachedDaySegs,
|
cachedSlotSegs, cachedDaySegs,
|
||||||
eventElements = [],
|
tm, firstDay,
|
||||||
eventElementsByID = {},
|
rtl, dis, dit, // day index sign / translate
|
||||||
eventsByID = {};
|
// ...
|
||||||
|
|
||||||
|
view = $.extend(this, viewMethods, methods, {
|
||||||
|
renderAgenda: renderAgenda,
|
||||||
|
renderEvents: renderEvents,
|
||||||
|
rerenderEvents: rerenderEvents,
|
||||||
|
updateSize: updateSize,
|
||||||
|
defaultEventEnd: function(event) {
|
||||||
|
return addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
||||||
|
},
|
||||||
|
visEventEnd: function(event) {
|
||||||
|
return addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
view.init(element, options);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Time-slot rendering
|
||||||
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
element.addClass('fc-agenda').css('position', 'relative');
|
element.addClass('fc-agenda').css('position', 'relative');
|
||||||
|
if (element.disableSelection) {
|
||||||
|
element.disableSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAgenda(c, colFormat, fetchEvents) { // TODO: get z-indexes sorted out
|
||||||
|
colCnt = c;
|
||||||
|
|
||||||
|
// update option-derived variables
|
||||||
|
tm = options.theme ? 'ui' : 'fc';
|
||||||
|
firstDay = options.firstDay;
|
||||||
|
if (rtl = options.isRTL) {
|
||||||
|
dis = -1;
|
||||||
|
dit = colCnt - 1;
|
||||||
|
}else{
|
||||||
|
dis = 1;
|
||||||
|
dit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************** cell rendering ********************************/
|
var d0 = rtl ? addDays(cloneDate(view.visEnd), -1) : cloneDate(view.visStart),
|
||||||
|
d = cloneDate(d0),
|
||||||
|
today = clearTime(new Date());
|
||||||
|
|
||||||
|
if (!head) { // first time rendering, build from scratch
|
||||||
|
|
||||||
this.renderAgenda = function(fetchEvents) { // TODO: get z-indexes sorted out
|
var i,
|
||||||
|
minutes,
|
||||||
var start = view.start,
|
slotNormal = options.slotMinutes % 15 == 0, //...
|
||||||
end = view.end,
|
|
||||||
today = getToday(),
|
|
||||||
todayI = -1,
|
|
||||||
tm = options.theme ? 'ui' : 'fc',
|
|
||||||
slotNormal = options.slotMinutes % 15 == 0,
|
|
||||||
dayAbbrevs = $.fullCalendar.dayAbbrevs;
|
|
||||||
|
|
||||||
if (!head) { // first time rendering, build from scratch TODO: need all the nbsp's?
|
|
||||||
|
|
||||||
// head
|
// head
|
||||||
var i, d, dDay, dMinutes,
|
|
||||||
s = "<div class='fc-agenda-head' style='position:relative;z-index:3'>" +
|
s = "<div class='fc-agenda-head' style='position:relative;z-index:3'>" +
|
||||||
"<table style='width:100%' cellpadding='0' cellspacing='0'>" +
|
"<table style='width:100%'>" +
|
||||||
"<tr class='fc-first'>" +
|
"<tr class='fc-first'>" +
|
||||||
"<th class='fc-first " + tm + "-state-default'> </th>";
|
"<th class='fc-leftmost " +
|
||||||
dayCnt = 0;
|
tm + "-state-default'> </th>";
|
||||||
for (d=cloneDate(start); d<end; addDays(d, 1)) {
|
for (i=0; i<colCnt; i++) {
|
||||||
s += "<th class='fc-" +
|
s += "<th class='fc-" +
|
||||||
dayIDs[d.getDay()] + ' ' + // needs to be first
|
dayIDs[d.getDay()] + ' ' + // needs to be first
|
||||||
tm + '-state-default' +
|
tm + '-state-default' +
|
||||||
"'>" + dayAbbrevs[d.getDay()] + "</th>";
|
"'>" + formatDate(d, colFormat, options) + "</th>";
|
||||||
if (+d == +today) {
|
addDays(d, dis);
|
||||||
todayI = dayCnt;
|
|
||||||
}
|
}
|
||||||
dayCnt++;
|
s+= "<th class='" + tm + "-state-default'> </th></tr>" +
|
||||||
}
|
"<tr class='fc-all-day'>" +
|
||||||
s += "<th class='fc-last " + tm + "-state-default'> </th></tr>" +
|
"<th class='fc-axis fc-leftmost " + tm + "-state-default'>all day</th>" +
|
||||||
"<tr class='fc-last'>" +
|
"<td colspan='" + colCnt + "' class='" + tm + "-state-default'>" +
|
||||||
"<th class='fc-first " + tm + "-state-default' style='font-weight:normal;text-align:right;padding:4px 2px'>all day</th>" +
|
"<div class='fc-day-content'><div> </div></div></td>" +
|
||||||
"<td colspan='" + dayCnt + "' class='" + tm + "-state-default'>" +
|
"<th class='" + tm + "-state-default'> </th>" +
|
||||||
"<div class='fc-day-content'><div/></div></td>" +
|
"</tr><tr class='fc-divider'><th colspan='" + (colCnt+2) + "' class='" +
|
||||||
"<th class='fc-last " + tm + "-state-default'> </th>" +
|
tm + "-state-default fc-leftmost'></th></tr></table></div>";
|
||||||
"</tr></table></div>";
|
|
||||||
head = $(s).appendTo(element);
|
head = $(s).appendTo(element);
|
||||||
|
head.find('td').click(slotClick);
|
||||||
|
|
||||||
// body & event panel
|
// body
|
||||||
s = "<div style='position:relative;overflow:hidden'>" +
|
d = new Date(1970, 0, 1);
|
||||||
"<table cellpadding='0' cellspacing='0'>";
|
s = "<table>";
|
||||||
d = getToday();
|
for (i=0; d.getDate() != 2; i++) {
|
||||||
dDay = d.getDay();
|
minutes = d.getMinutes();
|
||||||
for (i=0; d.getDay()==dDay; i++, addMinutes(d, options.slotMinutes)) {
|
|
||||||
dMinutes = d.getMinutes();
|
|
||||||
s += "<tr class='" +
|
s += "<tr class='" +
|
||||||
(i==0 ? 'fc-first' : (dMinutes==0 ? '' : 'fc-minor')) +
|
(i==0 ? 'fc-first' : (minutes==0 ? '' : 'fc-minor')) +
|
||||||
"'><th class='" + tm + "-state-default'>" +
|
"'><th class='fc-axis fc-leftmost " + tm + "-state-default'>" +
|
||||||
(!slotNormal || dMinutes==0 ? formatDate(d, options.agendaSideTimeFormat) : ' ') +
|
((!slotNormal || minutes==0) ? formatDate(d, options.axisFormat) : ' ') +
|
||||||
"</th><td class='fc-slot " + tm + "-state-default'> </td></tr>";
|
"</th><td class='fc-slot" + i + ' ' +
|
||||||
|
tm + "-state-default'><div class='fc-day-content'><div> </div></div></td></tr>";
|
||||||
|
addMinutes(d, options.slotMinutes);
|
||||||
}
|
}
|
||||||
s += "</table></div>";
|
s += "</table>";
|
||||||
body = $("<div class='fc-agenda-body' style='position:relative;z-index:2'/>")
|
body = $("<div class='fc-agenda-body' style='position:relative;z-index:2;overflow:auto'/>")
|
||||||
.append(panel = $(s))
|
.append(bodyContent = $("<div style='position:relative;overflow:hidden'>")
|
||||||
|
.append(bodyTable = $(s)))
|
||||||
.appendTo(element);
|
.appendTo(element);
|
||||||
|
body.find('td').click(slotClick);
|
||||||
|
|
||||||
// background stripes
|
// background stripes
|
||||||
s = "<div class='fc-agenda-bg' style='position:absolute;top:0;z-index:1'>" +
|
d = cloneDate(d0);
|
||||||
"<table style='width:100%;height:100%' cellpadding='0' cellspacing='0'><tr>";
|
s = "<div class='fc-agenda-bg' style='position:absolute;z-index:1'>" +
|
||||||
for (i=0; i<dayCnt; i++) {
|
"<table style='width:100%;height:100%'><tr class='fc-first'>";
|
||||||
|
for (i=0; i<colCnt; i++) {
|
||||||
s += "<td class='fc-" +
|
s += "<td class='fc-" +
|
||||||
dayIDs[i] + ' ' + // needs to be first
|
dayIDs[i] + ' ' + // needs to be first
|
||||||
tm + '-state-default ' +
|
tm + '-state-default ' +
|
||||||
(i==todayI ? tm + '-state-highlight fc-today' : 'fc-not-today') +
|
(i==0 ? 'fc-leftmost ' : '') +
|
||||||
|
(+d == +today ? tm + '-state-highlight fc-today' : 'fc-not-today') +
|
||||||
"'><div class='fc-day-content'><div> </div></div></td>";
|
"'><div class='fc-day-content'><div> </div></div></td>";
|
||||||
|
addDays(d, dis);
|
||||||
}
|
}
|
||||||
s += "</tr></table></div>";
|
s += "</tr></table></div>";
|
||||||
bg = $(s).appendTo(element);
|
bg = $(s).appendTo(element);
|
||||||
|
|
||||||
}else{ // skeleton already built, just modify it
|
}else{ // skeleton already built, just modify it
|
||||||
|
|
||||||
clearEvents();
|
view.clearEvents();
|
||||||
|
|
||||||
|
// redo column header text and class
|
||||||
|
head.find('tr:first th').slice(1, -1).each(function() {
|
||||||
|
$(this).text(formatDate(d, colFormat, options));
|
||||||
|
this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||||
|
addDays(d, dis);
|
||||||
|
});
|
||||||
|
|
||||||
// change classes of background stripes
|
// change classes of background stripes
|
||||||
todayI = Math.round((today - start) / msInDay);
|
d = cloneDate(d0);
|
||||||
bg.find('td').each(function(i) {
|
bg.find('td').each(function() {
|
||||||
if (i == todayI) {
|
this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
||||||
$(this).removeClass('fc-not-today')
|
if (+d == +today) {
|
||||||
|
$(this)
|
||||||
|
.removeClass('fc-not-today')
|
||||||
.addClass('fc-today')
|
.addClass('fc-today')
|
||||||
.addClass(tm + '-state-highlight');
|
.addClass(tm + '-state-highlight');
|
||||||
}else{
|
}else{
|
||||||
$(this).addClass('fc-not-today')
|
$(this)
|
||||||
|
.addClass('fc-not-today')
|
||||||
.removeClass('fc-today')
|
.removeClass('fc-today')
|
||||||
.removeClass(tm + '-state-highlight');
|
.removeClass(tm + '-state-highlight');
|
||||||
}
|
}
|
||||||
|
addDays(d, dis);
|
||||||
});
|
});
|
||||||
|
|
||||||
// if 1-day view, change day-of-week class and header text
|
|
||||||
if (dayCnt == 1) {
|
|
||||||
var th = head.find('th:eq(1)').html(dayAbbrevs[start.getDay()])[0],
|
|
||||||
td = bg.find('td')[0];
|
|
||||||
th.className = th.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[start.getDay()]);
|
|
||||||
td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[start.getDay()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSize();
|
updateSize();
|
||||||
|
@ -204,42 +199,66 @@ function Agenda(element, options) {
|
||||||
|
|
||||||
function updateSize() {
|
function updateSize() {
|
||||||
|
|
||||||
// align first 'time' column
|
bodyTable.width('');
|
||||||
timeWidth = body.find('th:first').outerWidth();
|
body.height(Math.round(body.width() / options.aspectRatio) - head.height());
|
||||||
head.find('th:first').width(timeWidth);
|
|
||||||
|
|
||||||
// set table width (100% in css wasn't working in IE)
|
// need this for IE6/7. triggers clientWidth to be calculated for
|
||||||
var panelWidth = body[0].clientWidth || body.width(); // first time, there are no scrollbars!? for IE6?
|
// later user in this function. this is ridiculous
|
||||||
body.find('table').width(panelWidth);
|
body[0].clientWidth;
|
||||||
|
|
||||||
// align spacer column to scrollbar width
|
var topTDs = head.find('tr:first th'),
|
||||||
setOuterWidth(head.find('th:last'), body.width() - panelWidth);
|
stripeTDs = bg.find('td'),
|
||||||
|
contentWidth = body[0].clientWidth;
|
||||||
|
bodyTable.width(contentWidth);
|
||||||
|
|
||||||
|
// time-axis width
|
||||||
|
timeWidth = 0;
|
||||||
|
setOuterWidth(
|
||||||
|
head.find('th.fc-axis').add(body.find('th.fc-axis:first'))
|
||||||
|
.width('')
|
||||||
|
.each(function() {
|
||||||
|
timeWidth = Math.max(timeWidth, $(this).outerWidth());
|
||||||
|
})
|
||||||
|
.add(stripeTDs.eq(0)),
|
||||||
|
timeWidth
|
||||||
|
);
|
||||||
|
|
||||||
|
// column width
|
||||||
|
colWidth = Math.floor((contentWidth - timeWidth) / colCnt);
|
||||||
|
setOuterWidth(stripeTDs.slice(0, -1), colWidth);
|
||||||
|
setOuterWidth(topTDs.slice(1, -2), colWidth);
|
||||||
|
setOuterWidth(topTDs.slice(-2, -1), contentWidth - timeWidth - colWidth*(colCnt-1));
|
||||||
|
|
||||||
// position background stripe container
|
|
||||||
bg.css({
|
bg.css({
|
||||||
|
top: head.find('tr').height(),
|
||||||
left: timeWidth,
|
left: timeWidth,
|
||||||
width: panelWidth - timeWidth,
|
width: contentWidth - timeWidth,
|
||||||
height: element.height()
|
height: element.height()
|
||||||
});
|
});
|
||||||
|
|
||||||
// align other columns
|
rowHeight = body.find('tr:eq(1)').height(); // use second, first prob doesn't have a border
|
||||||
dayWidth = Math.floor((panelWidth - timeWidth) / dayCnt);
|
|
||||||
var topCells = head.find('tr:first th:gt(0)'),
|
|
||||||
bgCells = bg.find('td');
|
|
||||||
for (var i=0, len=bgCells.length-1; i<len; i++) { // TODO: use slice
|
|
||||||
setOuterWidth(topCells.eq(i), dayWidth);
|
|
||||||
setOuterWidth(bgCells.eq(i), dayWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
slotHeight = body.find('tr:eq(1)').height(); // use second, first prob doesn't have a border
|
function slotClick(ev) {
|
||||||
|
var col = Math.floor((ev.pageX - bg.offset().left) / colWidth),
|
||||||
// body height
|
date = addDays(cloneDate(view.visStart), dit + dis*col),
|
||||||
body.height(Math.round(body.width() / contentAspectRatio) - head.height());
|
rowMatch = this.className.match(/fc-slot(\d+)/);
|
||||||
// but this will add scrollbars...
|
if (rowMatch) {
|
||||||
// TODO: bug, iE6 view heights dont match up
|
var mins = parseInt(rowMatch[1]) * options.slotMinutes,
|
||||||
// also, no scrollbars
|
hours = Math.floor(mins/60);
|
||||||
|
date.setHours(hours);
|
||||||
|
date.setMinutes(mins % 60);
|
||||||
|
view.trigger('dayClick', this, date, false, ev);
|
||||||
|
}else{
|
||||||
|
view.trigger('dayClick', this, date, true, ev);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,6 +266,7 @@ function Agenda(element, options) {
|
||||||
|
|
||||||
|
|
||||||
function renderEvents(events) {
|
function renderEvents(events) {
|
||||||
|
return;
|
||||||
|
|
||||||
var i, len=events.length, event,
|
var i, len=events.length, event,
|
||||||
fakeID=0, nextDay,
|
fakeID=0, nextDay,
|
||||||
|
@ -287,6 +307,7 @@ function Agenda(element, options) {
|
||||||
|
|
||||||
|
|
||||||
function rerenderEvents(skipCompile) {
|
function rerenderEvents(skipCompile) {
|
||||||
|
return;
|
||||||
clearEvents();
|
clearEvents();
|
||||||
if (skipCompile) {
|
if (skipCompile) {
|
||||||
renderSlotSegs(cachedSlotSegs);
|
renderSlotSegs(cachedSlotSegs);
|
||||||
|
@ -297,16 +318,6 @@ function Agenda(element, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function clearEvents() {
|
|
||||||
for (var i=0; i<eventElements.length; i++) {
|
|
||||||
eventElements[i].remove();
|
|
||||||
}
|
|
||||||
eventElements = [];
|
|
||||||
eventElementsByID = {};
|
|
||||||
eventsByID = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// renders events in the 'time slots' at the bottom
|
// renders events in the 'time slots' at the bottom
|
||||||
|
|
||||||
function renderSlotSegs(segCols) {
|
function renderSlotSegs(segCols) {
|
||||||
|
@ -629,33 +640,6 @@ function Agenda(element, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// hover effect when dragging events over top days
|
|
||||||
|
|
||||||
var dayOverlay;
|
|
||||||
|
|
||||||
function showDayOverlay(props) {
|
|
||||||
if (!dayOverlay) {
|
|
||||||
dayOverlay = $("<div class='fc-day-overlay' style='position:absolute;display:none'/>")
|
|
||||||
.appendTo(element);
|
|
||||||
}
|
|
||||||
var o = element.offset();
|
|
||||||
dayOverlay
|
|
||||||
.css({
|
|
||||||
top: props.top - o.top,
|
|
||||||
left: props.left - o.left,
|
|
||||||
width: props.width,
|
|
||||||
height: props.height
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideDayOverlay() {
|
|
||||||
if (dayOverlay) {
|
|
||||||
dayOverlay.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************* resizable **************************************/
|
/************************************* resizable **************************************/
|
||||||
|
|
||||||
|
@ -711,55 +695,6 @@ function Agenda(element, options) {
|
||||||
|
|
||||||
/**************************************** misc **************************************/
|
/**************************************** misc **************************************/
|
||||||
|
|
||||||
|
|
||||||
function reportEventElement(event, eventElement) {
|
|
||||||
eventElements.push(eventElement);
|
|
||||||
if (eventElementsByID[event._id]) {
|
|
||||||
eventElementsByID[event._id].push(eventElement);
|
|
||||||
}else{
|
|
||||||
eventElementsByID[event._id] = [eventElement];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function hideSimilarEvents(event, eventElement) {
|
|
||||||
var elements = eventElementsByID[event._id];
|
|
||||||
for (var i=0; i<elements.length; i++) {
|
|
||||||
if (elements[i] != eventElement) {
|
|
||||||
elements[i].hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function reportEventMove(event, days, keepTime, minutes) {
|
|
||||||
minutes = minutes || 0;
|
|
||||||
var events = eventsByID[event._id];
|
|
||||||
for (var i=0, event2; i<events.length; i++) {
|
|
||||||
event2 = events[i];
|
|
||||||
event2.hasTime = event.hasTime;
|
|
||||||
addMinutes(addDays(event2.start, days, keepTime), minutes);
|
|
||||||
if (event.end) {
|
|
||||||
event2.end = addMinutes(addDays(event2.end || event2._end, days, keepTime), minutes);
|
|
||||||
}else{
|
|
||||||
event2.end = event2._end = null;
|
|
||||||
// hopefully renderEvents() will always be called after this
|
|
||||||
// to reset _end.... TODO?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function reportEventResize(event, days, keepTime, minutes) {
|
|
||||||
minutes = minutes || 0;
|
|
||||||
var events = eventsByID[event._id];
|
|
||||||
for (var i=0, event2; i<events.length; i++) {
|
|
||||||
event2 = events[i];
|
|
||||||
event2.end = addMinutes(addDays(event2.end || event2._end, days, keepTime), minutes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// get the Y coordinate of the given time on the given day
|
// get the Y coordinate of the given time on the given day
|
||||||
|
|
||||||
function timeCoord(day, time) {
|
function timeCoord(day, time) {
|
||||||
|
@ -846,47 +781,18 @@ function compileSlotSegs(events, start, end) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: move to month.js
|
function segAfters(levels) { // TODO: put in agenda.js
|
||||||
|
var i, j, k, level, seg, seg2;
|
||||||
function sliceSegs(events, start, end) {
|
for (i=levels.length-1; i>0; i--) {
|
||||||
var segs = [],
|
level = levels[i];
|
||||||
i, len=events.length, event,
|
for (j=0; j<level.length; j++) {
|
||||||
eventStart, eventEnd,
|
seg = level[j];
|
||||||
segStart, segEnd,
|
for (k=0; k<segLevels[i-1].length; k++) {
|
||||||
isStart, isEnd;
|
seg2 = segLevels[i-1][k];
|
||||||
for (i=0; i<len; i++) {
|
if (segsCollide(seg, seg2)) {
|
||||||
event = events[i];
|
seg2.after = Math.max(seg2.after, seg.after+1);
|
||||||
eventStart = event.start;
|
}
|
||||||
eventEnd = event._end;
|
}
|
||||||
if (eventEnd > start && eventStart < end) {
|
|
||||||
if (eventStart < start) {
|
|
||||||
segStart = cloneDate(start);
|
|
||||||
isStart = false;
|
|
||||||
}else{
|
|
||||||
segStart = eventStart;
|
|
||||||
isStart = true;
|
|
||||||
}
|
|
||||||
if (eventEnd > end) {
|
|
||||||
segEnd = cloneDate(end);
|
|
||||||
isEnd = false;
|
|
||||||
}else{
|
|
||||||
segEnd = eventEnd;
|
|
||||||
isEnd = true;
|
|
||||||
}
|
|
||||||
segs.push({
|
|
||||||
event: event,
|
|
||||||
start: segStart,
|
|
||||||
end: segEnd,
|
|
||||||
isStart: isStart,
|
|
||||||
isEnd: isEnd,
|
|
||||||
msLength: segEnd - segStart
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return segs.sort(segCmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function segCmp(a, b) {
|
|
||||||
return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,78 @@
|
||||||
|
|
||||||
.fc-event,
|
/*.fc-event,
|
||||||
.fc-event a,
|
.fc-event a,
|
||||||
.fc-agenda .fc-event-time {
|
.fc-agenda .fc-event-time {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: blue;
|
border-color: blue;
|
||||||
background-color: blue;
|
background-color: blue;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
.fc .fc-axis {
|
||||||
|
width: 50px;
|
||||||
|
height: 1.6em;
|
||||||
|
padding: 0 4px 0 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* header styles */
|
.fc .fc-agenda th,
|
||||||
|
.fc .fc-agenda td {
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-agenda-head tr.fc-all-day th {
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-agenda tr.fc-first th,
|
||||||
|
.fc-agenda tr.fc-first td {
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-agenda .fc-leftmost {
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc .fc-agenda-head td,
|
||||||
|
.fc .fc-agenda-body td {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc .fc-agenda-body tr.fc-minor th,
|
||||||
|
.fc .fc-agenda-body tr.fc-minor td {
|
||||||
|
border-top-style: dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.fc .fc-divider th {
|
||||||
|
height: 3px;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc .fc-divider .fc-state-default {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* header styles */
|
||||||
|
/*
|
||||||
.fc .fc-agenda-head th.fc-first {
|
.fc .fc-agenda-head th.fc-first {
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
}
|
}
|
||||||
|
@ -31,39 +91,33 @@
|
||||||
border-bottom-width: 2px;
|
border-bottom-width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.fc-agenda-head tr.fc-last th {
|
.fc-agenda-head tr.fc-last th {
|
||||||
/*border-width: 1px 0 1px 1px;*/
|
#border-width: 1px 0 1px 1px;
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fc-agenda-head tr.fc-last th.fc-first {
|
.fc-agenda-head tr.fc-last th.fc-first {
|
||||||
/*border-width: 0 2px 1px 0;*/
|
#border-width: 0 2px 1px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fc-agenda-head tr.fc-last th.fc-last {
|
.fc-agenda-head tr.fc-last th.fc-last {
|
||||||
/*border-width: 0 0 0 3px;*/
|
#border-width: 0 0 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fc .fc-agenda-head td {
|
.fc .fc-agenda-head td {
|
||||||
/*border-width: 3px 0 3px 1px;*/
|
#border-width: 3px 0 3px 1px;
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.fc-agenda-body {
|
.fc-agenda-body {
|
||||||
/*width: 100%;*/
|
#width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
.fc .fc-agenda-body th {
|
.fc .fc-agenda-body th {
|
||||||
border-width: 1px 0 0 0;
|
border-width: 1px 0 0 0;
|
||||||
background-image: none;
|
background-image: none;
|
||||||
|
@ -106,6 +160,8 @@
|
||||||
.fc-agenda .fc-day-content {
|
.fc-agenda .fc-day-content {
|
||||||
padding: 2px 1px 14px;
|
padding: 2px 1px 14px;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fc {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
.fc table {
|
.fc table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
|
@ -145,7 +149,7 @@ table.fc-header {
|
||||||
}
|
}
|
||||||
|
|
||||||
.fc-header .fc-state-default span {
|
.fc-header .fc-state-default span {
|
||||||
border-color: #fff #fff #cecece; /* inner border */
|
border-color: #fff #fff #d1d1d1; /* inner border */
|
||||||
background: #e8e8e8;
|
background: #e8e8e8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
src/grid.js
12
src/grid.js
|
@ -116,10 +116,6 @@ function Grid(element, options, methods) {
|
||||||
rowCnt = r;
|
rowCnt = r;
|
||||||
colCnt = c;
|
colCnt = c;
|
||||||
|
|
||||||
var month = view.start.getMonth(),
|
|
||||||
today = clearTime(new Date()),
|
|
||||||
s, i, j, d = cloneDate(view.visStart);
|
|
||||||
|
|
||||||
// update option-derived variables
|
// update option-derived variables
|
||||||
tm = options.theme ? 'ui' : 'fc';
|
tm = options.theme ? 'ui' : 'fc';
|
||||||
firstDay = options.firstDay;
|
firstDay = options.firstDay;
|
||||||
|
@ -131,6 +127,10 @@ function Grid(element, options, methods) {
|
||||||
dit = 0;
|
dit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var month = view.start.getMonth(),
|
||||||
|
today = clearTime(new Date()),
|
||||||
|
s, i, j, d = cloneDate(view.visStart);
|
||||||
|
|
||||||
if (!tbody) { // first time, build all cells from scratch
|
if (!tbody) { // first time, build all cells from scratch
|
||||||
|
|
||||||
var table = $("<table/>").appendTo(element);
|
var table = $("<table/>").appendTo(element);
|
||||||
|
@ -247,12 +247,12 @@ function Grid(element, options, methods) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function dayClick() {
|
function dayClick(ev) {
|
||||||
var date = addDays(
|
var date = addDays(
|
||||||
cloneDate(view.visStart),
|
cloneDate(view.visStart),
|
||||||
parseInt(this.className.match(/fc\-day(\d+)/)[1])
|
parseInt(this.className.match(/fc\-day(\d+)/)[1])
|
||||||
);
|
);
|
||||||
view.trigger('dayClick', this, date);
|
view.trigger('dayClick', this, date, true, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
42
src/main.js
42
src/main.js
|
@ -113,7 +113,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
delete options.eventSources;
|
delete options.eventSources;
|
||||||
if (options.events) {
|
if (options.events) {
|
||||||
eventSources.push(options.events);
|
eventSources.push(options.events);
|
||||||
delete options.event;
|
delete options.events;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first event source reserved for 'sticky' events
|
// first event source reserved for 'sticky' events
|
||||||
|
@ -137,7 +137,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
// element
|
// element
|
||||||
var _element = this,
|
var _element = this,
|
||||||
element = $(this).addClass('fc'),
|
element = $(this).addClass('fc'),
|
||||||
content = $("<div class='fc-content " + tm + "-widget-content'/>").appendTo(this);
|
content = $("<div class='fc-content " + tm + "-widget-content' style='position:relative'/>").appendTo(this); // relative for ie6
|
||||||
if (options.isRTL) {
|
if (options.isRTL) {
|
||||||
element.addClass('fc-rtl');
|
element.addClass('fc-rtl');
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,6 @@ $.fn.fullCalendar = function(options) {
|
||||||
// view managing
|
// view managing
|
||||||
var date = new Date(),
|
var date = new Date(),
|
||||||
viewName, view, // the current view
|
viewName, view, // the current view
|
||||||
prevView,
|
|
||||||
viewInstances = {};
|
viewInstances = {};
|
||||||
if (options.year != undefined) {
|
if (options.year != undefined) {
|
||||||
date.setYear(options.year);
|
date.setYear(options.year);
|
||||||
|
@ -167,7 +166,14 @@ $.fn.fullCalendar = function(options) {
|
||||||
|
|
||||||
function changeView(v) {
|
function changeView(v) {
|
||||||
if (v != viewName) {
|
if (v != viewName) {
|
||||||
prevView = view;
|
lockContentSize();
|
||||||
|
if (view) {
|
||||||
|
if (view.eventsChanged) {
|
||||||
|
eventsDirtyExcept(view);
|
||||||
|
view.eventsChanged = false;
|
||||||
|
}
|
||||||
|
view.element.hide();
|
||||||
|
}
|
||||||
if (viewInstances[v]) {
|
if (viewInstances[v]) {
|
||||||
(view = viewInstances[v]).element.show();
|
(view = viewInstances[v]).element.show();
|
||||||
}else{
|
}else{
|
||||||
|
@ -175,11 +181,6 @@ $.fn.fullCalendar = function(options) {
|
||||||
$("<div class='fc-view fc-view-" + v + "'/>").appendTo(content),
|
$("<div class='fc-view fc-view-" + v + "'/>").appendTo(content),
|
||||||
options);
|
options);
|
||||||
}
|
}
|
||||||
if (prevView && prevView.eventsChanged) {
|
|
||||||
// if previous view's events have been changed, mark future views' events as dirty
|
|
||||||
eventsDirtyExcept(prevView);
|
|
||||||
prevView.eventsChanged = false;
|
|
||||||
}
|
|
||||||
if (header) {
|
if (header) {
|
||||||
// update 'active' view button
|
// update 'active' view button
|
||||||
header.find('div.fc-button-' + viewName).removeClass(tm + '-state-active');
|
header.find('div.fc-button-' + viewName).removeClass(tm + '-state-active');
|
||||||
|
@ -187,10 +188,7 @@ $.fn.fullCalendar = function(options) {
|
||||||
}
|
}
|
||||||
view.name = viewName = v;
|
view.name = viewName = v;
|
||||||
render();
|
render();
|
||||||
if (prevView) {
|
unlockContentSize();
|
||||||
// hide the old element AFTER the new has been rendered, preserves scrollbars
|
|
||||||
prevView.element.hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,6 +620,20 @@ $.fn.fullCalendar = function(options) {
|
||||||
/* Resizing
|
/* Resizing
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
function lockContentSize() {
|
||||||
|
content.css({
|
||||||
|
overflow: 'hidden',
|
||||||
|
height: Math.round(content.width() / options.aspectRatio)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function unlockContentSize() {
|
||||||
|
content.css({
|
||||||
|
overflow: '',
|
||||||
|
height: ($.browser.msie && $.browser.version == '6.0') ? 1 : ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var elementWidth,
|
var elementWidth,
|
||||||
ignoreWindowResizes = false,
|
ignoreWindowResizes = false,
|
||||||
resizeCnt = 0;
|
resizeCnt = 0;
|
||||||
|
@ -630,11 +642,13 @@ $.fn.fullCalendar = function(options) {
|
||||||
if (!ignoreWindowResizes && view.date) { // view.date means the view has been rendered
|
if (!ignoreWindowResizes && view.date) { // view.date means the view has been rendered
|
||||||
var rcnt = ++resizeCnt; // add a delay
|
var rcnt = ++resizeCnt; // add a delay
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
if (rcnt == resizeCnt) {
|
if (rcnt == resizeCnt && !ignoreWindowResizes) {
|
||||||
var newWidth = element.width();
|
var newWidth = element.width();
|
||||||
if (newWidth != elementWidth) {
|
if (newWidth != elementWidth) {
|
||||||
elementWidth = newWidth;
|
elementWidth = newWidth;
|
||||||
|
lockContentSize();
|
||||||
view.updateSize();
|
view.updateSize();
|
||||||
|
unlockContentSize();
|
||||||
view.rerenderEvents(true);
|
view.rerenderEvents(true);
|
||||||
sizesDirtyExcept(view);
|
sizesDirtyExcept(view);
|
||||||
view.trigger('windowResize', _element);
|
view.trigger('windowResize', _element);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<link rel='stylesheet' type='text/css' href='../examples/redmond/theme.css' />
|
||||||
<script type='text/javascript' src='loader.js'></script>
|
<script type='text/javascript' src='loader.js'></script>
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
|
|
||||||
|
@ -11,11 +12,15 @@
|
||||||
var m = d.getMonth();
|
var m = d.getMonth();
|
||||||
|
|
||||||
$('#calendar').fullCalendar({
|
$('#calendar').fullCalendar({
|
||||||
|
//weekMode: 'variable',
|
||||||
|
theme: true,
|
||||||
|
//isRTL: true,
|
||||||
editable: true,
|
editable: true,
|
||||||
|
defaultView: 'agendaWeek',
|
||||||
header: {
|
header: {
|
||||||
left: 'prev,next today',
|
left: 'prev,next today',
|
||||||
center: 'title',
|
center: 'title',
|
||||||
right: 'month,basicWeek,basicDay'
|
right: 'month,agendaWeek,agendaDay'
|
||||||
},
|
},
|
||||||
events: [
|
events: [
|
||||||
{
|
{
|
||||||
|
@ -51,7 +56,10 @@
|
||||||
url: "http://facebook.com/",
|
url: "http://facebook.com/",
|
||||||
allDay: false
|
allDay: false
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
dayClick: function(date, allDay) {
|
||||||
|
alert(date + ' allDay:' + allDay);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -67,7 +75,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendar {
|
#calendar {
|
||||||
width: 900px;
|
width: 80%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ if (_build) {
|
||||||
}else{
|
}else{
|
||||||
includeCSS('../src/css/main.css');
|
includeCSS('../src/css/main.css');
|
||||||
includeCSS('../src/css/grid.css');
|
includeCSS('../src/css/grid.css');
|
||||||
|
includeCSS('../src/css/agenda.css');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_legacy) {
|
if (_legacy) {
|
||||||
|
@ -78,6 +79,7 @@ if (_build) {
|
||||||
}else{
|
}else{
|
||||||
includeJS('../src/main.js');
|
includeJS('../src/main.js');
|
||||||
includeJS('../src/grid.js');
|
includeJS('../src/grid.js');
|
||||||
|
includeJS('../src/agenda.js');
|
||||||
includeJS('../src/view.js');
|
includeJS('../src/view.js');
|
||||||
includeJS('../src/util.js');
|
includeJS('../src/util.js');
|
||||||
includeJS('../src/gcal.js');
|
includeJS('../src/gcal.js');
|
||||||
|
|
Loading…
Reference in a new issue