aboutsummaryrefslogtreecommitdiffstats
path: root/library/fullcalendar/fullcalendar.js
diff options
context:
space:
mode:
authorOlivier Migeot <olivier+github@migeot.org>2013-04-10 13:15:09 +0200
committerOlivier Migeot <olivier+github@migeot.org>2013-04-10 13:16:41 +0200
commit29419257827cacb1128242e139cde764d873060a (patch)
tree8f49ba45b0ddb6c6e87f58a48f2fde5cd600fc08 /library/fullcalendar/fullcalendar.js
parent989e78137edf1c8d0a85038965fb12e7bffb3e7a (diff)
downloadvolse-hubzilla-29419257827cacb1128242e139cde764d873060a.tar.gz
volse-hubzilla-29419257827cacb1128242e139cde764d873060a.tar.bz2
volse-hubzilla-29419257827cacb1128242e139cde764d873060a.zip
Upgraded jQuery to 1.9.1, including jQuery Migrate (for the sake of keeping old code working) and upgrade Fullcalendar (because Migrate just wasn't enough for him).
Diffstat (limited to 'library/fullcalendar/fullcalendar.js')
-rw-r--r--library/fullcalendar/fullcalendar.js665
1 files changed, 409 insertions, 256 deletions
diff --git a/library/fullcalendar/fullcalendar.js b/library/fullcalendar/fullcalendar.js
index 779a313c7..648938fee 100644
--- a/library/fullcalendar/fullcalendar.js
+++ b/library/fullcalendar/fullcalendar.js
@@ -1,23 +1,20 @@
-/**
- * @preserve
- * FullCalendar v1.5.3
- * http://arshaw.com/fullcalendar/
- *
+/*!
+ * FullCalendar v1.6.0
+ * Docs & License: http://arshaw.com/fullcalendar/
+ * (c) 2013 Adam Shaw
+ */
+
+/*
* Use fullcalendar.css for basic styling.
* For event drag & drop, requires jQuery UI draggable.
* For event resizing, requires jQuery UI resizable.
- *
- * Copyright (c) 2011 Adam Shaw
- * Dual licensed under the MIT and GPL licenses, located in
- * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
- *
- * Date: Mon Feb 6 22:40:40 2012 -0800
- *
*/
(function($, undefined) {
+;;
+
var defaults = {
// display
@@ -29,6 +26,9 @@ var defaults = {
right: 'today prev,next'
},
weekends: true,
+ weekNumbers: false,
+ weekNumberCalculation: 'iso',
+ weekNumberTitle: 'W',
// editing
//editable: false,
@@ -66,10 +66,10 @@ var defaults = {
dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
buttonText: {
- prev: '&nbsp;&#9668;&nbsp;',
- next: '&nbsp;&#9658;&nbsp;',
- prevYear: '&nbsp;&lt;&lt;&nbsp;',
- nextYear: '&nbsp;&gt;&gt;&nbsp;',
+ prev: "<span class='fc-text-arrow'>&lsaquo;</span>",
+ next: "<span class='fc-text-arrow'>&rsaquo;</span>",
+ prevYear: "<span class='fc-text-arrow'>&laquo;</span>",
+ nextYear: "<span class='fc-text-arrow'>&raquo;</span>",
today: 'today',
month: 'month',
week: 'week',
@@ -98,10 +98,10 @@ var rtlDefaults = {
right: 'title'
},
buttonText: {
- prev: '&nbsp;&#9658;&nbsp;',
- next: '&nbsp;&#9668;&nbsp;',
- prevYear: '&nbsp;&gt;&gt;&nbsp;',
- nextYear: '&nbsp;&lt;&lt;&nbsp;'
+ prev: "<span class='fc-text-arrow'>&rsaquo;</span>",
+ next: "<span class='fc-text-arrow'>&lsaquo;</span>",
+ prevYear: "<span class='fc-text-arrow'>&raquo;</span>",
+ nextYear: "<span class='fc-text-arrow'>&laquo;</span>"
},
buttonIcons: {
prev: 'circle-triangle-e',
@@ -111,7 +111,9 @@ var rtlDefaults = {
-var fc = $.fullCalendar = { version: "1.5.3" };
+;;
+
+var fc = $.fullCalendar = { version: "1.6.0" };
var fcViews = fc.views = {};
@@ -177,6 +179,8 @@ function setDefaults(d) {
+;;
+
function Calendar(element, options, eventSources) {
var t = this;
@@ -258,6 +262,9 @@ function Calendar(element, options, eventSources) {
if (options.isRTL) {
element.addClass('fc-rtl');
}
+ else {
+ element.addClass('fc-ltr');
+ }
if (options.theme) {
element.addClass('ui-widget');
}
@@ -674,6 +681,8 @@ function Calendar(element, options, eventSources) {
}
+;;
+
function Header(calendar, options) {
var t = this;
@@ -747,54 +756,47 @@ function Header(calendar, options) {
var text = smartProperty(options.buttonText, buttonName); // why are we using smartProperty here?
var button = $(
"<span class='fc-button fc-button-" + buttonName + " " + tm + "-state-default'>" +
- "<span class='fc-button-inner'>" +
- "<span class='fc-button-content'>" +
- (icon ?
- "<span class='fc-icon-wrap'>" +
- "<span class='ui-icon ui-icon-" + icon + "'/>" +
- "</span>" :
- text
- ) +
- "</span>" +
- "<span class='fc-button-effect'><span></span></span>" +
- "</span>" +
+ (icon ?
+ "<span class='fc-icon-wrap'>" +
+ "<span class='ui-icon ui-icon-" + icon + "'/>" +
+ "</span>" :
+ text
+ ) +
"</span>"
- );
- if (button) {
- button
- .click(function() {
- if (!button.hasClass(tm + '-state-disabled')) {
- buttonClick();
- }
- })
- .mousedown(function() {
+ )
+ .click(function() {
+ if (!button.hasClass(tm + '-state-disabled')) {
+ buttonClick();
+ }
+ })
+ .mousedown(function() {
+ button
+ .not('.' + tm + '-state-active')
+ .not('.' + tm + '-state-disabled')
+ .addClass(tm + '-state-down');
+ })
+ .mouseup(function() {
+ button.removeClass(tm + '-state-down');
+ })
+ .hover(
+ function() {
button
.not('.' + tm + '-state-active')
.not('.' + tm + '-state-disabled')
- .addClass(tm + '-state-down');
- })
- .mouseup(function() {
- button.removeClass(tm + '-state-down');
- })
- .hover(
- function() {
- button
- .not('.' + tm + '-state-active')
- .not('.' + tm + '-state-disabled')
- .addClass(tm + '-state-hover');
- },
- function() {
- button
- .removeClass(tm + '-state-hover')
- .removeClass(tm + '-state-down');
- }
- )
- .appendTo(e);
- if (!prevButton) {
- button.addClass(tm + '-corner-left');
- }
- prevButton = button;
+ .addClass(tm + '-state-hover');
+ },
+ function() {
+ button
+ .removeClass(tm + '-state-hover')
+ .removeClass(tm + '-state-down');
+ }
+ )
+ .appendTo(e);
+ disableTextSelection(button);
+ if (!prevButton) {
+ button.addClass(tm + '-corner-left');
}
+ prevButton = button;
}
}
});
@@ -839,6 +841,8 @@ function Header(calendar, options) {
}
+;;
+
fc.sourceNormalizers = [];
fc.sourceFetchers = [];
@@ -914,6 +918,16 @@ function EventManager(options, _sources) {
_fetchEventSource(source, function(events) {
if (fetchID == currentFetchID) {
if (events) {
+
+ if (options.eventDataTransform) {
+ events = $.map(events, options.eventDataTransform);
+ }
+ if (source.eventDataTransform) {
+ events = $.map(events, source.eventDataTransform);
+ }
+ // TODO: this technique is not ideal for static array event sources.
+ // For arrays, we'll want to process all events right in the beginning, then never again.
+
for (var i=0; i<events.length; i++) {
events[i].source = source;
normalizeEvent(events[i]);
@@ -1227,6 +1241,8 @@ function EventManager(options, _sources) {
}
+;;
+
fc.addDays = addDays;
fc.cloneDate = cloneDate;
@@ -1581,10 +1597,38 @@ var dateFormatters = {
return 'th';
}
return ['st', 'nd', 'rd'][date%10-1] || 'th';
+ },
+ w : function(d, o) { // local
+ return o.weekNumberCalculation(d);
+ },
+ W : function(d) { // ISO
+ return iso8601Week(d);
}
};
+fc.dateFormatters = dateFormatters;
+
+
+/* thanks jQuery UI (https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js)
+ *
+ * Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
+ * @param date Date - the date to get the week for
+ * @return number - the number of the week within the year that contains this date
+ */
+function iso8601Week(date) {
+ var time;
+ var checkDate = new Date(date.getTime());
+
+ // Find Thursday of this week starting on Monday
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+
+ time = checkDate.getTime();
+ checkDate.setMonth(0); // Compare with Jan 1
+ checkDate.setDate(1);
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+}
+;;
fc.applyAll = applyAll;
@@ -1658,7 +1702,7 @@ function sliceSegs(events, visEventEnds, start, end) {
msLength: segEnd - segStart
});
}
- }
+ }
return segs.sort(segCmp);
}
@@ -1742,29 +1786,26 @@ function setOuterHeight(element, height, includeMargins) {
}
-// TODO: curCSS has been deprecated (jQuery 1.4.3 - 10/16/2010)
-
-
function hsides(element, includeMargins) {
return hpadding(element) + hborders(element) + (includeMargins ? hmargins(element) : 0);
}
function hpadding(element) {
- return (parseFloat($.curCSS(element[0], 'paddingLeft', true)) || 0) +
- (parseFloat($.curCSS(element[0], 'paddingRight', true)) || 0);
+ return (parseFloat($.css(element[0], 'paddingLeft', true)) || 0) +
+ (parseFloat($.css(element[0], 'paddingRight', true)) || 0);
}
function hmargins(element) {
- return (parseFloat($.curCSS(element[0], 'marginLeft', true)) || 0) +
- (parseFloat($.curCSS(element[0], 'marginRight', true)) || 0);
+ return (parseFloat($.css(element[0], 'marginLeft', true)) || 0) +
+ (parseFloat($.css(element[0], 'marginRight', true)) || 0);
}
function hborders(element) {
- return (parseFloat($.curCSS(element[0], 'borderLeftWidth', true)) || 0) +
- (parseFloat($.curCSS(element[0], 'borderRightWidth', true)) || 0);
+ return (parseFloat($.css(element[0], 'borderLeftWidth', true)) || 0) +
+ (parseFloat($.css(element[0], 'borderRightWidth', true)) || 0);
}
@@ -1774,20 +1815,20 @@ function vsides(element, includeMargins) {
function vpadding(element) {
- return (parseFloat($.curCSS(element[0], 'paddingTop', true)) || 0) +
- (parseFloat($.curCSS(element[0], 'paddingBottom', true)) || 0);
+ return (parseFloat($.css(element[0], 'paddingTop', true)) || 0) +
+ (parseFloat($.css(element[0], 'paddingBottom', true)) || 0);
}
function vmargins(element) {
- return (parseFloat($.curCSS(element[0], 'marginTop', true)) || 0) +
- (parseFloat($.curCSS(element[0], 'marginBottom', true)) || 0);
+ return (parseFloat($.css(element[0], 'marginTop', true)) || 0) +
+ (parseFloat($.css(element[0], 'marginBottom', true)) || 0);
}
function vborders(element) {
- return (parseFloat($.curCSS(element[0], 'borderTopWidth', true)) || 0) +
- (parseFloat($.curCSS(element[0], 'borderBottomWidth', true)) || 0);
+ return (parseFloat($.css(element[0], 'borderTopWidth', true)) || 0) +
+ (parseFloat($.css(element[0], 'borderBottomWidth', true)) || 0);
}
@@ -1956,6 +1997,7 @@ function firstDefined() {
}
+;;
fcViews.month = MonthView;
@@ -2003,12 +2045,14 @@ function MonthView(element, calendar) {
t.end = end;
t.visStart = visStart;
t.visEnd = visEnd;
- renderBasic(6, rowCnt, nwe ? 5 : 7, true);
+ renderBasic(rowCnt, nwe ? 5 : 7, true);
}
}
+;;
+
fcViews.basicWeek = BasicWeekView;
function BasicWeekView(element, calendar) {
@@ -2049,12 +2093,14 @@ function BasicWeekView(element, calendar) {
t.end = end;
t.visStart = visStart;
t.visEnd = visEnd;
- renderBasic(1, 1, weekends ? 7 : 5, false);
+ renderBasic(1, weekends ? 7 : 5, false);
}
}
+;;
+
fcViews.basicDay = BasicDayView;
//TODO: when calendar's date starts out on a weekend, shouldn't happen
@@ -2086,12 +2132,14 @@ function BasicDayView(element, calendar) {
t.title = formatDate(date, opt('titleFormat'));
t.start = t.visStart = cloneDate(date, true);
t.end = t.visEnd = addDays(cloneDate(t.start), 1);
- renderBasic(1, 1, 1, false);
+ renderBasic(1, 1, false);
}
}
+;;
+
setDefaults({
weekMode: 'fixed'
});
@@ -2144,6 +2192,7 @@ function BasicView(element, calendar, viewName) {
// locals
+ var table;
var head;
var headCells;
var body;
@@ -2156,6 +2205,7 @@ function BasicView(element, calendar, viewName) {
var viewWidth;
var viewHeight;
var colWidth;
+ var weekNumberWidth;
var rowCnt, colCnt;
var coordinateGrid;
@@ -2164,9 +2214,12 @@ function BasicView(element, calendar, viewName) {
var rtl, dis, dit;
var firstDay;
- var nwe;
+ var nwe; // no weekends? a 0 or 1 for easy computations
var tm;
var colFormat;
+ var showWeekNumbers;
+ var weekNumberTitle;
+ var weekNumberFormat;
@@ -2177,17 +2230,17 @@ function BasicView(element, calendar, viewName) {
disableTextSelection(element.addClass('fc-grid'));
- function renderBasic(maxr, r, c, showNumbers) {
+ function renderBasic(r, c, showNumbers) {
rowCnt = r;
colCnt = c;
updateOptions();
var firstTime = !body;
if (firstTime) {
- buildSkeleton(maxr, showNumbers);
+ buildEventContainer();
}else{
clearEvents();
}
- updateCells(firstTime);
+ buildTable(showNumbers);
}
@@ -2205,124 +2258,141 @@ function BasicView(element, calendar, viewName) {
nwe = opt('weekends') ? 0 : 1;
tm = opt('theme') ? 'ui' : 'fc';
colFormat = opt('columnFormat');
+
+ // week # options. (TODO: bad, logic also in other views)
+ showWeekNumbers = opt('weekNumbers');
+ weekNumberTitle = opt('weekNumberTitle');
+ if (opt('weekNumberCalculation') != 'iso') {
+ weekNumberFormat = "w";
+ }
+ else {
+ weekNumberFormat = "W";
+ }
}
- function buildSkeleton(maxRowCnt, showNumbers) {
- var s;
+ function buildEventContainer() {
+ daySegmentContainer =
+ $("<div style='position:absolute;z-index:8;top:0;left:0'/>")
+ .appendTo(element);
+ }
+
+
+
+ function buildTable(showNumbers) {
+ var html = '';
+ var i, j;
var headerClass = tm + "-widget-header";
var contentClass = tm + "-widget-content";
- var i, j;
- var table;
-
- s =
- "<table class='fc-border-separate' style='width:100%' cellspacing='0'>" +
- "<thead>" +
- "<tr>";
+ var month = t.start.getMonth();
+ var today = clearTime(new Date());
+ var cellDate; // not to be confused with local function. TODO: better names
+ var cellClasses;
+ var cell;
+
+ html += "<table class='fc-border-separate' style='width:100%' cellspacing='0'>" +
+ "<thead>" +
+ "<tr>";
+
+ if (showWeekNumbers) {
+ html += "<th class='fc-week-number " + headerClass + "'/>";
+ }
+
for (i=0; i<colCnt; i++) {
- s +=
- "<th class='fc- " + headerClass + "'/>"; // need fc- for setDayID
+ html += "<th class='fc-day-header fc-" + dayIDs[i] + " " + headerClass + "'/>";
}
- s +=
- "</tr>" +
- "</thead>" +
- "<tbody>";
- for (i=0; i<maxRowCnt; i++) {
- s +=
- "<tr class='fc-week" + i + "'>";
+
+ html += "</tr>" +
+ "</thead>" +
+ "<tbody>";
+
+ for (i=0; i<rowCnt; i++) {
+ html += "<tr class='fc-week'>";
+
+ if (showWeekNumbers) {
+ html += "<td class='fc-week-number " + contentClass + "'>" +
+ "<div/>" +
+ "</td>";
+ }
+
for (j=0; j<colCnt; j++) {
- s +=
- "<td class='fc- " + contentClass + " fc-day" + (i*colCnt+j) + "'>" + // need fc- for setDayID
- "<div>" +
- (showNumbers ?
- "<div class='fc-day-number'/>" :
- ''
- ) +
- "<div class='fc-day-content'>" +
- "<div style='position:relative'>&nbsp;</div>" +
- "</div>" +
- "</div>" +
- "</td>";
+ cellDate = _cellDate(i, j); // a little confusing. cellDate is local variable. _cellDate is private function
+
+ cellClasses = [
+ 'fc-day',
+ 'fc-' + dayIDs[cellDate.getDay()],
+ contentClass
+ ];
+ if (cellDate.getMonth() != month) {
+ cellClasses.push('fc-other-month');
+ }
+ if (+cellDate == +today) {
+ cellClasses.push('fc-today');
+ cellClasses.push(tm + '-state-highlight');
+ }
+
+ html += "<td" +
+ " class='" + cellClasses.join(' ') + "'" +
+ " data-date='" + formatDate(cellDate, 'yyyy-MM-dd') + "'" +
+ ">" +
+ "<div>";
+ if (showNumbers) {
+ html += "<div class='fc-day-number'>" + cellDate.getDate() + "</div>";
+ }
+ html += "<div class='fc-day-content'>" +
+ "<div style='position:relative'>&nbsp;</div>" +
+ "</div>" +
+ "</div>" +
+ "</td>";
}
- s +=
- "</tr>";
+
+ html += "</tr>";
}
- s +=
- "</tbody>" +
- "</table>";
- table = $(s).appendTo(element);
-
+ html += "</tbody>" +
+ "</table>";
+
+ lockHeight(); // the unlock happens later, in setHeight()...
+ if (table) {
+ table.remove();
+ }
+ table = $(html).appendTo(element);
+
head = table.find('thead');
- headCells = head.find('th');
+ headCells = head.find('.fc-day-header');
body = table.find('tbody');
bodyRows = body.find('tr');
- bodyCells = body.find('td');
- bodyFirstCells = bodyCells.filter(':first-child');
- bodyCellTopInners = bodyRows.eq(0).find('div.fc-day-content div');
+ bodyCells = body.find('.fc-day');
+ bodyFirstCells = bodyRows.find('td:first-child');
+ bodyCellTopInners = bodyRows.eq(0).find('.fc-day-content > div');
markFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's
markFirstLast(bodyRows); // marks first+last td's
- bodyRows.eq(0).addClass('fc-first'); // fc-last is done in updateCells
-
- dayBind(bodyCells);
-
- daySegmentContainer =
- $("<div style='position:absolute;z-index:8;top:0;left:0'/>")
- .appendTo(element);
- }
+ bodyRows.eq(0).addClass('fc-first');
+ bodyRows.filter(':last').addClass('fc-last');
-
-
- function updateCells(firstTime) {
- var dowDirty = firstTime || rowCnt == 1; // could the cells' day-of-weeks need updating?
- var month = t.start.getMonth();
- var today = clearTime(new Date());
- var cell;
- var date;
- var row;
-
- if (dowDirty) {
- headCells.each(function(i, _cell) {
- cell = $(_cell);
- date = indexDate(i);
- cell.html(formatDate(date, colFormat));
- setDayID(cell, date);
+ if (showWeekNumbers) {
+ head.find('.fc-week-number').text(weekNumberTitle);
+ }
+
+ headCells.each(function(i, _cell) {
+ var date = indexDate(i);
+ $(_cell).text(formatDate(date, colFormat));
+ });
+
+ if (showWeekNumbers) {
+ body.find('.fc-week-number > div').each(function(i, _cell) {
+ var weekStart = _cellDate(i, 0);
+ $(_cell).text(formatDate(weekStart, weekNumberFormat));
});
}
bodyCells.each(function(i, _cell) {
- cell = $(_cell);
- date = indexDate(i);
- if (date.getMonth() == month) {
- cell.removeClass('fc-other-month');
- }else{
- cell.addClass('fc-other-month');
- }
- if (+date == +today) {
- cell.addClass(tm + '-state-highlight fc-today');
- }else{
- cell.removeClass(tm + '-state-highlight fc-today');
- }
- cell.find('div.fc-day-number').text(date.getDate());
- if (dowDirty) {
- setDayID(cell, date);
- }
- });
-
- bodyRows.each(function(i, _row) {
- row = $(_row);
- if (i < rowCnt) {
- row.show();
- if (i == rowCnt-1) {
- row.addClass('fc-last');
- }else{
- row.removeClass('fc-last');
- }
- }else{
- row.hide();
- }
+ var date = indexDate(i);
+ trigger('dayRender', t, date, $(_cell));
});
+
+ dayBind(bodyCells);
}
@@ -2352,13 +2422,20 @@ function BasicView(element, calendar, viewName) {
}
});
+ unlockHeight();
}
function setWidth(width) {
viewWidth = width;
colContentPositions.clear();
- colWidth = Math.floor(viewWidth / colCnt);
+
+ weekNumberWidth = 0;
+ if (showWeekNumbers) {
+ weekNumberWidth = head.find('th.fc-week-number').outerWidth();
+ }
+
+ colWidth = Math.floor((viewWidth - weekNumberWidth) / colCnt);
setOuterWidth(headCells.slice(0, -1), colWidth);
}
@@ -2376,8 +2453,7 @@ function BasicView(element, calendar, viewName) {
function dayClick(ev) {
if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
- var index = parseInt(this.className.match(/fc\-day(\d+)/)[1]); // TODO: maybe use .data
- var date = indexDate(index);
+ var date = parseISO8601($(this).data('date'));
trigger('dayClick', this, date, true, ev);
}
}
@@ -2568,15 +2644,34 @@ function BasicView(element, calendar, viewName) {
function allDayBounds(i) {
+ var left = 0;
+ if (showWeekNumbers) {
+ left += weekNumberWidth;
+ }
return {
- left: 0,
+ left: left,
right: viewWidth
};
}
-
+
+
+
+ // makes sure height doesn't collapse while we destroy/render new cells
+ // (this causes a bad end-user scrollbar jump)
+ // TODO: generalize this for all view rendering. (also in Calendar.js)
+
+ function lockHeight() {
+ setMinHeight(element, element.height());
+ }
+
+ function unlockHeight() {
+ setMinHeight(element, 1);
+ }
}
+;;
+
function BasicEventRenderer() {
var t = this;
@@ -2619,6 +2714,7 @@ function BasicEventRenderer() {
function renderEvents(events, modifiedEventId) {
reportEvents(events);
renderDaySegs(compileSegs(events), modifiedEventId);
+ trigger('eventAfterAllRender');
}
@@ -2718,6 +2814,8 @@ function BasicEventRenderer() {
}
+;;
+
fcViews.agendaWeek = AgendaWeekView;
function AgendaWeekView(element, calendar) {
@@ -2764,6 +2862,8 @@ function AgendaWeekView(element, calendar) {
}
+;;
+
fcViews.agendaDay = AgendaDayView;
function AgendaDayView(element, calendar) {
@@ -2800,6 +2900,8 @@ function AgendaDayView(element, calendar) {
}
+;;
+
setDefaults({
allDaySlot: true,
allDayText: 'all-day',
@@ -2851,7 +2953,8 @@ function AgendaView(element, calendar, viewName) {
t.getRowCnt = function() { return 1 };
t.getColCnt = function() { return colCnt };
t.getColWidth = function() { return colWidth };
- t.getSlotHeight = function() { return slotHeight };
+ t.getSnapHeight = function() { return snapHeight };
+ t.getSnapMinutes = function() { return snapMinutes };
t.defaultSelectionEnd = defaultSelectionEnd;
t.renderDayOverlay = renderDayOverlay;
t.renderSelection = renderSelection;
@@ -2907,7 +3010,10 @@ function AgendaView(element, calendar, viewName) {
var colWidth;
var gutterWidth;
var slotHeight; // TODO: what if slotHeight changes? (see issue 650)
- var savedScrollTop;
+
+ var snapMinutes;
+ var snapRatio; // ratio of number of "selection" slots to normal slots. (ex: 1, 2, 4)
+ var snapHeight; // holds the pixel hight of a "selection" slot
var colCnt;
var slotCnt;
@@ -2915,6 +3021,7 @@ function AgendaView(element, calendar, viewName) {
var hoverListener;
var colContentPositions;
var slotTopCache = {};
+ var savedScrollTop;
var tm;
var firstDay;
@@ -2922,6 +3029,9 @@ function AgendaView(element, calendar, viewName) {
var rtl, dis, dit; // day index sign / translate
var minMinute, maxMinute;
var colFormat;
+ var showWeekNumbers;
+ var weekNumberTitle;
+ var weekNumberFormat;
@@ -2959,6 +3069,18 @@ function AgendaView(element, calendar, viewName) {
minMinute = parseTime(opt('minTime'));
maxMinute = parseTime(opt('maxTime'));
colFormat = opt('columnFormat');
+
+ // week # options. (TODO: bad, logic also in other views)
+ showWeekNumbers = opt('weekNumbers');
+ weekNumberTitle = opt('weekNumberTitle');
+ if (opt('weekNumberCalculation') != 'iso') {
+ weekNumberFormat = "w";
+ }
+ else {
+ weekNumberFormat = "W";
+ }
+
+ snapMinutes = opt('snapMinutes') || opt('slotMinutes');
}
@@ -2976,8 +3098,15 @@ function AgendaView(element, calendar, viewName) {
s =
"<table style='width:100%' class='fc-agenda-days fc-border-separate' cellspacing='0'>" +
"<thead>" +
- "<tr>" +
- "<th class='fc-agenda-axis " + headerClass + "'>&nbsp;</th>";
+ "<tr>";
+
+ if (showWeekNumbers) {
+ s += "<th class='fc-agenda-axis fc-week-number " + headerClass + "'/>";
+ }
+ else {
+ s += "<th class='fc-agenda-axis " + headerClass + "'>&nbsp;</th>";
+ }
+
for (i=0; i<colCnt; i++) {
s +=
"<th class='fc- fc-col" + i + ' ' + headerClass + "'/>"; // fc- needed for setDayID
@@ -3111,6 +3240,18 @@ function AgendaView(element, calendar, viewName) {
var bodyCell;
var date;
var today = clearTime(new Date());
+
+ if (showWeekNumbers) {
+ var weekText = formatDate(colDate(0), weekNumberFormat);
+ if (rtl) {
+ weekText = weekText + weekNumberTitle;
+ }
+ else {
+ weekText = weekNumberTitle + weekText;
+ }
+ dayHead.find('.fc-week-number').text(weekText);
+ }
+
for (i=0; i<colCnt; i++) {
date = colDate(i);
headCell = dayHeadCells.eq(i);
@@ -3149,6 +3290,9 @@ function AgendaView(element, calendar, viewName) {
slotScroller.height(bodyHeight - allDayHeight - 1);
slotHeight = slotTableFirstInner.height() + 1; // +1 for border
+
+ snapRatio = opt('slotMinutes') / snapMinutes;
+ snapHeight = slotHeight / snapRatio;
if (dateChanged) {
resetScroll();
@@ -3337,10 +3481,10 @@ function AgendaView(element, calendar, viewName) {
function constrain(n) {
return Math.max(slotScrollerTop, Math.min(slotScrollerBottom, n));
}
- for (var i=0; i<slotCnt; i++) {
+ for (var i=0; i<slotCnt*snapRatio; i++) { // adapt slot count to increased/decreased selection slot count
rows.push([
- constrain(slotTableTop + slotHeight*i),
- constrain(slotTableTop + slotHeight*(i+1))
+ constrain(slotTableTop + snapHeight*i),
+ constrain(slotTableTop + snapHeight*(i+1))
]);
}
});
@@ -3381,7 +3525,7 @@ function AgendaView(element, calendar, viewName) {
slotIndex--;
}
if (slotIndex >= 0) {
- addMinutes(d, minMinute + slotIndex * opt('slotMinutes'));
+ addMinutes(d, minMinute + slotIndex * snapMinutes);
}
return d;
}
@@ -3544,9 +3688,9 @@ function AgendaView(element, calendar, viewName) {
var d2 = cellDate(cell);
dates = [
d1,
- addMinutes(cloneDate(d1), opt('slotMinutes')),
+ addMinutes(cloneDate(d1), snapMinutes), // calculate minutes depending on selection slot minutes
d2,
- addMinutes(cloneDate(d2), opt('slotMinutes'))
+ addMinutes(cloneDate(d2), snapMinutes)
].sort(cmp);
renderSlotSelection(dates[0], dates[3]);
}else{
@@ -3603,6 +3747,8 @@ function AgendaView(element, calendar, viewName) {
}
+;;
+
function AgendaEventRenderer() {
var t = this;
@@ -3639,7 +3785,8 @@ function AgendaEventRenderer() {
var resizableDayEvent = t.resizableDayEvent; // TODO: streamline binding architecture
var getColCnt = t.getColCnt;
var getColWidth = t.getColWidth;
- var getSlotHeight = t.getSlotHeight;
+ var getSnapHeight = t.getSnapHeight;
+ var getSnapMinutes = t.getSnapMinutes;
var getBodyContent = t.getBodyContent;
var reportEventElement = t.reportEventElement;
var showEvents = t.showEvents;
@@ -3675,6 +3822,7 @@ function AgendaEventRenderer() {
setHeight(); // no params means set to viewHeight
}
renderSlotSegs(compileSlotSegs(slotEvents), modifiedEventId);
+ trigger('eventAfterAllRender');
}
@@ -3760,7 +3908,7 @@ function AgendaEventRenderer() {
vsideCache={},
hsideCache={},
key, val,
- contentElement,
+ titleElement,
height,
slotSegmentContainer = getSlotSegmentContainer(),
rtl, dis, dit,
@@ -3849,9 +3997,9 @@ function AgendaEventRenderer() {
seg.vsides = val === undefined ? (vsideCache[key] = vsides(eventElement, true)) : val;
val = hsideCache[key];
seg.hsides = val === undefined ? (hsideCache[key] = hsides(eventElement, true)) : val;
- contentElement = eventElement.find('div.fc-event-content');
- if (contentElement.length) {
- seg.contentTop = contentElement[0].offsetTop;
+ titleElement = eventElement.find('.fc-event-title');
+ if (titleElement.length) {
+ seg.contentTop = titleElement[0].offsetTop;
}
}
}
@@ -3865,7 +4013,7 @@ function AgendaEventRenderer() {
eventElement[0].style.height = height + 'px';
event = seg.event;
if (seg.contentTop !== undefined && height - seg.contentTop < 10) {
- // not enough room for title, put it in the time header
+ // not enough room for title, put it in the time (TODO: maybe make both display:inline instead)
eventElement.find('div.fc-event-time')
.text(formatDate(event.start, opt('timeFormat')) + ' - ' + event.title);
eventElement.find('div.fc-event-title')
@@ -3882,16 +4030,15 @@ function AgendaEventRenderer() {
var html = "<";
var url = event.url;
var skinCss = getSkinCss(event, opt);
- var skinCssAttr = (skinCss ? " style='" + skinCss + "'" : '');
- var classes = ['fc-event', 'fc-event-skin', 'fc-event-vert'];
+ var classes = ['fc-event', 'fc-event-vert'];
if (isEventDraggable(event)) {
classes.push('fc-event-draggable');
}
if (seg.isStart) {
- classes.push('fc-corner-top');
+ classes.push('fc-event-start');
}
if (seg.isEnd) {
- classes.push('fc-corner-bottom');
+ classes.push('fc-event-end');
}
classes = classes.concat(event.className);
if (event.source) {
@@ -3906,19 +4053,15 @@ function AgendaEventRenderer() {
" class='" + classes.join(' ') + "'" +
" style='position:absolute;z-index:8;top:" + seg.top + "px;left:" + seg.left + "px;" + skinCss + "'" +
">" +
- "<div class='fc-event-inner fc-event-skin'" + skinCssAttr + ">" +
- "<div class='fc-event-head fc-event-skin'" + skinCssAttr + ">" +
+ "<div class='fc-event-inner'>" +
"<div class='fc-event-time'>" +
htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +
"</div>" +
- "</div>" +
- "<div class='fc-event-content'>" +
"<div class='fc-event-title'>" +
htmlEscape(event.title) +
"</div>" +
"</div>" +
- "<div class='fc-event-bg'></div>" +
- "</div>"; // close inner
+ "<div class='fc-event-bg'></div>";
if (seg.isEnd && isEventResizable(event)) {
html +=
"<div class='ui-resizable-handle ui-resizable-s'>=</div>";
@@ -3968,7 +4111,8 @@ function AgendaEventRenderer() {
var dis = opt('isRTL') ? -1 : 1;
var hoverListener = getHoverListener();
var colWidth = getColWidth();
- var slotHeight = getSlotHeight();
+ var snapHeight = getSnapHeight();
+ var snapMinutes = getSnapMinutes();
var minMinute = getMinMinute();
eventElement.draggable({
zIndex: 9,
@@ -3999,9 +4143,9 @@ function AgendaEventRenderer() {
eventElement.width(colWidth - 10); // don't use entire width
setOuterHeight(
eventElement,
- slotHeight * Math.round(
- (event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes'))
- / opt('slotMinutes')
+ snapHeight * Math.round(
+ (event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes')) /
+ snapMinutes
)
);
eventElement.draggable('option', 'grid', [colWidth, 1]);
@@ -4033,8 +4177,8 @@ function AgendaEventRenderer() {
// changed!
var minuteDelta = 0;
if (!allDay) {
- minuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / slotHeight)
- * opt('slotMinutes')
+ minuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / snapHeight)
+ * snapMinutes
+ minMinute
- (event.start.getHours() * 60 + event.start.getMinutes());
}
@@ -4067,11 +4211,12 @@ function AgendaEventRenderer() {
var hoverListener = getHoverListener();
var colCnt = getColCnt();
var colWidth = getColWidth();
- var slotHeight = getSlotHeight();
+ var snapHeight = getSnapHeight();
+ var snapMinutes = getSnapMinutes();
eventElement.draggable({
zIndex: 9,
scroll: false,
- grid: [colWidth, slotHeight],
+ grid: [colWidth, snapHeight],
axis: colCnt==1 ? 'y' : false,
opacity: opt('dragOpacity'),
revertDuration: opt('dragRevertDuration'),
@@ -4105,7 +4250,7 @@ function AgendaEventRenderer() {
}, ev, 'drag');
},
drag: function(ev, ui) {
- minuteDelta = Math.round((ui.position.top - origPosition.top) / slotHeight) * opt('slotMinutes');
+ minuteDelta = Math.round((ui.position.top - origPosition.top) / snapHeight) * snapMinutes;
if (minuteDelta != prevMinuteDelta) {
if (!allDay) {
updateTimeText(minuteDelta);
@@ -4142,7 +4287,7 @@ function AgendaEventRenderer() {
// convert back to original slot-event
if (allDay) {
timeElement.css('display', ''); // show() was causing display=inline
- eventElement.draggable('option', 'grid', [colWidth, slotHeight]);
+ eventElement.draggable('option', 'grid', [colWidth, snapHeight]);
allDay = false;
}
}
@@ -4155,38 +4300,39 @@ function AgendaEventRenderer() {
function resizableSlotEvent(event, eventElement, timeElement) {
- var slotDelta, prevSlotDelta;
- var slotHeight = getSlotHeight();
+ var snapDelta, prevSnapDelta;
+ var snapHeight = getSnapHeight();
+ var snapMinutes = getSnapMinutes();
eventElement.resizable({
handles: {
- s: 'div.ui-resizable-s'
+ s: '.ui-resizable-handle'
},
- grid: slotHeight,
+ grid: snapHeight,
start: function(ev, ui) {
- slotDelta = prevSlotDelta = 0;
+ snapDelta = prevSnapDelta = 0;
hideEvents(event, eventElement);
eventElement.css('z-index', 9);
trigger('eventResizeStart', this, event, ev, ui);
},
resize: function(ev, ui) {
// don't rely on ui.size.height, doesn't take grid into account
- slotDelta = Math.round((Math.max(slotHeight, eventElement.height()) - ui.originalSize.height) / slotHeight);
- if (slotDelta != prevSlotDelta) {
+ snapDelta = Math.round((Math.max(snapHeight, eventElement.height()) - ui.originalSize.height) / snapHeight);
+ if (snapDelta != prevSnapDelta) {
timeElement.text(
formatDates(
event.start,
- (!slotDelta && !event.end) ? null : // no change, so don't display time range
- addMinutes(eventEnd(event), opt('slotMinutes')*slotDelta),
+ (!snapDelta && !event.end) ? null : // no change, so don't display time range
+ addMinutes(eventEnd(event), snapMinutes*snapDelta),
opt('timeFormat')
)
);
- prevSlotDelta = slotDelta;
+ prevSnapDelta = snapDelta;
}
},
stop: function(ev, ui) {
trigger('eventResizeStop', this, event, ev, ui);
- if (slotDelta) {
- eventResize(this, event, 0, opt('slotMinutes')*slotDelta, ev, ui);
+ if (snapDelta) {
+ eventResize(this, event, 0, snapMinutes*snapDelta, ev, ui);
}else{
eventElement.css('z-index', 8);
showEvents(event, eventElement);
@@ -4218,6 +4364,8 @@ function countForwardSegs(levels) {
+;;
+
function View(element, calendar, viewName) {
var t = this;
@@ -4472,6 +4620,8 @@ function View(element, calendar, viewName) {
}
+;;
+
function DayEventRenderer() {
var t = this;
@@ -4609,28 +4759,22 @@ function DayEventRenderer() {
for (i=0; i<segCnt; i++) {
seg = segs[i];
event = seg.event;
- classes = ['fc-event', 'fc-event-skin', 'fc-event-hori'];
+ classes = ['fc-event', 'fc-event-hori'];
if (isEventDraggable(event)) {
classes.push('fc-event-draggable');
}
+ if (seg.isStart) {
+ classes.push('fc-event-start');
+ }
+ if (seg.isEnd) {
+ classes.push('fc-event-end');
+ }
if (rtl) {
- if (seg.isStart) {
- classes.push('fc-corner-right');
- }
- if (seg.isEnd) {
- classes.push('fc-corner-left');
- }
leftCol = dayOfWeekCol(seg.end.getDay()-1);
rightCol = dayOfWeekCol(seg.start.getDay());
left = seg.isEnd ? colContentLeft(leftCol) : minLeft;
right = seg.isStart ? colContentRight(rightCol) : maxLeft;
}else{
- if (seg.isStart) {
- classes.push('fc-corner-left');
- }
- if (seg.isEnd) {
- classes.push('fc-corner-right');
- }
leftCol = dayOfWeekCol(seg.start.getDay());
rightCol = dayOfWeekCol(seg.end.getDay()-1);
left = seg.isStart ? colContentLeft(leftCol) : minLeft;
@@ -4651,10 +4795,7 @@ function DayEventRenderer() {
" class='" + classes.join(' ') + "'" +
" style='position:absolute;z-index:8;left:"+left+"px;" + skinCss + "'" +
">" +
- "<div" +
- " class='fc-event-inner fc-event-skin'" +
- (skinCss ? " style='" + skinCss + "'" : '') +
- ">";
+ "<div class='fc-event-inner'>";
if (!event.allDay && seg.isStart) {
html +=
"<span class='fc-event-time'>" +
@@ -4816,7 +4957,7 @@ function DayEventRenderer() {
var rowDivs = [];
for (i=0; i<rowCnt; i++) {
rowDivs[i] = allDayRow(i)
- .find('td:first div.fc-day-content > div'); // optimal selector?
+ .find('div.fc-day-content > div'); // optimal selector?
}
return rowDivs;
}
@@ -4859,7 +5000,7 @@ function DayEventRenderer() {
function resizableDayEvent(event, element, seg) {
var rtl = opt('isRTL');
var direction = rtl ? 'w' : 'e';
- var handle = element.find('div.ui-resizable-' + direction);
+ var handle = element.find('.ui-resizable-' + direction); // TODO: stop using this class because we aren't using jqui for this
var isResizing = false;
// TODO: look into using jquery-ui mouse widget for this stuff
@@ -4955,6 +5096,8 @@ function DayEventRenderer() {
}
+;;
+
//BUG: unselect needs to be triggered when events are dragged+dropped
function SelectionManager() {
@@ -5052,6 +5195,8 @@ function SelectionManager() {
}
+
+;;
function OverlayManager() {
var t = this;
@@ -5090,6 +5235,8 @@ function OverlayManager() {
}
+;;
+
function CoordinateGrid(buildFunc) {
var t = this;
@@ -5136,6 +5283,8 @@ function CoordinateGrid(buildFunc) {
}
+;;
+
function HoverListener(coordinateGrid) {
@@ -5194,6 +5343,8 @@ function _fixUIEvent(event) { // for issue 1168
event.pageY = event.originalEvent.pageY;
}
}
+;;
+
function HorizontalPositionCache(getElement) {
var t = this,
@@ -5220,5 +5371,7 @@ function HorizontalPositionCache(getElement) {
};
}
-
-})(jQuery);
+
+;;
+
+})(jQuery); \ No newline at end of file