|
|
@@ -1,1262 +0,0 @@
|
|
|
-
|
|
|
-/* Agenda Views: agendaWeek/agendaDay
|
|
|
------------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-setDefaults({
|
|
|
- allDaySlot: true,
|
|
|
- allDayText: 'all-day',
|
|
|
- firstHour: 6,
|
|
|
- slotMinutes: 30,
|
|
|
- defaultEventMinutes: 120,
|
|
|
- axisFormat: 'h(:mm)tt',
|
|
|
- timeFormat: {
|
|
|
- agenda: 'h:mm{ - h:mm}'
|
|
|
- },
|
|
|
- dragOpacity: {
|
|
|
- agenda: .5
|
|
|
- },
|
|
|
- minTime: 0,
|
|
|
- maxTime: 24
|
|
|
-});
|
|
|
-
|
|
|
-views.agendaWeek = function(element, options, viewName) {
|
|
|
- return new Agenda(element, options, {
|
|
|
- render: function(date, delta) {
|
|
|
- if (delta) {
|
|
|
- addDays(date, delta * 7);
|
|
|
- }
|
|
|
- var visStart = this.visStart = cloneDate(
|
|
|
- this.start = addDays(cloneDate(date), -((date.getDay() - options.firstDay + 7) % 7))
|
|
|
- ),
|
|
|
- visEnd = this.visEnd = cloneDate(
|
|
|
- this.end = addDays(cloneDate(visStart), 7)
|
|
|
- );
|
|
|
- if (!options.weekends) {
|
|
|
- skipWeekend(visStart);
|
|
|
- skipWeekend(visEnd, -1, true);
|
|
|
- }
|
|
|
- this.title = formatDates(
|
|
|
- visStart,
|
|
|
- addDays(cloneDate(visEnd), -1),
|
|
|
- this.option('titleFormat'),
|
|
|
- options
|
|
|
- );
|
|
|
- this.renderAgenda(
|
|
|
- options.weekends ? 7 : 5,
|
|
|
- this.option('columnFormat')
|
|
|
- );
|
|
|
- }
|
|
|
- }, viewName);
|
|
|
-};
|
|
|
-
|
|
|
-views.agendaDay = function(element, options, viewName) {
|
|
|
- return new Agenda(element, options, {
|
|
|
- render: function(date, delta) {
|
|
|
- if (delta) {
|
|
|
- addDays(date, delta);
|
|
|
- if (!options.weekends) {
|
|
|
- skipWeekend(date, delta < 0 ? -1 : 1);
|
|
|
- }
|
|
|
- }
|
|
|
- this.title = formatDate(date, this.option('titleFormat'), options);
|
|
|
- this.start = this.visStart = cloneDate(date, true);
|
|
|
- this.end = this.visEnd = addDays(cloneDate(this.start), 1);
|
|
|
- this.renderAgenda(
|
|
|
- 1,
|
|
|
- this.option('columnFormat')
|
|
|
- );
|
|
|
- }
|
|
|
- }, viewName);
|
|
|
-};
|
|
|
-
|
|
|
-function Agenda(element, options, methods, viewName) {
|
|
|
-
|
|
|
- var head, body, bodyContent, bodyTable, bg,
|
|
|
- colCnt,
|
|
|
- slotCnt=0, // spanning all the way across
|
|
|
- axisWidth, colWidth, slotHeight,
|
|
|
- viewWidth, viewHeight,
|
|
|
- savedScrollTop,
|
|
|
- cachedEvents=[],
|
|
|
- daySegmentContainer,
|
|
|
- slotSegmentContainer,
|
|
|
- tm, firstDay,
|
|
|
- nwe, // no weekends (int)
|
|
|
- rtl, dis, dit, // day index sign / translate
|
|
|
- minMinute, maxMinute,
|
|
|
- colContentPositions = new HorizontalPositionCache(function(col) {
|
|
|
- return bg.find('td:eq(' + col + ') div div');
|
|
|
- }),
|
|
|
- slotTopCache = {},
|
|
|
- // ...
|
|
|
-
|
|
|
- view = $.extend(this, viewMethods, methods, {
|
|
|
- renderAgenda: renderAgenda,
|
|
|
- renderEvents: renderEvents,
|
|
|
- rerenderEvents: rerenderEvents,
|
|
|
- clearEvents: clearEvents,
|
|
|
- setHeight: setHeight,
|
|
|
- setWidth: setWidth,
|
|
|
- beforeHide: function() {
|
|
|
- savedScrollTop = body.scrollTop();
|
|
|
- },
|
|
|
- afterShow: function() {
|
|
|
- body.scrollTop(savedScrollTop);
|
|
|
- },
|
|
|
- defaultEventEnd: function(event) {
|
|
|
- var start = cloneDate(event.start);
|
|
|
- if (event.allDay) {
|
|
|
- return start;
|
|
|
- }
|
|
|
- return addMinutes(start, options.defaultEventMinutes);
|
|
|
- }
|
|
|
- });
|
|
|
- view.name = viewName;
|
|
|
- view.init(element, options);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Time-slot rendering
|
|
|
- -----------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-
|
|
|
- disableTextSelection(element.addClass('fc-agenda'));
|
|
|
-
|
|
|
-
|
|
|
- function renderAgenda(c, colFormat) {
|
|
|
-
|
|
|
- colCnt = c;
|
|
|
-
|
|
|
- // update option-derived variables
|
|
|
- tm = options.theme ? 'ui' : 'fc';
|
|
|
- nwe = options.weekends ? 0 : 1;
|
|
|
- firstDay = options.firstDay;
|
|
|
- if (rtl = options.isRTL) {
|
|
|
- dis = -1;
|
|
|
- dit = colCnt - 1;
|
|
|
- }else{
|
|
|
- dis = 1;
|
|
|
- dit = 0;
|
|
|
- }
|
|
|
- minMinute = parseTime(options.minTime);
|
|
|
- maxMinute = parseTime(options.maxTime);
|
|
|
-
|
|
|
- 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
|
|
|
-
|
|
|
- var i,
|
|
|
- minutes,
|
|
|
- slotNormal = options.slotMinutes % 15 == 0, //...
|
|
|
-
|
|
|
- // head
|
|
|
- s = "<div class='fc-agenda-head' style='position:relative;z-index:4'>" +
|
|
|
- "<table style='width:100%'>" +
|
|
|
- "<tr class='fc-first" + (options.allDaySlot ? '' : ' fc-last') + "'>" +
|
|
|
- "<th class='fc-leftmost " +
|
|
|
- tm + "-state-default'> </th>";
|
|
|
- for (i=0; i<colCnt; i++) {
|
|
|
- s += "<th class='fc-" +
|
|
|
- dayIDs[d.getDay()] + ' ' + // needs to be first
|
|
|
- tm + '-state-default' +
|
|
|
- "'>" + formatDate(d, colFormat, options) + "</th>";
|
|
|
- addDays(d, dis);
|
|
|
- if (nwe) {
|
|
|
- skipWeekend(d, dis);
|
|
|
- }
|
|
|
- }
|
|
|
- s += "<th class='" + tm + "-state-default'> </th></tr>";
|
|
|
- if (options.allDaySlot) {
|
|
|
- s += "<tr class='fc-all-day'>" +
|
|
|
- "<th class='fc-axis fc-leftmost " + tm + "-state-default'>" + options.allDayText + "</th>" +
|
|
|
- "<td colspan='" + colCnt + "' class='" + tm + "-state-default'>" +
|
|
|
- "<div class='fc-day-content'><div style='position:relative'> </div></div></td>" +
|
|
|
- "<th class='" + tm + "-state-default'> </th>" +
|
|
|
- "</tr><tr class='fc-divider fc-last'><th colspan='" + (colCnt+2) + "' class='" +
|
|
|
- tm + "-state-default fc-leftmost'><div/></th></tr>";
|
|
|
- }
|
|
|
- s+= "</table></div>";
|
|
|
- head = $(s).appendTo(element);
|
|
|
- dayBind(head.find('td'));
|
|
|
-
|
|
|
- // all-day event container
|
|
|
- daySegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(head);
|
|
|
-
|
|
|
- // body
|
|
|
- d = zeroDate();
|
|
|
- var maxd = addMinutes(cloneDate(d), maxMinute);
|
|
|
- addMinutes(d, minMinute);
|
|
|
- s = "<table>";
|
|
|
- for (i=0; d < maxd; i++) {
|
|
|
- minutes = d.getMinutes();
|
|
|
- s += "<tr class='" +
|
|
|
- (!i ? 'fc-first' : (!minutes ? '' : 'fc-minor')) +
|
|
|
- "'><th class='fc-axis fc-leftmost " + tm + "-state-default'>" +
|
|
|
- ((!slotNormal || !minutes) ? formatDate(d, options.axisFormat) : ' ') +
|
|
|
- "</th><td class='fc-slot" + i + ' ' +
|
|
|
- tm + "-state-default'><div style='position:relative'> </div></td></tr>";
|
|
|
- addMinutes(d, options.slotMinutes);
|
|
|
- slotCnt++;
|
|
|
- }
|
|
|
- s += "</table>";
|
|
|
- body = $("<div class='fc-agenda-body' style='position:relative;z-index:2;overflow:auto'/>")
|
|
|
- .append(bodyContent = $("<div style='position:relative;overflow:hidden'>")
|
|
|
- .append(bodyTable = $(s)))
|
|
|
- .appendTo(element);
|
|
|
- slotBind(body.find('td'));
|
|
|
-
|
|
|
- // slot event container
|
|
|
- slotSegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(bodyContent);
|
|
|
-
|
|
|
- // background stripes
|
|
|
- d = cloneDate(d0);
|
|
|
- s = "<div class='fc-agenda-bg' style='position:absolute;z-index:1'>" +
|
|
|
- "<table style='width:100%;height:100%'><tr class='fc-first'>";
|
|
|
- for (i=0; i<colCnt; i++) {
|
|
|
- s += "<td class='fc-" +
|
|
|
- dayIDs[d.getDay()] + ' ' + // needs to be first
|
|
|
- tm + '-state-default ' +
|
|
|
- (!i ? 'fc-leftmost ' : '') +
|
|
|
- (+d == +today ? tm + '-state-highlight fc-today' : 'fc-not-today') +
|
|
|
- "'><div class='fc-day-content'><div> </div></div></td>";
|
|
|
- addDays(d, dis);
|
|
|
- if (nwe) {
|
|
|
- skipWeekend(d, dis);
|
|
|
- }
|
|
|
- }
|
|
|
- s += "</tr></table></div>";
|
|
|
- bg = $(s).appendTo(element);
|
|
|
-
|
|
|
- }else{ // skeleton already built, just modify it
|
|
|
-
|
|
|
- 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);
|
|
|
- if (nwe) {
|
|
|
- skipWeekend(d, dis);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // change classes of background stripes
|
|
|
- d = cloneDate(d0);
|
|
|
- bg.find('td').each(function() {
|
|
|
- this.className = this.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
|
|
|
- if (+d == +today) {
|
|
|
- $(this)
|
|
|
- .removeClass('fc-not-today')
|
|
|
- .addClass('fc-today')
|
|
|
- .addClass(tm + '-state-highlight');
|
|
|
- }else{
|
|
|
- $(this)
|
|
|
- .addClass('fc-not-today')
|
|
|
- .removeClass('fc-today')
|
|
|
- .removeClass(tm + '-state-highlight');
|
|
|
- }
|
|
|
- addDays(d, dis);
|
|
|
- if (nwe) {
|
|
|
- skipWeekend(d, dis);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function resetScroll() {
|
|
|
- var d0 = zeroDate(),
|
|
|
- scrollDate = cloneDate(d0);
|
|
|
- scrollDate.setHours(options.firstHour);
|
|
|
- var top = timePosition(d0, scrollDate) + 1, // +1 for the border
|
|
|
- scroll = function() {
|
|
|
- body.scrollTop(top);
|
|
|
- };
|
|
|
- scroll();
|
|
|
- setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function setHeight(height, dateChanged) {
|
|
|
- viewHeight = height;
|
|
|
- slotTopCache = {};
|
|
|
-
|
|
|
- body.height(height - head.height());
|
|
|
-
|
|
|
- slotHeight = body.find('tr:first div').height() + 1;
|
|
|
-
|
|
|
- bg.css({
|
|
|
- top: head.find('tr').height(),
|
|
|
- height: height
|
|
|
- });
|
|
|
-
|
|
|
- // if the table ends up shorter than the allotted view, shrink the view to fit the table
|
|
|
- var tableHeight=body.find('table:first').height();
|
|
|
- if (tableHeight<body.height()) {
|
|
|
- body.height(tableHeight);
|
|
|
- }
|
|
|
-
|
|
|
- if (dateChanged) {
|
|
|
- resetScroll();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function setWidth(width) {
|
|
|
- viewWidth = width;
|
|
|
- colContentPositions.clear();
|
|
|
-
|
|
|
- body.width(width);
|
|
|
- bodyTable.width('');
|
|
|
-
|
|
|
- var topTDs = head.find('tr:first th'),
|
|
|
- stripeTDs = bg.find('td'),
|
|
|
- clientWidth = body[0].clientWidth;
|
|
|
-
|
|
|
- bodyTable.width(clientWidth);
|
|
|
-
|
|
|
- // time-axis width
|
|
|
- axisWidth = 0;
|
|
|
- setOuterWidth(
|
|
|
- head.find('tr:lt(2) th:first').add(body.find('tr:first th'))
|
|
|
- .width('')
|
|
|
- .each(function() {
|
|
|
- axisWidth = Math.max(axisWidth, $(this).outerWidth());
|
|
|
- }),
|
|
|
- axisWidth
|
|
|
- );
|
|
|
-
|
|
|
- // column width
|
|
|
- colWidth = Math.floor((clientWidth - axisWidth) / colCnt);
|
|
|
- setOuterWidth(stripeTDs.slice(0, -1), colWidth);
|
|
|
- setOuterWidth(topTDs.slice(1, -2), colWidth);
|
|
|
-
|
|
|
- var scrollbar=body[0].scrollHeight!=body[0].clientHeight;
|
|
|
-
|
|
|
- if (scrollbar) {
|
|
|
- setOuterWidth(topTDs.slice(-2, -1), clientWidth - axisWidth - colWidth*(colCnt-1));
|
|
|
- } else {
|
|
|
- topTDs.slice(-1).hide();
|
|
|
- $('tr.fc-all-day th').slice(-1).hide();
|
|
|
- }
|
|
|
- bg.css({
|
|
|
- left: axisWidth,
|
|
|
- width: clientWidth - axisWidth
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Slot/Day clicking and binding
|
|
|
- -----------------------------------------------------------------------*/
|
|
|
-
|
|
|
-
|
|
|
- function dayBind(tds) {
|
|
|
- tds.click(slotClick)
|
|
|
- .mousedown(daySelectionMousedown);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function slotBind(tds) {
|
|
|
- tds.click(slotClick)
|
|
|
- .mousedown(slotSelectionMousedown);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function slotClick(ev) {
|
|
|
- if (!view.option('selectable')) { // SelectionManager will worry about dayClick
|
|
|
- var col = Math.min(colCnt-1, Math.floor((ev.pageX - bg.offset().left) / colWidth)),
|
|
|
- date = addDays(cloneDate(view.visStart), col*dis+dit),
|
|
|
- rowMatch = this.className.match(/fc-slot(\d+)/);
|
|
|
- if (rowMatch) {
|
|
|
- var mins = parseInt(rowMatch[1]) * options.slotMinutes,
|
|
|
- hours = Math.floor(mins/60);
|
|
|
- date.setHours(hours);
|
|
|
- date.setMinutes(mins%60 + minMinute);
|
|
|
- view.trigger('dayClick', this, date, false, ev);
|
|
|
- }else{
|
|
|
- view.trigger('dayClick', this, date, true, ev);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Event Rendering
|
|
|
- -----------------------------------------------------------------------------*/
|
|
|
-
|
|
|
- function renderEvents(events, modifiedEventId) {
|
|
|
- view.reportEvents(cachedEvents = events);
|
|
|
- var i, len=events.length,
|
|
|
- dayEvents=[],
|
|
|
- slotEvents=[];
|
|
|
- for (i=0; i<len; i++) {
|
|
|
- if (events[i].allDay) {
|
|
|
- dayEvents.push(events[i]);
|
|
|
- }else{
|
|
|
- slotEvents.push(events[i]);
|
|
|
- }
|
|
|
- }
|
|
|
- renderDaySegs(compileDaySegs(dayEvents), modifiedEventId);
|
|
|
- renderSlotSegs(compileSlotSegs(slotEvents), modifiedEventId);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function rerenderEvents(modifiedEventId) {
|
|
|
- clearEvents();
|
|
|
- renderEvents(cachedEvents, modifiedEventId);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function clearEvents() {
|
|
|
- view._clearEvents(); // only clears the hashes
|
|
|
- daySegmentContainer.empty();
|
|
|
- slotSegmentContainer.empty();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- function compileDaySegs(events) {
|
|
|
- var levels = stackSegs(view.sliceSegs(events, $.map(events, exclEndDay), view.visStart, view.visEnd)),
|
|
|
- i, levelCnt=levels.length, level,
|
|
|
- j, seg,
|
|
|
- segs=[];
|
|
|
- for (i=0; i<levelCnt; i++) {
|
|
|
- level = levels[i];
|
|
|
- for (j=0; j<level.length; j++) {
|
|
|
- seg = level[j];
|
|
|
- seg.row = 0;
|
|
|
- seg.level = i;
|
|
|
- segs.push(seg);
|
|
|
- }
|
|
|
- }
|
|
|
- return segs;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function compileSlotSegs(events) {
|
|
|
- var d = addMinutes(cloneDate(view.visStart), minMinute),
|
|
|
- visEventEnds = $.map(events, slotEventEnd),
|
|
|
- i, col,
|
|
|
- j, level,
|
|
|
- k, seg,
|
|
|
- segs=[];
|
|
|
- for (i=0; i<colCnt; i++) {
|
|
|
- col = stackSegs(view.sliceSegs(events, visEventEnds, d, addMinutes(cloneDate(d), maxMinute-minMinute)));
|
|
|
- countForwardSegs(col);
|
|
|
- for (j=0; j<col.length; j++) {
|
|
|
- level = col[j];
|
|
|
- for (k=0; k<level.length; k++) {
|
|
|
- seg = level[k];
|
|
|
- seg.col = i;
|
|
|
- seg.level = j;
|
|
|
- segs.push(seg);
|
|
|
- }
|
|
|
- }
|
|
|
- addDays(d, 1, true);
|
|
|
- }
|
|
|
- return segs;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // renders 'all-day' events at the top
|
|
|
-
|
|
|
- function renderDaySegs(segs, modifiedEventId) {
|
|
|
- if (options.allDaySlot) {
|
|
|
- _renderDaySegs(
|
|
|
- segs,
|
|
|
- 1,
|
|
|
- view,
|
|
|
- axisWidth,
|
|
|
- viewWidth,
|
|
|
- function() {
|
|
|
- return head.find('tr.fc-all-day');
|
|
|
- },
|
|
|
- function(dayOfWeek) {
|
|
|
- return axisWidth + colContentPositions.left(dayOfWeekCol(dayOfWeek));
|
|
|
- },
|
|
|
- function(dayOfWeek) {
|
|
|
- return axisWidth + colContentPositions.right(dayOfWeekCol(dayOfWeek));
|
|
|
- },
|
|
|
- daySegmentContainer,
|
|
|
- daySegBind,
|
|
|
- modifiedEventId
|
|
|
- );
|
|
|
- setHeight(viewHeight); // might have pushed the body down, so resize
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // renders events in the 'time slots' at the bottom
|
|
|
-
|
|
|
- function renderSlotSegs(segs, modifiedEventId) {
|
|
|
-
|
|
|
- var i, segCnt=segs.length, seg,
|
|
|
- event,
|
|
|
- className,
|
|
|
- top, bottom,
|
|
|
- colI, levelI, forward,
|
|
|
- leftmost,
|
|
|
- availWidth,
|
|
|
- outerWidth,
|
|
|
- left,
|
|
|
- html='',
|
|
|
- eventElements,
|
|
|
- eventElement,
|
|
|
- triggerRes,
|
|
|
- vsideCache={},
|
|
|
- hsideCache={},
|
|
|
- key, val,
|
|
|
- titleSpan,
|
|
|
- height;
|
|
|
-
|
|
|
- // calculate position/dimensions, create html
|
|
|
- for (i=0; i<segCnt; i++) {
|
|
|
- seg = segs[i];
|
|
|
- event = seg.event;
|
|
|
- className = 'fc-event fc-event-vert ';
|
|
|
- if (seg.isStart) {
|
|
|
- className += 'fc-corner-top ';
|
|
|
- }
|
|
|
- if (seg.isEnd) {
|
|
|
- className += 'fc-corner-bottom ';
|
|
|
- }
|
|
|
- top = timePosition(seg.start, seg.start);
|
|
|
- bottom = timePosition(seg.start, seg.end);
|
|
|
- colI = seg.col;
|
|
|
- levelI = seg.level;
|
|
|
- forward = seg.forward || 0;
|
|
|
- leftmost = axisWidth + colContentPositions.left(colI*dis + dit);
|
|
|
- availWidth = axisWidth + colContentPositions.right(colI*dis + dit) - leftmost;
|
|
|
- availWidth = Math.min(availWidth-6, availWidth*.95); // TODO: move this to CSS
|
|
|
- if (levelI) {
|
|
|
- // indented and thin
|
|
|
- outerWidth = availWidth / (levelI + forward + 1);
|
|
|
- }else{
|
|
|
- if (forward) {
|
|
|
- // moderately wide, aligned left still
|
|
|
- outerWidth = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
|
|
- }else{
|
|
|
- // can be entire width, aligned left
|
|
|
- outerWidth = availWidth;
|
|
|
- }
|
|
|
- }
|
|
|
- left = leftmost + // leftmost possible
|
|
|
- (availWidth / (levelI + forward + 1) * levelI) // indentation
|
|
|
- * dis + (rtl ? availWidth - outerWidth : 0); // rtl
|
|
|
- seg.top = top;
|
|
|
- seg.left = left;
|
|
|
- seg.outerWidth = outerWidth;
|
|
|
- seg.outerHeight = bottom - top;
|
|
|
- html += slotSegHtml(event, seg, className);
|
|
|
- }
|
|
|
- slotSegmentContainer[0].innerHTML = html; // faster than html()
|
|
|
- eventElements = slotSegmentContainer.children();
|
|
|
-
|
|
|
- // retrieve elements, run through eventRender callback, bind event handlers
|
|
|
- for (i=0; i<segCnt; i++) {
|
|
|
- seg = segs[i];
|
|
|
- event = seg.event;
|
|
|
- eventElement = $(eventElements[i]); // faster than eq()
|
|
|
- triggerRes = view.trigger('eventRender', event, event, eventElement);
|
|
|
- if (triggerRes === false) {
|
|
|
- eventElement.remove();
|
|
|
- }else{
|
|
|
- if (triggerRes && triggerRes !== true) {
|
|
|
- eventElement.remove();
|
|
|
- eventElement = $(triggerRes)
|
|
|
- .css({
|
|
|
- position: 'absolute',
|
|
|
- top: seg.top,
|
|
|
- left: seg.left
|
|
|
- })
|
|
|
- .appendTo(slotSegmentContainer);
|
|
|
- }
|
|
|
- seg.element = eventElement;
|
|
|
- if (event._id === modifiedEventId) {
|
|
|
- slotSegBind(event, eventElement, seg);
|
|
|
- }else{
|
|
|
- eventElement[0]._fci = i; // for lazySegBind
|
|
|
- }
|
|
|
- view.reportEventElement(event, eventElement);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- lazySegBind(slotSegmentContainer, segs, slotSegBind);
|
|
|
-
|
|
|
- // record event sides and title positions
|
|
|
- for (i=0; i<segCnt; i++) {
|
|
|
- seg = segs[i];
|
|
|
- if (eventElement = seg.element) {
|
|
|
- val = vsideCache[key = seg.key = cssKey(eventElement[0])];
|
|
|
- seg.vsides = val === undefined ? (vsideCache[key] = vsides(eventElement[0], true)) : val;
|
|
|
- val = hsideCache[key];
|
|
|
- seg.hsides = val === undefined ? (hsideCache[key] = hsides(eventElement[0], true)) : val;
|
|
|
- titleSpan = eventElement.find('span.fc-event-title');
|
|
|
- if (titleSpan.length) {
|
|
|
- seg.titleTop = titleSpan[0].offsetTop;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // set all positions/dimensions at once
|
|
|
- for (i=0; i<segCnt; i++) {
|
|
|
- seg = segs[i];
|
|
|
- if (eventElement = seg.element) {
|
|
|
- eventElement[0].style.width = seg.outerWidth - seg.hsides + 'px';
|
|
|
- eventElement[0].style.height = (height = seg.outerHeight - seg.vsides) + 'px';
|
|
|
- event = seg.event;
|
|
|
- if (seg.titleTop !== undefined && height - seg.titleTop < 10) {
|
|
|
- // not enough room for title, put it in the time header
|
|
|
- eventElement.find('span.fc-event-time')
|
|
|
- .text(formatDate(event.start, view.option('timeFormat')) + ' - ' + event.title);
|
|
|
- eventElement.find('span.fc-event-title')
|
|
|
- .remove();
|
|
|
- }
|
|
|
- view.trigger('eventAfterRender', event, event, eventElement);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function slotSegHtml(event, seg, className) {
|
|
|
- return "<div class='" + className + event.className.join(' ') + "' style='position:absolute;z-index:8;top:" + seg.top + "px;left:" + seg.left + "px'>" +
|
|
|
- "<a" + (event.url ? " href='" + htmlEscape(event.url) + "'" : '') + ">" +
|
|
|
- "<span class='fc-event-bg'></span>" +
|
|
|
- "<span class='fc-event-time'>" + htmlEscape(formatDates(event.start, event.end, view.option('timeFormat'))) + "</span>" +
|
|
|
- "<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
|
|
- "</a>" +
|
|
|
- ((event.editable || event.editable === undefined && options.editable) && !options.disableResizing && $.fn.resizable ?
|
|
|
- "<div class='ui-resizable-handle ui-resizable-s'>=</div>"
|
|
|
- : '') +
|
|
|
- "</div>";
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- function daySegBind(event, eventElement, seg) {
|
|
|
- view.eventElementHandlers(event, eventElement);
|
|
|
- if (event.editable || event.editable === undefined && options.editable) {
|
|
|
- draggableDayEvent(event, eventElement, seg.isStart);
|
|
|
- if (seg.isEnd) {
|
|
|
- view.resizableDayEvent(event, eventElement, colWidth);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- function slotSegBind(event, eventElement, seg) {
|
|
|
- view.eventElementHandlers(event, eventElement);
|
|
|
- if (event.editable || event.editable === undefined && options.editable) {
|
|
|
- var timeElement = eventElement.find('span.fc-event-time');
|
|
|
- draggableSlotEvent(event, eventElement, timeElement);
|
|
|
- if (seg.isEnd) {
|
|
|
- resizableSlotEvent(event, eventElement, timeElement);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Event Dragging
|
|
|
- -----------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // when event starts out FULL-DAY
|
|
|
-
|
|
|
- function draggableDayEvent(event, eventElement, isStart) {
|
|
|
- if (!options.disableDragging && eventElement.draggable) {
|
|
|
- var origWidth;
|
|
|
- var allDay=true;
|
|
|
- var dayDelta;
|
|
|
- eventElement.draggable({
|
|
|
- zIndex: 9,
|
|
|
- opacity: view.option('dragOpacity', 'month'), // use whatever the month view was using
|
|
|
- revertDuration: options.dragRevertDuration,
|
|
|
- start: function(ev, ui) {
|
|
|
- view.trigger('eventDragStart', eventElement, event, ev, ui);
|
|
|
- view.hideEvents(event, eventElement);
|
|
|
- origWidth = eventElement.width();
|
|
|
- hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
|
|
- eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
|
|
|
- clearOverlay();
|
|
|
- if (cell) {
|
|
|
- dayDelta = colDelta * dis;
|
|
|
- if (!cell.row) {
|
|
|
- // on full-days
|
|
|
- renderDayOverlay(
|
|
|
- addDays(cloneDate(event.start), dayDelta),
|
|
|
- addDays(exclEndDay(event), dayDelta)
|
|
|
- );
|
|
|
- resetElement();
|
|
|
- }else{
|
|
|
- // mouse is over bottom slots
|
|
|
- if (isStart && allDay) {
|
|
|
- // convert event to temporary slot-event
|
|
|
- setOuterHeight(
|
|
|
- eventElement.width(colWidth - 10), // don't use entire width
|
|
|
- slotHeight * Math.round(
|
|
|
- (event.end ? ((event.end - event.start) / MINUTE_MS) : options.defaultEventMinutes)
|
|
|
- / options.slotMinutes
|
|
|
- )
|
|
|
- );
|
|
|
- eventElement.draggable('option', 'grid', [colWidth, 1]);
|
|
|
- allDay = false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }, ev, 'drag');
|
|
|
- },
|
|
|
- stop: function(ev, ui) {
|
|
|
- var cell = hoverListener.stop();
|
|
|
- clearOverlay();
|
|
|
- view.trigger('eventDragStop', eventElement, event, ev, ui);
|
|
|
- if (cell && (!allDay || dayDelta)) {
|
|
|
- // changed!
|
|
|
- eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
|
|
|
- var minuteDelta = 0;
|
|
|
- if (!allDay) {
|
|
|
- minuteDelta = Math.round((eventElement.offset().top - bodyContent.offset().top) / slotHeight)
|
|
|
- * options.slotMinutes
|
|
|
- + minMinute
|
|
|
- - (event.start.getHours() * 60 + event.start.getMinutes());
|
|
|
- }
|
|
|
- view.eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui);
|
|
|
- }else{
|
|
|
- // hasn't moved or is out of bounds (draggable has already reverted)
|
|
|
- resetElement();
|
|
|
- if ($.browser.msie) {
|
|
|
- eventElement.css('filter', ''); // clear IE opacity side-effects
|
|
|
- }
|
|
|
- view.showEvents(event, eventElement);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- function resetElement() {
|
|
|
- if (!allDay) {
|
|
|
- eventElement
|
|
|
- .width(origWidth)
|
|
|
- .height('')
|
|
|
- .draggable('option', 'grid', null);
|
|
|
- allDay = true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // when event starts out IN TIMESLOTS
|
|
|
-
|
|
|
- function draggableSlotEvent(event, eventElement, timeElement) {
|
|
|
- if (!options.disableDragging && eventElement.draggable) {
|
|
|
- var origPosition;
|
|
|
- var allDay=false;
|
|
|
- var dayDelta;
|
|
|
- var minuteDelta;
|
|
|
- var prevMinuteDelta;
|
|
|
- eventElement.draggable({
|
|
|
- zIndex: 9,
|
|
|
- scroll: false,
|
|
|
- grid: [colWidth, slotHeight],
|
|
|
- axis: colCnt==1 ? 'y' : false,
|
|
|
- opacity: view.option('dragOpacity'),
|
|
|
- revertDuration: options.dragRevertDuration,
|
|
|
- start: function(ev, ui) {
|
|
|
- view.trigger('eventDragStart', eventElement, event, ev, ui);
|
|
|
- view.hideEvents(event, eventElement);
|
|
|
- if ($.browser.msie) {
|
|
|
- eventElement.find('span.fc-event-bg').hide(); // nested opacities mess up in IE, just hide
|
|
|
- }
|
|
|
- origPosition = eventElement.position();
|
|
|
- minuteDelta = prevMinuteDelta = 0;
|
|
|
- hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
|
|
- eventElement.draggable('option', 'revert', !cell);
|
|
|
- clearOverlay();
|
|
|
- if (cell) {
|
|
|
- dayDelta = colDelta * dis;
|
|
|
- if (options.allDaySlot && !cell.row) {
|
|
|
- // over full days
|
|
|
- if (!allDay) {
|
|
|
- // convert to temporary all-day event
|
|
|
- allDay = true;
|
|
|
- timeElement.hide();
|
|
|
- eventElement.draggable('option', 'grid', null);
|
|
|
- }
|
|
|
- renderDayOverlay(
|
|
|
- addDays(cloneDate(event.start), dayDelta),
|
|
|
- addDays(exclEndDay(event), dayDelta)
|
|
|
- );
|
|
|
- }else{
|
|
|
- // on slots
|
|
|
- resetElement();
|
|
|
- }
|
|
|
- }
|
|
|
- }, ev, 'drag');
|
|
|
- },
|
|
|
- drag: function(ev, ui) {
|
|
|
- minuteDelta = Math.round((ui.position.top - origPosition.top) / slotHeight) * options.slotMinutes;
|
|
|
- if (minuteDelta != prevMinuteDelta) {
|
|
|
- if (!allDay) {
|
|
|
- updateTimeText(minuteDelta);
|
|
|
- }
|
|
|
- prevMinuteDelta = minuteDelta;
|
|
|
- }
|
|
|
- },
|
|
|
- stop: function(ev, ui) {
|
|
|
- var cell = hoverListener.stop();
|
|
|
- clearOverlay();
|
|
|
- view.trigger('eventDragStop', eventElement, event, ev, ui);
|
|
|
- if (cell && (dayDelta || minuteDelta || allDay)) {
|
|
|
- // changed!
|
|
|
- view.eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui);
|
|
|
- }else{
|
|
|
- // either no change or out-of-bounds (draggable has already reverted)
|
|
|
- resetElement();
|
|
|
- eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position
|
|
|
- updateTimeText(0);
|
|
|
- if ($.browser.msie) {
|
|
|
- eventElement
|
|
|
- .css('filter', '') // clear IE opacity side-effects
|
|
|
- .find('span.fc-event-bg')
|
|
|
- .css('display', ''); // .show() made display=inline
|
|
|
- }
|
|
|
- view.showEvents(event, eventElement);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- function updateTimeText(minuteDelta) {
|
|
|
- var newStart = addMinutes(cloneDate(event.start), minuteDelta);
|
|
|
- var newEnd;
|
|
|
- if (event.end) {
|
|
|
- newEnd = addMinutes(cloneDate(event.end), minuteDelta);
|
|
|
- }
|
|
|
- timeElement.text(formatDates(newStart, newEnd, view.option('timeFormat')));
|
|
|
- }
|
|
|
- function resetElement() {
|
|
|
- // convert back to original slot-event
|
|
|
- if (allDay) {
|
|
|
- timeElement.css('display', ''); // show() was causing display=inline
|
|
|
- eventElement.draggable('option', 'grid', [colWidth, slotHeight]);
|
|
|
- allDay = false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Event Resizing
|
|
|
- -----------------------------------------------------------------------------*/
|
|
|
-
|
|
|
- // for TIMESLOT events
|
|
|
-
|
|
|
- function resizableSlotEvent(event, eventElement, timeElement) {
|
|
|
- if (!options.disableResizing && eventElement.resizable) {
|
|
|
- var slotDelta, prevSlotDelta;
|
|
|
- eventElement.resizable({
|
|
|
- handles: {
|
|
|
- s: 'div.ui-resizable-s'
|
|
|
- },
|
|
|
- grid: slotHeight,
|
|
|
- start: function(ev, ui) {
|
|
|
- slotDelta = prevSlotDelta = 0;
|
|
|
- view.hideEvents(event, eventElement);
|
|
|
- if ($.browser.msie && $.browser.version == '6.0') {
|
|
|
- eventElement.css('overflow', 'hidden');
|
|
|
- }
|
|
|
- eventElement.css('z-index', 9);
|
|
|
- view.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) {
|
|
|
- timeElement.text(
|
|
|
- formatDates(
|
|
|
- event.start,
|
|
|
- (!slotDelta && !event.end) ? null : // no change, so don't display time range
|
|
|
- addMinutes(view.eventEnd(event), options.slotMinutes*slotDelta),
|
|
|
- view.option('timeFormat')
|
|
|
- )
|
|
|
- );
|
|
|
- prevSlotDelta = slotDelta;
|
|
|
- }
|
|
|
- },
|
|
|
- stop: function(ev, ui) {
|
|
|
- view.trigger('eventResizeStop', this, event, ev, ui);
|
|
|
- if (slotDelta) {
|
|
|
- view.eventResize(this, event, 0, options.slotMinutes*slotDelta, ev, ui);
|
|
|
- }else{
|
|
|
- eventElement.css('z-index', 8);
|
|
|
- view.showEvents(event, eventElement);
|
|
|
- // BUG: if event was really short, need to put title back in span
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Coordinate Utilities
|
|
|
- -----------------------------------------------------------------------------*/
|
|
|
-
|
|
|
- var coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
|
|
- var e, n, p;
|
|
|
- bg.find('td').each(function(i, _e) {
|
|
|
- e = $(_e);
|
|
|
- n = e.offset().left;
|
|
|
- if (i) {
|
|
|
- p[1] = n;
|
|
|
- }
|
|
|
- p = [n];
|
|
|
- cols[i] = p;
|
|
|
- });
|
|
|
- p[1] = n + e.outerWidth();
|
|
|
- if (options.allDaySlot) {
|
|
|
- e = head.find('td');
|
|
|
- n = e.offset().top;
|
|
|
- rows[0] = [n, n+e.outerHeight()];
|
|
|
- }
|
|
|
- var bodyContentTop = bodyContent.offset().top;
|
|
|
- var bodyTop = body.offset().top;
|
|
|
- var bodyBottom = bodyTop + body.outerHeight();
|
|
|
- function constrain(n) {
|
|
|
- return Math.max(bodyTop, Math.min(bodyBottom, n));
|
|
|
- }
|
|
|
- for (var i=0; i<slotCnt; i++) {
|
|
|
- rows.push([
|
|
|
- constrain(bodyContentTop + slotHeight*i),
|
|
|
- constrain(bodyContentTop + slotHeight*(i+1))
|
|
|
- ]);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- var hoverListener = new HoverListener(coordinateGrid);
|
|
|
-
|
|
|
- // get the Y coordinate of the given time on the given day (both Date objects)
|
|
|
- function timePosition(day, time) { // both date objects. day holds 00:00 of current day
|
|
|
- day = cloneDate(day, true);
|
|
|
- if (time < addMinutes(cloneDate(day), minMinute)) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (time >= addMinutes(cloneDate(day), maxMinute)) {
|
|
|
- return bodyContent.height();
|
|
|
- }
|
|
|
- var slotMinutes = options.slotMinutes,
|
|
|
- minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
|
|
- slotI = Math.floor(minutes / slotMinutes),
|
|
|
- slotTop = slotTopCache[slotI];
|
|
|
- if (slotTop === undefined) {
|
|
|
- slotTop = slotTopCache[slotI] = body.find('tr:eq(' + slotI + ') td div')[0].offsetTop;
|
|
|
- }
|
|
|
- return Math.max(0, Math.round(
|
|
|
- slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
|
|
- ));
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Selecting
|
|
|
- -----------------------------------------------------------------------------*/
|
|
|
-
|
|
|
- var selected = false;
|
|
|
- var daySelectionMousedown = selection_dayMousedown(
|
|
|
- view, hoverListener, cellDate, cellIsAllDay, renderDayOverlay, clearOverlay, reportSelection, unselect
|
|
|
- );
|
|
|
-
|
|
|
- function slotSelectionMousedown(ev) {
|
|
|
- if (view.option('selectable')) {
|
|
|
- unselect(ev);
|
|
|
- var _mousedownElement = this;
|
|
|
- var dates;
|
|
|
- hoverListener.start(function(cell, origCell) {
|
|
|
- clearSelection();
|
|
|
- if (cell && cell.col == origCell.col && !cellIsAllDay(cell)) {
|
|
|
- var d1 = cellDate(origCell);
|
|
|
- var d2 = cellDate(cell);
|
|
|
- dates = [
|
|
|
- d1,
|
|
|
- addMinutes(cloneDate(d1), options.slotMinutes),
|
|
|
- d2,
|
|
|
- addMinutes(cloneDate(d2), options.slotMinutes)
|
|
|
- ].sort(cmp);
|
|
|
- renderSlotSelection(dates[0], dates[3]);
|
|
|
- }else{
|
|
|
- dates = null;
|
|
|
- }
|
|
|
- }, ev);
|
|
|
- $(document).one('mouseup', function(ev) {
|
|
|
- hoverListener.stop();
|
|
|
- if (dates) {
|
|
|
- if (+dates[0] == +dates[1]) {
|
|
|
- view.trigger('dayClick', _mousedownElement, dates[0], false, ev);
|
|
|
- // BUG: _mousedownElement will sometimes be the overlay
|
|
|
- }
|
|
|
- reportSelection(dates[0], dates[3], false, ev);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- view.select = function(startDate, endDate, allDay) {
|
|
|
- coordinateGrid.build();
|
|
|
- unselect();
|
|
|
- if (allDay) {
|
|
|
- if (options.allDaySlot) {
|
|
|
- if (!endDate) {
|
|
|
- endDate = cloneDate(startDate);
|
|
|
- }
|
|
|
- renderDayOverlay(startDate, addDays(cloneDate(endDate), 1));
|
|
|
- }
|
|
|
- }else{
|
|
|
- if (!endDate) {
|
|
|
- endDate = addMinutes(cloneDate(startDate), options.slotMinutes);
|
|
|
- }
|
|
|
- renderSlotSelection(startDate, endDate);
|
|
|
- }
|
|
|
- reportSelection(startDate, endDate, allDay);
|
|
|
- };
|
|
|
-
|
|
|
- function reportSelection(startDate, endDate, allDay, ev) {
|
|
|
- selected = true;
|
|
|
- view.trigger('select', view, startDate, endDate, allDay, ev);
|
|
|
- }
|
|
|
-
|
|
|
- function unselect(ev) {
|
|
|
- if (selected) {
|
|
|
- clearSelection();
|
|
|
- selected = false;
|
|
|
- view.trigger('unselect', view, ev);
|
|
|
- }
|
|
|
- }
|
|
|
- view.unselect = unselect;
|
|
|
-
|
|
|
- selection_unselectAuto(view, unselect);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Selecting drawing utils
|
|
|
- -----------------------------------------------------------------------------*/
|
|
|
-
|
|
|
- var selectionHelper;
|
|
|
-
|
|
|
- function renderSlotSelection(startDate, endDate) {
|
|
|
- var helperOption = view.option('selectHelper');
|
|
|
- if (helperOption) {
|
|
|
- var col = dayDiff(startDate, view.visStart) * dis + dit;
|
|
|
- if (col >= 0 && col < colCnt) { // only works when times are on same day
|
|
|
- var rect = coordinateGrid.rect(0, col, 0, col, bodyContent); // only for horizontal coords
|
|
|
- var top = timePosition(startDate, startDate);
|
|
|
- var bottom = timePosition(startDate, endDate);
|
|
|
- if (bottom > top) { // protect against selections that are entirely before or after visible range
|
|
|
- rect.top = top;
|
|
|
- rect.height = bottom - top;
|
|
|
- rect.left += 2;
|
|
|
- rect.width -= 5;
|
|
|
- if ($.isFunction(helperOption)) {
|
|
|
- var helperRes = helperOption(startDate, endDate);
|
|
|
- if (helperRes) {
|
|
|
- rect.position = 'absolute';
|
|
|
- rect.zIndex = 8;
|
|
|
- selectionHelper = $(helperRes)
|
|
|
- .css(rect)
|
|
|
- .appendTo(bodyContent);
|
|
|
- }
|
|
|
- }else{
|
|
|
- selectionHelper = $(slotSegHtml(
|
|
|
- {
|
|
|
- title: '',
|
|
|
- start: startDate,
|
|
|
- end: endDate,
|
|
|
- className: [],
|
|
|
- editable: false
|
|
|
- },
|
|
|
- rect,
|
|
|
- 'fc-event fc-event-vert fc-corner-top fc-corner-bottom '
|
|
|
- ));
|
|
|
- if ($.browser.msie) {
|
|
|
- selectionHelper.find('span.fc-event-bg').hide(); // nested opacities mess up in IE, just hide
|
|
|
- }
|
|
|
- selectionHelper.css('opacity', view.option('dragOpacity'));
|
|
|
- }
|
|
|
- if (selectionHelper) {
|
|
|
- slotBind(selectionHelper);
|
|
|
- bodyContent.append(selectionHelper);
|
|
|
- setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended
|
|
|
- setOuterHeight(selectionHelper, rect.height, true);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }else{
|
|
|
- renderSlotOverlay(startDate, endDate);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function clearSelection() {
|
|
|
- clearOverlay();
|
|
|
- if (selectionHelper) {
|
|
|
- selectionHelper.remove();
|
|
|
- selectionHelper = null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Semi-transparent Overlay Helpers
|
|
|
- -----------------------------------------------------*/
|
|
|
-
|
|
|
- function renderDayOverlay(startDate, endDate) {
|
|
|
- var startCol, endCol;
|
|
|
- if (rtl) {
|
|
|
- startCol = dayDiff(endDate, view.visStart)*dis+dit+1;
|
|
|
- endCol = dayDiff(startDate, view.visStart)*dis+dit+1;
|
|
|
- }else{
|
|
|
- startCol = dayDiff(startDate, view.visStart);
|
|
|
- endCol = dayDiff(endDate, view.visStart);
|
|
|
- }
|
|
|
- startCol = Math.max(0, startCol);
|
|
|
- endCol = Math.min(colCnt, endCol);
|
|
|
- if (startCol < endCol) {
|
|
|
- dayBind(
|
|
|
- _renderDayOverlay(0, startCol, 0, endCol-1)
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function _renderDayOverlay(col0, row0, col1, row1) {
|
|
|
- var rect = coordinateGrid.rect(col0, row0, col1, row1, head);
|
|
|
- return view.renderOverlay(rect, head);
|
|
|
- }
|
|
|
-
|
|
|
- function renderSlotOverlay(overlayStart, overlayEnd) {
|
|
|
- var dayStart = cloneDate(view.visStart);
|
|
|
- var dayEnd = addDays(cloneDate(dayStart), 1);
|
|
|
- for (var i=0; i<colCnt; i++) {
|
|
|
- var stretchStart = new Date(Math.max(dayStart, overlayStart));
|
|
|
- var stretchEnd = new Date(Math.min(dayEnd, overlayEnd));
|
|
|
- if (stretchStart < stretchEnd) {
|
|
|
- var col = i*dis+dit;
|
|
|
- var rect = coordinateGrid.rect(0, col, 0, col, bodyContent); // only use it for horizontal coords
|
|
|
- var top = timePosition(dayStart, stretchStart);
|
|
|
- var bottom = timePosition(dayStart, stretchEnd);
|
|
|
- rect.top = top;
|
|
|
- rect.height = bottom - top;
|
|
|
- slotBind(
|
|
|
- view.renderOverlay(rect, bodyContent)
|
|
|
- );
|
|
|
- }
|
|
|
- addDays(dayStart, 1);
|
|
|
- addDays(dayEnd, 1);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function clearOverlay() {
|
|
|
- view.clearOverlays();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* External dragging
|
|
|
- -----------------------------------------------------*/
|
|
|
-
|
|
|
- view.dragStart = function(_dragElement, ev, ui) {
|
|
|
- hoverListener.start(function(cell) {
|
|
|
- clearOverlay();
|
|
|
- if (cell) {
|
|
|
- if (cellIsAllDay(cell)) {
|
|
|
- _renderDayOverlay(cell.row, cell.col, cell.row, cell.col);
|
|
|
- }else{
|
|
|
- var d1 = cellDate(cell);
|
|
|
- var d2 = addMinutes(cloneDate(d1), options.defaultEventMinutes);
|
|
|
- renderSlotOverlay(d1, d2);
|
|
|
- }
|
|
|
- }
|
|
|
- }, ev);
|
|
|
- };
|
|
|
-
|
|
|
- view.dragStop = function(_dragElement, ev, ui) {
|
|
|
- var cell = hoverListener.stop();
|
|
|
- clearOverlay();
|
|
|
- if (cell) {
|
|
|
- view.trigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /* Date Utilities
|
|
|
- ----------------------------------------------------*/
|
|
|
-
|
|
|
- function slotEventEnd(event) {
|
|
|
- if (event.end) {
|
|
|
- return cloneDate(event.end);
|
|
|
- }else{
|
|
|
- return addMinutes(cloneDate(event.start), options.defaultEventMinutes);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function dayOfWeekCol(dayOfWeek) {
|
|
|
- return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit;
|
|
|
- }
|
|
|
-
|
|
|
- function cellDate(cell) {
|
|
|
- var d = addDays(cloneDate(view.visStart), cell.col*dis+dit);
|
|
|
- var slotIndex = cell.row;
|
|
|
- if (options.allDaySlot) {
|
|
|
- slotIndex--;
|
|
|
- }
|
|
|
- if (slotIndex >= 0) {
|
|
|
- addMinutes(d, minMinute + slotIndex*options.slotMinutes);
|
|
|
- }
|
|
|
- return d;
|
|
|
- }
|
|
|
-
|
|
|
- function cellIsAllDay(cell) {
|
|
|
- return options.allDaySlot && !cell.row;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// count the number of colliding, higher-level segments (for event squishing)
|
|
|
-
|
|
|
-function countForwardSegs(levels) {
|
|
|
- var i, j, k, level, segForward, segBack;
|
|
|
- for (i=levels.length-1; i>0; i--) {
|
|
|
- level = levels[i];
|
|
|
- for (j=0; j<level.length; j++) {
|
|
|
- segForward = level[j];
|
|
|
- for (k=0; k<levels[i-1].length; k++) {
|
|
|
- segBack = levels[i-1][k];
|
|
|
- if (segsCollide(segForward, segBack)) {
|
|
|
- segBack.forward = Math.max(segBack.forward||0, (segForward.forward||0)+1);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|