modified docs, added all new tests

This commit is contained in:
Adam Shaw
2009-11-22 16:21:12 -08:00
parent 2017ce20e8
commit 92e482089b
20 changed files with 1173 additions and 944 deletions
+16
View File
@@ -1,4 +1,20 @@
function segAfters(levels) { // TODO: put in agenda.js
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 ***********************************/
$.fullCalendar.views.week = function(element, options) {
+2 -2
View File
@@ -6,12 +6,12 @@
width: 100%;
}
.fc-grid th {
.fc .fc-grid th {
border-width: 0 0 0 1px;
text-align: center;
}
.fc-grid td {
.fc .fc-grid td {
border-width: 1px 0 0 1px;
}
+27 -9
View File
@@ -212,14 +212,6 @@ table.fc-header {
background-color: blue;
}
.fc-event-nobg,
.fc-event-nobg a,
.fc-agenda .fc-event-nobg .fc-event-time {
border-style: none;
background: none;
color: inherit;
}
.fc-event a {
overflow: hidden;
font-size: 11px;
@@ -239,6 +231,14 @@ table.fc-header {
height: 100%;
}
/* resizable */
.fc .ui-resizable-handle {
display: block;
position: absolute;
z-index: 99999;
}
/* Horizontal Events
@@ -271,8 +271,26 @@ table.fc-header {
border-right-width: 1px;
}
/* resizable */
.fc-event-hori .ui-resizable-e {
top: 0;
right: -5px;
width: 7px;
height: 100%;
cursor: e-resize;
}
.fc-event-hori .ui-resizable-w {
top: 0;
left: -5px;
width: 7px;
height: 100%;
cursor: w-resize;
}
.fc-event-hori .ui-resizable-handle {
_height: 10px; /* IE6 had 0 height */
_height: 14px; /* IE6 had 0 height */
}
+5 -5
View File
@@ -26,12 +26,12 @@
var startStr = entry['gd$when'][0]['startTime'];
var start = $.fullCalendar.parseDate(startStr);
var end = $.fullCalendar.parseDate(entry['gd$when'][0]['endTime']);
var hasTime = startStr.indexOf('T') != -1;
var allDay = startStr.indexOf('T') == -1;
var classNames = [];
if (hasTime) {
classNames.push('fc-event-nobg');
if (allDay) {
end = new Date(end - 1); // make in inclusive
}else{
end = new Date(end - 1);
classNames.push('fc-event-nobg');
}
if (options.className) {
if (typeof options.className == 'string') {
@@ -48,7 +48,7 @@
end: end,
location: entry['gd$where'][0]['valueString'],
description: entry['content']['$t'],
hasTime: hasTime,
allDay: allDay,
className: classNames,
editable: options.editable || false
});
+58 -62
View File
@@ -81,15 +81,16 @@ function Grid(element, options, methods) {
// initialize superclass
view = $.extend(this, viewMethods, methods, {
renderGrid: renderGrid,
renderEvents: renderEvents,
rerenderEvents: rerenderEvents,
updateSize: updateSize,
eventEnd: function(event) {
return event.end || cloneDate(event.start);
defaultEventEnd: function(event) {
return cloneDate(event.start);
},
visEventEnd: function(event) {
if (event.end) {
var end = cloneDate(event.end);
return (!event.hasTime || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
return (event.allDay || end.getHours() || end.getMinutes()) ? addDays(end, 1) : end;
}else{
return addDays(cloneDate(event.start), 1);
}
@@ -108,13 +109,12 @@ function Grid(element, options, methods) {
}
function renderGrid(r, c, colFormat, showNumbers, fetchEvents) {
//console.log('renderGrid!');
rowCnt = r;
colCnt = c;
var month = view.start.getMonth(),
today = clearTime(new Date()),
s, s2, s3, i, j, d = cloneDate(view.visStart);
s, i, j, d = cloneDate(view.visStart);
// update option-derived variables
tm = options.theme ? 'ui' : 'fc';
@@ -131,28 +131,23 @@ function Grid(element, options, methods) {
var table = $("<table/>").appendTo(element);
s = '';
s = "<thead><tr>";
for (i=0; i<colCnt; i++) {
s2 = "<th class='fc-" +
s += "<th class='fc-" +
dayIDs[d.getDay()] + ' ' + // needs to be first
tm + '-state-default ' +
tm + '-state-default' +
(i==dit ? ' fc-left' : '') +
"'>" + formatDate(d, colFormat, options) + "</th>"; // TODO: optionize
//if (rtl) {
// s = s2 + s;
//}else{
s += s2;
//}
"'>" + formatDate(d, colFormat, options) + "</th>";
addDays(d, 1);
}
thead = $("<thead><tr>" + s + "</tr></thead>").appendTo(table);
thead = $(s + "</tr></thead>").appendTo(table);
s = "<tbody>";
d = cloneDate(view.visStart);
for (i=0; i<rowCnt; i++) {
s2 = '';
s += "<tr class='fc-week" + i + "'>";
for (j=0; j<colCnt; j++) {
s3 = "<td class='fc-" +
s += "<td class='fc-" +
dayIDs[d.getDay()] + ' ' + // needs to be first
tm + '-state-default fc-day' + (i*colCnt+j) +
(j==dit ? ' fc-left' : '') +
@@ -162,14 +157,9 @@ function Grid(element, options, methods) {
' fc-not-today') + "'>" +
(showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') +
"<div class='fc-day-content'><div>&nbsp;</div></div></td>";
//if (rtl) {
// s2 = s3 + s2;
//}else{
s2 += s3;
//}
addDays(d, 1);
}
s += "<tr class='fc-week" + i + "'>" + s2 + "</tr>";
s += "</tr>";
}
tbody = $(s + "</tbody>").appendTo(table);
tbody.find('td').click(dayClick);
@@ -182,60 +172,67 @@ function Grid(element, options, methods) {
if (rowCnt < prevRowCnt) {
tbody.find('tr:gt(' + (rowCnt-1) + ')').remove(); // remove extra rows
}
else if (rowCnt > prevRowCnt) {
else if (rowCnt > prevRowCnt) { // needs to create new rows...
s = '';
for (i=prevRowCnt; i<rowCnt; i++) {
s2 = '';
s += "<tr class='fc-week" + i + "'>";
for (j=0; j<colCnt; j++) {
s3 = "<td class='fc-" +
dayIDs[(j * dis + dit + weekStart) % 7] + ' ' + // needs to be first
tm + '-state-default fc-new fc-day' + (i*colCnt + j) +
s += "<td class='fc-" +
dayIDs[d.getDay()] + ' ' + // needs to be first
tm + '-state-default fc-new fc-day' + (i*colCnt+j) +
(j==dit ? ' fc-left' : '') + "'>" +
(showNumbers ? "<div class='fc-day-number'></div>" : '') +
"<div class='fc-day-content'><div>&nbsp;</div></div>" +
"</td>";
//if (rtl) {
// s2 = s3 + s2;
//}else{
s2 += s3;
//}
addDays(d, 1);
}
s += "<tr class='fc-week" + i + "'>" + s2 + "</tr>";
s += "</tr>";
}
tbody.append(s);
}
tbody.find('td.fc-new').removeClass('fc-new').click(dayClick);
// re-label and re-class existing cells
tbody.find('tr').each(function() {
for (i=0; i<colCnt; i++) {
var td = $(this.childNodes[i]); // * dis + dit TODO: clean
if (rowCnt > 1) {
if (d.getMonth() == month) {
td.removeClass('fc-other-month');
}else{
td.addClass('fc-other-month');
}
}
if (+d == +today) {
td.removeClass('fc-not-today')
.addClass('fc-today')
.addClass(tm + '-state-highlight');
d = cloneDate(view.visStart);
tbody.find('td').each(function() {
var td = $(this);
if (rowCnt > 1) {
if (d.getMonth() == month) {
td.removeClass('fc-other-month');
}else{
td.addClass('fc-not-today')
.removeClass('fc-today')
.removeClass(tm + '-state-highlight');
td.addClass('fc-other-month');
}
td.find('div.fc-day-number').text(d.getDate());
addDays(d, 1);
}
if (+d == +today) {
td.removeClass('fc-not-today')
.addClass('fc-today')
.addClass(tm + '-state-highlight');
}else{
td.addClass('fc-not-today')
.removeClass('fc-today')
.removeClass(tm + '-state-highlight');
}
td.find('div.fc-day-number').text(d.getDate());
addDays(d, 1);
});
if (colCnt == 1) {
var startDay = this.visStart.getDay();
var td = tbody.find('td')[0];
td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[startDay]);
thead.find('th').text(formatDate(this.start, colFormat, options));
if (rowCnt == 1) { // more likely changed (week or day view)
// redo column header text and class
d = cloneDate(view.visStart);
thead.find('th').each(function() {
$(this).text(formatDate(d, colFormat, options));
this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
addDays(d, 1);
});
// redo cell day-of-weeks
d = cloneDate(view.visStart);
tbody.find('td').each(function() {
this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
addDays(d, 1);
});
}
}
@@ -297,7 +294,7 @@ function Grid(element, options, methods) {
function renderEvents(events) {
view.reportEvents(events);
renderSegs(cachedSegs = compileSegs(events)); // view.visibleEvents(
renderSegs(cachedSegs = compileSegs(events));
}
@@ -388,10 +385,9 @@ function Grid(element, options, methods) {
}
eventElement = $("<div class='" + eventClasses.join(' ') + "'/>")
.append(eventAnchor = $("<a/>")
.append(event.hasTime ?
.append(event.allDay ? null :
$("<span class='fc-event-time'/>")
.html(formatDate(event.start, options.eventTimeFormat, options)) :
null)
.html(formatDates(event.start, event.end, options.timeFormat, options)))
.append($("<span class='fc-event-title'/>")
.text(event.title)));
if (event.url) {
+164 -119
View File
@@ -12,9 +12,9 @@ var defaults = {
defaultView: 'month',
aspectRatio: 1.35,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
left: 'title',
center: '',
right: 'today prev,next'
},
// event ajax
@@ -23,7 +23,7 @@ var defaults = {
cacheParam: '_',
// time formats
eventTimeFormat: 'h(:mm)t',
timeFormat: 'h(:mm)t', // for events
titleFormat: {
month: 'MMMM yyyy',
week: "MMM d[ yyyy]{ '&#8212;'[ MMM] d yyyy}",
@@ -62,9 +62,9 @@ var defaults = {
// right-to-left defaults
var rtlDefaults = {
header: {
left: 'basicDay,basicWeek,month',
center: 'title',
right: 'today next,prev'
left: 'next,prev today',
center: '',
right: 'title'
},
buttonText: {
prev: '&#9658;',
@@ -254,7 +254,7 @@ $.fn.fullCalendar = function(options) {
// Fetch from a particular source. Append to the 'events' array
function fetchEventSource(src, callback) {
var prevDate = cloneDate(date),
reportEvents = function(a, dontPopLoading) {
reportEvents = function(a) {
if (+date == +prevDate) {
for (var i=0; i<a.length; i++) {
normalizeEvent(a[i]);
@@ -262,12 +262,13 @@ $.fn.fullCalendar = function(options) {
}
events = events.concat(a);
}
if (!dontPopLoading) {
popLoading();
}
if (callback) {
callback(a);
}
},
reportPopEvents = function(a) {
reportEvents(a);
popLoading();
};
if (typeof src == 'string') {
var params = {};
@@ -275,14 +276,14 @@ $.fn.fullCalendar = function(options) {
params[options.endParam] = Math.round(eventEnd.getTime() / 1000);
params[options.cacheParam] = (new Date()).getTime();
pushLoading();
$.getJSON(src, params, reportEvents);
$.getJSON(src, params, reportPopEvents);
}
else if ($.isFunction(src)) {
pushLoading();
src(cloneDate(eventStart), cloneDate(eventEnd), reportEvents);
src(cloneDate(eventStart), cloneDate(eventEnd), reportPopEvents);
}
else {
reportEvents(src, true); // src is an array
reportEvents(src); // src is an array
}
}
@@ -329,73 +330,123 @@ $.fn.fullCalendar = function(options) {
render();
},
gotoDate: function() {
gotoDate: function(year, month, dateNum) {
if (typeof year != 'undefined') {
date.setYear(year);
}
if (typeof month != 'undefined') {
date.setMonth(month);
}
if (typeof dateNum != 'undefined') {
date.setDate(dateNum);
}
render();
},
moveDate: function() {
moveDate: function(years, months, days) {
if (typeof years != 'undefined') {
addYears(date, years);
}
if (typeof months != 'undefined') {
addMonths(date, months);
}
if (typeof days != 'undefined') {
addDays(date, days);
}
render();
},
//
// Event Rendering
//
renderEvent: function(event, stick) {
if (typeof event != 'object') {
event = eventsByID(event)[0]; // assumed to be ID
if (!event) return;
}else{
normalizeEvent(event);
}
updateEvent: function(event) {
var startDelta = event.start - event._start,
msDuration = event.end - event.start,
i, len = events.length, e,
found = false;
endDelta = event.end ? (event.end - (event._end || view.defaultEventEnd(event))) : 0,
i, len = events.length, e;
for (i=0; i<len; i++) {
e = events[i];
if (e._id == event._id) {
if (e != event) {
e._start = cloneDate(e.start = new Date(+e.start + startDelta));
e.end = new Date(+e.start + msDuration);
e.title = event.title;
e.hasTime = event.hasTime;
if (stick && !event.source) {
(event.source = eventSources[0]).push(event);
if (e._id == event._id && e != event) {
e.start = new Date(+e.start + startDelta);
if (event.end) {
if (e.end) {
e.end = new Date(+e.end + endDelta);
}else{
e.end = new Date(+view.defaultEventEnd(e) + endDelta);
}
}else{
e.end = null;
}
found = true;
e.title = event.title;
e.allDay = event.allDay;
normalizeEvent(e);
}
}
if (!found) {
normalizeEvent(event);
eventsChanged();
},
renderEvent: function(event, stick) {
normalizeEvent(event);
if (!event.source) {
if (stick) {
(event.source = eventSources[0]).push(event);
}
events.push(event);
}
eventsChanged();
},
removeEvent: function(id) {
if (typeof id == 'object') {
id = id._id;
removeEvents: function(filter) {
if (!filter) { // remove all
events = [];
// clear all array sources
for (var i=0; i<eventSources.length; i++) {
if (typeof eventSources[i] == 'object') {
eventSources[i] = [];
}
}
}else{
id += '';
if (!$.isFunction(filter)) { // an event ID
var id = filter + '';
filter = function(e) {
return e._id == id;
};
}
events = filterArray(events, function(e) {
return !filter(e);
});
// remove events from array sources
for (var i=0; i<eventSources.length; i++) {
if (typeof eventSources[i] == 'object') {
eventSources[i] = filterArray(eventSources[i], function(e) {
return !filter(e);
});
}
}
}
removeEvents(function(e) {
return e._id != id;
});
eventsChanged();
},
clientEvents: function(filter) {
if (filter) {
if ($.isFunction(filter)) {
return filterArray(events, filter);
}else{
}
else if (filter) { // an event ID
filter += '';
return filterArray(events, function(e) {
return e._id == filter;
});
}
else {
return events;
}
},
rerender: function() {
rerenderEvents: function() {
view.rerenderEvents();
},
clientEventsByID: eventsByID,
removeEvents: removeEvents,
//
// Event Source
//
@@ -418,46 +469,14 @@ $.fn.fullCalendar = function(options) {
eventsChanged();
},
refetch: function() {
refetchEvents: function() {
fetchEvents(eventsChanged);
}
};
$.data(this, 'fullCalendar', publicMethods);
function eventsByID(id) {
id += '';
return filterArray(events, function(e) {
e._id == id;
});
}
function removeEvents(filter) {
var i, len = eventSources.length;
if (filter) {
events = filterArray(events, function(e) {
return !filter(e);
});
// remove events from array sources
for (i=0; i<len; i++) {
if (typeof eventSources[i] == 'object') {
eventSources[i] = filterArray(eventSources[i], function(e) {
return !filter(e);
});
}
}
}else{
events = [];
// clear all array sources
for (i=0; i<len; i++) {
if (typeof eventSources[i] == 'object') {
eventSources[i] = [];
}
}
}
eventsChanged();
}
/* Header
@@ -489,47 +508,58 @@ $.fn.fullCalendar = function(options) {
tr.append("<td><h2 class='fc-header-title'/></td>");
prevTitle = true;
}else{
var button,
icon = options.theme ? options.buttonIcons[buttonNameShort] : null,
text = options.buttonText[buttonNameShort];
if (icon) {
button = $("<div class='fc-button-" + buttonName + " ui-state-default'>" +
"<a><span class='ui-icon ui-icon-" + icon + "'/></a></div>");
var buttonClick;
if (publicMethods[buttonNameShort]) {
buttonClick = publicMethods[buttonNameShort];
}
else if (text) {
button = $("<div class='fc-button-" + buttonName + " " + tm + "-state-default'>" +
"<a><span>" + text + "</span></a></div>");
else if (views[buttonName]) {
buttonClick = function() { switchView(buttonName) };
}
if (button) {
button
.mousedown(function() {
button.addClass(tm + '-state-down');
})
.mouseup(function() {
button.removeClass(tm + '-state-down');
})
.hover(function() {
button.addClass(tm + '-state-hover');
},
function() {
button.removeClass(tm + '-state-hover')
.removeClass(tm + '-state-down');
})
.appendTo($("<td/>").appendTo(tr));
if (publicMethods[buttonNameShort]) {
button.click(publicMethods[buttonNameShort]);
if (buttonClick) {
var button,
icon = options.theme ? options.buttonIcons[buttonNameShort] : null,
text = options.buttonText[buttonNameShort];
if (icon) {
button = $("<div class='fc-button-" + buttonName + " ui-state-default'>" +
"<a><span class='ui-icon ui-icon-" + icon + "'/></a></div>");
}
else if (views[buttonName]) {
button.click(function() {
switchView(buttonName);
});
else if (text) {
button = $("<div class='fc-button-" + buttonName + " " + tm + "-state-default'>" +
"<a><span>" + text + "</span></a></div>");
}
if (j == 0 || prevTitle) {
button.addClass(tm + '-corner-left');
}else{
button.addClass(tm + '-no-left');
if (button) {
button
.mousedown(function() {
button.addClass(tm + '-state-down');
})
.mouseup(function() {
button.removeClass(tm + '-state-down');
})
.hover(
function() {
button.addClass(tm + '-state-hover');
},
function() {
button.removeClass(tm + '-state-hover')
.removeClass(tm + '-state-down');
}
)
.appendTo($("<td/>").appendTo(tr));
if (publicMethods[buttonNameShort]) {
button.click(publicMethods[buttonNameShort]);
}
else if (views[buttonName]) {
button.click(function() {
switchView(buttonName);
});
}
if (j == 0 || prevTitle) {
button.addClass(tm + '-corner-left');
}else{
button.addClass(tm + '-no-left');
}
prevTitle = false;
}
prevTitle = false;
}
}
});
@@ -572,6 +602,8 @@ $.fn.fullCalendar = function(options) {
});
return this;
};
@@ -583,7 +615,20 @@ var fakeID = 0;
function normalizeEvent(event) {
event._id = event._id || (typeof event.id == 'undefined' ? '_fc' + fakeID++ : event.id + '');
if (event.date) {
if (!event.start) {
event.start = event.date;
}
delete event.date;
}
event._start = cloneDate(event.start = parseDate(event.start));
event.end = parseDate(event.end);
if (event.end && event.end < event.start) {
event.end = cloneDate(event.start);
}
event._end = event.end ? cloneDate(event.end) : null;
if (typeof event.allDay == 'undefined') {
event.allDay = true;
}
}
+4 -4
View File
@@ -4,14 +4,14 @@
var DAY_MS = 86400000;
function addMonths(d, n, keepTime) {
d.setMonth(d.getMonth() + n);
function addYears(d, n, keepTime) {
d.setFullYear(d.getFullYear() + n);
if (keepTime) return d;
return clearTime(d);
}
function addYears(d, n, keepTime) {
d.setFullYear(d.getFullYear() + n);
function addMonths(d, n, keepTime) {
d.setMonth(d.getMonth() + n);
if (keepTime) return d;
return clearTime(d);
}
+13 -34
View File
@@ -8,7 +8,7 @@ var viewMethods = {
// - end
// - visStart
// - visEnd
// - eventEnd(event)
// - defaultEventEnd(event)
// - visEventEnd(event)
//
// - render
@@ -26,6 +26,8 @@ var viewMethods = {
// trigger event handlers, always append view as last arg
trigger: function(name, thisObj) {
if (this.options[name]) {
return this.options[name].apply(thisObj || this, Array.prototype.slice.call(arguments, 2).concat([this]));
@@ -34,6 +36,14 @@ var viewMethods = {
//
eventEnd: function(event) {
return event.end || this.defaultEventEnd(event);
},
// event/element creation reporting
reportEvents: function(events) {
@@ -64,21 +74,6 @@ var viewMethods = {
// get events within visStart and visEnd TODO: need this? move it somewhere else?
visibleEvents: function(events) {
var res=[], i, len=events.length, event;
for (i=0; i<len; i++) {
event = events[i];
if (this.visEventEnd(event) > this.visStart && event.start < this.visEnd) {
res.push(event);
}
}
return res;
},
// event element manipulation
clearEvents: function() { // just remove ELEMENTS
@@ -115,7 +110,7 @@ var viewMethods = {
var i, event2, events = this.eventsByID[event._id];
for (i=0; i<events.length; i++) {
event2 = events[i];
event2.hasTime = event.hasTime;
event2.allDay = event.allDay;
addMinutes(addDays(event2.start, days, true), minutes);
if (event.end) {
event2.end = addMinutes(addDays(this.eventEnd(event2), days, true), minutes);
@@ -239,27 +234,11 @@ function stackSegs(segs) {
}else{
levels[j] = [seg];
}
seg.after = 0;
//seg.after = 0;
}
return levels;
}
function segAfters(levels) { // TODO: put in agenda.js
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);
}
}
}
}
}
function segCmp(a, b) {
return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
}