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" + "" + " "; dayCnt = 0; for (d=cloneDate(start); d" + dayAbbrevs[d.getDay()] + ""; if (+d == +today) { todayI = dayCnt; } dayCnt++; } s += " " + "" + "all day" + "" + "
" + " " + "
"; head = $(s).appendTo(element); // body & event panel s = "
" + ""; d = getToday(); dDay = d.getDay(); for (i=0; d.getDay()==dDay; i++, addMinutes(d, options.slotMinutes)) { dMinutes = d.getMinutes(); s += ""; } s += "
" + (!slotNormal || dMinutes==0 ? formatDate(d, options.agendaSideTimeFormat) : ' ') + " 
"; body = $("
") .append(panel = $(s)) .appendTo(element); // background stripes s = "
" + ""; for (i=0; i
 
"; } s += "
"; bg = $(s).appendTo(element); }else{ // skeleton already built, just modify it clearEvents(); // change classes of background stripes todayI = Math.round((today - start) / msInDay); bg.find('td').each(function(i) { if (i == todayI) { $(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'); } }); // if 1-day view, change day-of-week class and header text if (dayCnt == 1) { var th = head.find('th:eq(1)').html(dayAbbrevs[start.getDay()])[0], td = bg.find('td')[0]; th.className = th.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[start.getDay()]); td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[start.getDay()]); } } updateSize(); fetchEvents(renderEvents); }; function updateSize() { // align first 'time' column timeWidth = body.find('th:first').outerWidth(); head.find('th:first').width(timeWidth); // set table width (100% in css wasn't working in IE) var panelWidth = body[0].clientWidth || body.width(); // first time, there are no scrollbars!? for IE6? body.find('table').width(panelWidth); // align spacer column to scrollbar width setOuterWidth(head.find('th:last'), body.width() - panelWidth); // position background stripe container bg.css({ left: timeWidth, width: panelWidth - timeWidth, height: element.height() }); // align other columns dayWidth = Math.floor((panelWidth - timeWidth) / dayCnt); var topCells = head.find('tr:first th:gt(0)'), bgCells = bg.find('td'); for (var i=0, len=bgCells.length-1; i view.start) { if (event.hasTime) { event._end = event.end || addMinutes(cloneDate(event.start), options.defaultEventMinutes); slotEvents.push(event); }else{ event._end = addDays(cloneDate(event.end || event.start), 1); dayEvents.push(event); } } } cachedEvents = events; cachedSlotSegs = compileSlotSegs(slotEvents, view.start, view.end); cachedDaySegs = levelizeSegs(sliceSegs(dayEvents, view.start, view.end)); renderSlotSegs(cachedSlotSegs); renderDaySegs(cachedDaySegs); } function rerenderEvents(skipCompile) { clearEvents(); if (skipCompile) { renderSlotSegs(cachedSlotSegs); renderDaySegs(cachedDaySegs); }else{ renderEvents(cachedEvents); } } function clearEvents() { for (var i=0; i") .append(anchorElement = $("") .append(titleElement = $("") .text(event.title))) .css({ position: 'absolute', zIndex: 1000, top: top, left: left }); if (event.url) { anchorElement.attr('href', event.url); } if (seg.isStart) { eventElement.addClass('fc-corner-top'); // add the time header anchorElement .prepend(timeElement = $("") .text(formatDates(event.start, event.end, options.agendaEventTimeFormat))) }else{ timeElement = null; } if (seg.isEnd) { eventElement.addClass('fc-corner-bottom'); resizableSlotEvent(event, eventElement, timeElement); } eventElement.appendTo(panel); setOuterWidth(eventElement, width, true); setOuterHeight(eventElement, bottom-top, true); if (timeElement && eventElement.height() - titleElement.position().top < 10) { // event title doesn't have enough room, but next to the time timeElement.text(formatDate(event.start, options.agendaEventTimeFormat) + ' - ' + event.title); titleElement.remove(); } draggableSlotEvent(event, eventElement, timeElement); reportEventElement(event, eventElement); } } } } // renders 'all-day' events at the top function renderDaySegs(segRow) { var td = head.find('td'); var tdInner = td.find('div div'); var top = tdInner.position().top, rowHeight = 0, i, len=segRow.length, level, levelHeight, j, seg, event, left, right, eventElement, anchorElement; for (i=0; i") .append(anchorElement = $("") .append($("") .text(event.title))) .css({ position: 'absolute', top: top, left: timeWidth + left }); if (seg.isStart) { eventElement.addClass('fc-corner-left'); } if (seg.isEnd) { eventElement.addClass('fc-corner-right'); } if (event.url) { anchorElement.attr('href', event.url); } eventElement.appendTo(head); setOuterWidth(eventElement, right-left, true); draggableDayEvent(event, eventElement); //resizableDayEvent(event, eventElement); reportEventElement(event, eventElement); levelHeight = Math.max(levelHeight, eventElement.outerHeight(true)); } top += levelHeight; rowHeight += levelHeight; } tdInner.height(rowHeight); //bg.height(element.height()); // tdInner might have pushed the body down, so resize //updateSize(); } /******************************************* draggable *****************************************/ // when event starts out IN TIMESLOTS function draggableSlotEvent(event, eventElement, timeElement) { var origPosition, origMarginTop, prevSlotDelta, slotDelta, matrix; eventElement.draggable({ zIndex: 1001, scroll: false, grid: [dayWidth, slotHeight], axis: dayCnt==1 ? 'y' : false, cancel: '.ui-resizable-handle', opacity: .5, start: function(ev, ui) { if ($.browser.msie) { eventElement.find('span.fc-event-bg').hide(); } origPosition = eventElement.position(); origMarginTop = parseInt(eventElement.css('margin-top')) || 0; prevSlotDelta = 0; matrix = new HoverMatrix(function(cell) { if (event.hasTime) { // event is an original slot-event if (cell && cell.row == 0) { // but needs to convert to temporary full-day-event var topDiff = panel.offset().top - head.offset().top; eventElement.css('margin-top', origMarginTop + topDiff) .appendTo(head); // TODO: bug in IE8 w/ above technique, draggable ends immediately event.hasTime = false; if (timeElement) { timeElement.hide(); } eventElement.draggable('option', 'grid', null); } }else{ // event is a temporary full-day-event if (cell && cell.row == 1) { // but needs to convert to original slot-event eventElement.css('margin-top', origMarginTop) .appendTo(panel); event.hasTime = true; if (timeElement) { timeElement.css('display', ''); // show() was causing display=inline } eventElement.draggable('option', 'grid', [dayWidth, slotHeight]); } } if (cell && cell.row == 0) { showDayOverlay(cell); }else{ hideDayOverlay(); } }); matrix.row(head.find('td')); bg.find('td').each(function() { matrix.col(this); }); matrix.row(body); matrix.start(); hideSimilarEvents(event, eventElement); }, drag: function(ev, ui) { slotDelta = Math.round((ui.position.top - origPosition.top) / slotHeight); if (slotDelta != prevSlotDelta) { if (timeElement && event.hasTime) { // update time header var newStart = addMinutes(cloneDate(event.start), slotDelta * options.slotMinutes), newEnd; if (event.end) { newEnd = addMinutes(cloneDate(event.end), slotDelta * options.slotMinutes); } timeElement.text(formatDates(newStart, newEnd, options.agendaEventTimeFormat)); } prevSlotDelta = slotDelta; } matrix.mouse(ev.pageX, ev.pageY); }, stop: function(ev, ui) { if (event.hasTime) { if (matrix.cell) { // over slots var dayDelta = Math.round((ui.position.left - origPosition.left) / dayWidth); reportEventMove(event, dayDelta, true, slotDelta * options.slotMinutes); } }else{ // over full-days if (!matrix.cell) { // was being dragged over full-days, but finished over nothing, reset event.hasTime = true; }else{ event.end = null; reportEventMove(event, matrix.cell.colDelta); } } hideDayOverlay(); rerenderEvents(); } }); } // when event starts out FULL-DAY function draggableDayEvent(event, eventElement) { var origWidth, matrix; eventElement.draggable({ zIndex: 1001, start: function() { origWidth = eventElement.width(); matrix = new HoverMatrix(function(cell) { if (!cell) { // mouse is outside of everything hideDayOverlay(); }else{ if (cell.row == 0) { // on full-days if (event.hasTime) { // and needs to be original full-day event eventElement .width(origWidth) .height('') .draggable('option', 'grid', null); event.hasTime = false; } showDayOverlay(cell); }else{ // mouse is over bottom slots if (!event.hasTime) { // convert event to temporary slot-event //if (+cloneDate(event.start, true) == +cloneDate(event._end, true)) { // only change styles if a 1-day event eventElement .width(dayWidth - 10) // don't use entire width .height(slotHeight * Math.round(options.defaultEventMinutes/options.slotMinutes) - 2); //} eventElement.draggable('option', 'grid', [dayWidth, 1]); event.hasTime = true; } hideDayOverlay(); } } }); matrix.row(head.find('td')); bg.find('td').each(function() { matrix.col(this); }); matrix.row(body); matrix.start(); hideSimilarEvents(event, eventElement); }, drag: function(ev, ui) { matrix.mouse(ev.pageX, ev.pageY); }, stop: function() { var cell = matrix.cell; if (!cell) { // over nothing if (event.hasTime) { // event was on the slots before going out, convert back event.hasTime = false; } }else{ if (!event.hasTime) { // event has been dropped on a full-day reportEventMove(event, cell.colDelta); }else{ // event has been dropped on the slots var slots = Math.floor((eventElement.offset().top - panel.offset().top) / slotHeight); event.end = null; reportEventMove(event, cell.colDelta, false, slots * options.slotMinutes); } } hideDayOverlay(); rerenderEvents(); } }); } // hover effect when dragging events over top days var dayOverlay; function showDayOverlay(props) { if (!dayOverlay) { dayOverlay = $("