/*! * FullCalendar v1.4.5 * http://arshaw.com/fullcalendar/ * * Use fullcalendar.css for basic styling. * For event drag & drop, required jQuery UI draggable. * For event resizing, requires jQuery UI resizable. * * Copyright (c) 2009 Adam Shaw * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Date: Sun Feb 21 20:30:11 2010 -0800 * */ (function($) { var fc = $.fullCalendar = {}; var views = fc.views = {}; /* Defaults -----------------------------------------------------------------------------*/ var defaults = { // display defaultView: 'month', aspectRatio: 1.35, header: { left: 'title', center: '', right: 'today prev,next' }, weekends: true, // editing //editable: false, //disableDragging: false, //disableResizing: false, allDayDefault: true, // event ajax lazyFetching: true, startParam: 'start', endParam: 'end', // time formats titleFormat: { month: 'MMMM yyyy', week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}", day: 'dddd, MMM d, yyyy' }, columnFormat: { month: 'ddd', week: 'ddd M/d', day: 'dddd M/d' }, timeFormat: { // for event elements '': 'h(:mm)t' // default }, // locale isRTL: false, firstDay: 0, monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], buttonText: { prev: ' ◄ ', next: ' ► ', prevYear: ' << ', nextYear: ' >> ', today: 'today', month: 'month', week: 'week', day: 'day' }, // jquery-ui theming theme: false, buttonIcons: { prev: 'circle-triangle-w', next: 'circle-triangle-e' } }; // right-to-left defaults var rtlDefaults = { header: { left: 'next,prev today', center: '', right: 'title' }, buttonText: { prev: ' ► ', next: ' ◄ ', prevYear: ' >> ', nextYear: ' << ' }, buttonIcons: { prev: 'circle-triangle-e', next: 'circle-triangle-w' } }; // function for adding/overriding defaults var setDefaults = fc.setDefaults = function(d) { $.extend(true, defaults, d); } /* .fullCalendar jQuery function -----------------------------------------------------------------------------*/ $.fn.fullCalendar = function(options) { // method calling if (typeof options == 'string') { var args = Array.prototype.slice.call(arguments, 1), res; this.each(function() { var data = $.data(this, 'fullCalendar'); if (data) { var r = data[options].apply(this, args); if (res == undefined) { res = r; } } }); if (res != undefined) { return res; } return this; } // pluck the 'events' and 'eventSources' options var eventSources = options.eventSources || []; delete options.eventSources; if (options.events) { eventSources.push(options.events); delete options.events; } // first event source reserved for 'sticky' events eventSources.unshift([]); // initialize options options = $.extend(true, {}, defaults, (options.isRTL || options.isRTL==undefined && defaults.isRTL) ? rtlDefaults : {}, options ); var tm = options.theme ? 'ui' : 'fc'; // for making theme classes this.each(function() { /* Instance Initialization -----------------------------------------------------------------------------*/ // element var _element = this, element = $(_element).addClass('fc'), elementOuterWidth, content = $("
").prependTo(_element), suggestedViewHeight, resizeUID = 0, ignoreWindowResize = 0, date = new Date(), viewName, // the current view name (TODO: look into getting rid of) view, // the current view viewInstances = {}, absoluteViewElement; if (options.isRTL) { element.addClass('fc-rtl'); } if (options.theme) { element.addClass('ui-widget'); } if (options.year != undefined && options.year != date.getFullYear()) { date.setDate(1); date.setMonth(0); date.setFullYear(options.year); } if (options.month != undefined && options.month != date.getMonth()) { date.setDate(1); date.setMonth(options.month); } if (options.date != undefined) { date.setDate(options.date); } /* View Rendering -----------------------------------------------------------------------------*/ function changeView(v) { if (v != viewName) { ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached var oldView = view, newViewElement; if (oldView) { if (oldView.eventsChanged) { eventsDirty(); oldView.eventDirty = oldView.eventsChanged = false; } if (oldView.beforeHide) { oldView.beforeHide(); // called before changing min-height. if called after, scroll state is reset (in Opera) } setMinHeight(content, content.height()); oldView.element.hide(); }else{ setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated } content.css('overflow', 'hidden'); if (viewInstances[v]) { (view = viewInstances[v]).element.show(); }else{ view = viewInstances[v] = $.fullCalendar.views[v]( newViewElement = absoluteViewElement = $("
") .appendTo(content), options ); } if (header) { // update 'active' view button header.find('div.fc-button-' + viewName).removeClass(tm + '-state-active'); header.find('div.fc-button-' + v).addClass(tm + '-state-active'); } view.name = viewName = v; render(); // after height has been set, will make absoluteViewElement's position=relative, then set to null content.css('overflow', ''); if (oldView) { setMinHeight(content, 1); } if (!newViewElement && view.afterShow) { view.afterShow(); // called after setting min-height/overflow, so in final scroll state (for Opera) } ignoreWindowResize--; } } function render(inc) { if (elementVisible()) { ignoreWindowResize++; // because view.renderEvents might temporarily change the height before setSize is reached if (suggestedViewHeight == undefined) { calcSize(); } if (!view.start || inc || date < view.start || date >= view.end) { view.render(date, inc || 0); // responsible for clearing events setSize(true); if (!eventStart || !options.lazyFetching || view.visStart < eventStart || view.visEnd > eventEnd) { fetchAndRenderEvents(); }else{ view.renderEvents(events); // don't refetch } } else if (view.sizeDirty || view.eventsDirty || !options.lazyFetching) { view.clearEvents(); if (view.sizeDirty) { setSize(); } if (options.lazyFetching) { view.renderEvents(events); // don't refetch }else{ fetchAndRenderEvents(); } } elementOuterWidth = element.outerWidth(); view.sizeDirty = false; view.eventsDirty = false; if (header) { // update title text header.find('h2.fc-header-title').html(view.title); // enable/disable 'today' button var today = new Date(); if (today >= view.start && today < view.end) { header.find('div.fc-button-today').addClass(tm + '-state-disabled'); }else{ header.find('div.fc-button-today').removeClass(tm + '-state-disabled'); } } ignoreWindowResize--; view.trigger('viewDisplay', _element); } } function elementVisible() { return _element.offsetWidth !== 0; } function bodyVisible() { return $('body')[0].offsetWidth !== 0; } // called when any event objects have been added/removed/changed, rerenders function eventsChanged() { eventsDirty(); if (elementVisible()) { view.clearEvents(); view.renderEvents(events); view.eventsDirty = false; } } // marks other views' events as dirty function eventsDirty() { $.each(viewInstances, function() { this.eventsDirty = true; }); } // called when we know the element size has changed function sizeChanged() { sizesDirty(); if (elementVisible()) { calcSize(); setSize(); view.rerenderEvents(); view.sizeDirty = false; } } // marks other views' sizes as dirty function sizesDirty() { $.each(viewInstances, function() { this.sizeDirty = true; }); } /* Event Sources and Fetching -----------------------------------------------------------------------------*/ var events = [], eventStart, eventEnd; // Fetch from ALL sources. Clear 'events' array and populate function fetchEvents(callback) { events = []; eventStart = cloneDate(view.visStart); eventEnd = cloneDate(view.visEnd); var queued = eventSources.length, sourceDone = function() { if (--queued == 0) { if (callback) { callback(events); } } }, i=0; for (; i") .append($("") .append($("").append(buildSection(sections.left))) .append($("").append(buildSection(sections.center))) .append($("").append(buildSection(sections.right)))) .prependTo(element); } function buildSection(buttonStr) { if (buttonStr) { var tr = $(""); $.each(buttonStr.split(' '), function(i) { if (i > 0) { tr.append(""); } var prevButton; $.each(this.split(','), function(j, buttonName) { if (buttonName == 'title') { tr.append("

 

"); if (prevButton) { prevButton.addClass(tm + '-corner-right'); } prevButton = null; }else{ var buttonClick; if (publicMethods[buttonName]) { buttonClick = publicMethods[buttonName]; } else if (views[buttonName]) { buttonClick = function() { button.removeClass(tm + '-state-hover'); changeView(buttonName) }; } if (buttonClick) { if (prevButton) { prevButton.addClass(tm + '-no-right'); } var button, icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null, text = smartProperty(options.buttonText, buttonName); if (icon) { button = $("
" + "
"); } else if (text) { button = $(""); } if (button) { button .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-hover'); }, function() { button .removeClass(tm + '-state-hover') .removeClass(tm + '-state-down'); } ) .appendTo($("").appendTo(tr)); if (prevButton) { prevButton.addClass(tm + '-no-right'); }else{ button.addClass(tm + '-corner-left'); } prevButton = button; } } } }); if (prevButton) { prevButton.addClass(tm + '-corner-right'); } }); return $("").append(tr); } } /* Resizing -----------------------------------------------------------------------------*/ function calcSize() { if (options.contentHeight) { suggestedViewHeight = options.contentHeight; } else if (options.height) { suggestedViewHeight = options.height - (header ? header.height() : 0) - vsides(content[0]); } else { suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5)); } } function setSize(dateChanged) { ignoreWindowResize++; view.setHeight(suggestedViewHeight, dateChanged); if (absoluteViewElement) { absoluteViewElement.css('position', 'relative'); absoluteViewElement = null; } view.setWidth(content.width(), dateChanged); ignoreWindowResize--; } function windowResize() { if (!ignoreWindowResize) { if (view.start) { // view has already been rendered var uid = ++resizeUID; setTimeout(function() { // add a delay if (uid == resizeUID && !ignoreWindowResize && elementVisible()) { if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) { ignoreWindowResize++; // in case the windowResize callback changes the height sizeChanged(); view.trigger('windowResize', _element); ignoreWindowResize--; } } }, 200); }else{ // calendar must have been initialized in a 0x0 iframe that has just been resized lateRender(); } } }; $(window).resize(windowResize); // let's begin... changeView(options.defaultView); // needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize if (!bodyVisible()) { lateRender(); } // called when we know the calendar couldn't be rendered when it was initialized, // but we think it's ready now function lateRender() { setTimeout(function() { // IE7 needs this so dimensions are calculated correctly if (!view.start && bodyVisible()) { // !view.start makes sure this never happens more than once render(); } },0); } }); return this; }; /* Important Event Utilities -----------------------------------------------------------------------------*/ var fakeID = 0; function normalizeEvent(event, options) { event._id = event._id || (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 = null; } event._end = event.end ? cloneDate(event.end) : null; if (event.allDay == undefined) { event.allDay = options.allDayDefault; } if (event.className) { if (typeof event.className == 'string') { event.className = event.className.split(/\s+/); } }else{ event.className = []; } } // TODO: if there is no title or start date, return false to indicate an invalid event /* Grid-based Views: month, basicWeek, basicDay -----------------------------------------------------------------------------*/ setDefaults({ weekMode: 'fixed' }); views.month = function(element, options) { return new Grid(element, options, { render: function(date, delta) { if (delta) { addMonths(date, delta); date.setDate(1); } // start/end var start = this.start = cloneDate(date, true); start.setDate(1); this.end = addMonths(cloneDate(start), 1); // visStart/visEnd var visStart = this.visStart = cloneDate(start), visEnd = this.visEnd = cloneDate(this.end), nwe = options.weekends ? 0 : 1; if (nwe) { skipWeekend(visStart); skipWeekend(visEnd, -1, true); } addDays(visStart, -((visStart.getDay() - Math.max(options.firstDay, nwe) + 7) % 7)); addDays(visEnd, (7 - visEnd.getDay() + Math.max(options.firstDay, nwe)) % 7); // row count var rowCnt = Math.round((visEnd - visStart) / (DAY_MS * 7)); if (options.weekMode == 'fixed') { addDays(visEnd, (6 - rowCnt) * 7); rowCnt = 6; } // title this.title = formatDate( start, this.option('titleFormat'), options ); // render this.renderGrid( rowCnt, options.weekends ? 7 : 5, this.option('columnFormat'), true ); } }); } views.basicWeek = function(element, options) { return new Grid(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.renderGrid( 1, options.weekends ? 7 : 5, this.option('columnFormat'), false ); } }); }; views.basicDay = function(element, options) { return new Grid(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.renderGrid( 1, 1, this.option('columnFormat'), false ); } }); } // rendering bugs var tdHeightBug; function Grid(element, options, methods) { var tm, firstDay, nwe, // no weekends (int) rtl, dis, dit, // day index sign / translate viewWidth, viewHeight, rowCnt, colCnt, colWidth, thead, tbody, cachedEvents=[], segmentContainer, dayContentPositions = new HorizontalPositionCache(function(dayOfWeek) { return tbody.find('td:eq(' + ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt) + ') div div') }), // ... // initialize superclass view = $.extend(this, viewMethods, methods, { renderGrid: renderGrid, renderEvents: renderEvents, rerenderEvents: rerenderEvents, clearEvents: clearEvents, setHeight: setHeight, setWidth: setWidth, defaultEventEnd: function(event) { // calculates an end if event doesnt have one, mostly for resizing return cloneDate(event.start); } }); view.init(element, options); /* Grid Rendering -----------------------------------------------------------------------------*/ element.addClass('fc-grid'); if (element.disableSelection) { element.disableSelection(); } function renderGrid(r, c, colFormat, showNumbers) { rowCnt = r; 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; } var month = view.start.getMonth(), today = clearTime(new Date()), s, i, j, d = cloneDate(view.visStart); if (!tbody) { // first time, build all cells from scratch var table = $("
").appendTo(element); s = ""; for (i=0; i" + formatDate(d, colFormat, options) + ""; addDays(d, 1); if (nwe) { skipWeekend(d); } } thead = $(s + "").appendTo(table); s = ""; d = cloneDate(view.visStart); for (i=0; i"; for (j=0; j1 && d.getMonth() != month ? ' fc-other-month' : '') + (+d == +today ? ' fc-today '+tm+'-state-highlight' : ' fc-not-today') + "'>" + (showNumbers ? "
" + d.getDate() + "
" : '') + "
 
"; addDays(d, 1); if (nwe) { skipWeekend(d); } } s += ""; } tbody = $(s + "
").appendTo(table); tbody.find('td').click(dayClick); segmentContainer = $("
").appendTo(element); }else{ // NOT first time, reuse as many cells as possible clearEvents(); var prevRowCnt = tbody.find('tr').length; if (rowCnt < prevRowCnt) { tbody.find('tr:gt(' + (rowCnt-1) + ')').remove(); // remove extra rows } else if (rowCnt > prevRowCnt) { // needs to create new rows... s = ''; for (i=prevRowCnt; i"; for (j=0; j" + (showNumbers ? "
" : '') + "
 
" + ""; addDays(d, 1); if (nwe) { skipWeekend(d); } } s += ""; } tbody.append(s); } tbody.find('td.fc-new').removeClass('fc-new').click(dayClick); // re-label and re-class existing cells 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-other-month'); } } 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 (nwe) { skipWeekend(d); } }); if (rowCnt == 1) { // more changes likely (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); if (nwe) { skipWeekend(d); } }); // 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); if (nwe) { skipWeekend(d); } }); } } }; function dayClick(ev) { var n = parseInt(this.className.match(/fc\-day(\d+)/)[1]), date = addDays( cloneDate(view.visStart), Math.floor(n/colCnt) * 7 + n % colCnt ); view.trigger('dayClick', this, date, true, ev); } function setHeight(height) { viewHeight = height; var leftTDs = tbody.find('tr td:first-child'), tbodyHeight = viewHeight - thead.height(), rowHeight1, rowHeight2; if (options.weekMode == 'variable') { rowHeight1 = rowHeight2 = Math.floor(tbodyHeight / (rowCnt==1 ? 2 : 6)); }else{ rowHeight1 = Math.floor(tbodyHeight / rowCnt); rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1); } if (tdHeightBug == undefined) { // bug in firefox where cell height includes padding var tr = tbody.find('tr:first'), td = tr.find('td:first'); td.height(rowHeight1); tdHeightBug = rowHeight1 != td.height(); } if (tdHeightBug) { leftTDs.slice(0, -1).height(rowHeight1); leftTDs.slice(-1).height(rowHeight2); }else{ setOuterHeight(leftTDs.slice(0, -1), rowHeight1); setOuterHeight(leftTDs.slice(-1), rowHeight2); } } function setWidth(width) { viewWidth = width; dayContentPositions.clear(); setOuterWidth( thead.find('th').slice(0, -1), colWidth = Math.floor(viewWidth / colCnt) ); } /* Event Rendering -----------------------------------------------------------------------------*/ function renderEvents(events) { view.reportEvents(cachedEvents = events); renderSegs(compileSegs(events)); } function rerenderEvents(modifiedEventId) { clearEvents(); renderSegs(compileSegs(cachedEvents), modifiedEventId); } function clearEvents() { view._clearEvents(); // only clears the hashes segmentContainer.empty(); } function compileSegs(events) { var d1 = cloneDate(view.visStart), d2 = addDays(cloneDate(d1), colCnt), visEventsEnds = $.map(events, visEventEnd), i, row, j, level, k, seg, segs=[]; for (i=0; i" + "" + (!event.allDay && seg.isStart ? "" + htmlEscape(formatDates(event.start, event.end, view.option('timeFormat'), options)) + "" :'') + "" + htmlEscape(event.title) + "" + "" + ((event.editable || event.editable == undefined && options.editable) && !options.disableResizing && $.fn.resizable ? "
" : '') + "
"; seg.left = left; seg.outerWidth = right - left; } segmentContainer[0].innerHTML = html; // faster than html() eventElements = segmentContainer.children(); // retrieve elements, run through eventRender callback, bind handlers for (i=0; i div') // optimal selector? .height(top + levelHeight); } // calculate row tops for (rowI=0; rowI" + "" + ""; for (i=0; i" + formatDate(d, colFormat, options) + ""; addDays(d, dis); if (nwe) { skipWeekend(d, dis); } } s += ""; if (options.allDaySlot) { s += "" + "" + "" + "" + ""; } s+= "
  
" + options.allDayText + "" + "
 
 
"; head = $(s).appendTo(element); head.find('td').click(slotClick); // all-day event container daySegmentContainer = $("
").appendTo(head); // body d = zeroDate(); var maxd = addMinutes(cloneDate(d), maxMinute); addMinutes(d, minMinute); s = ""; for (i=0; d < maxd; i++) { minutes = d.getMinutes(); s += ""; addMinutes(d, options.slotMinutes); } s += "
" + ((!slotNormal || minutes==0) ? formatDate(d, options.axisFormat) : ' ') + "
 
"; body = $("
") .append(bodyContent = $("
") .append(bodyTable = $(s))) .appendTo(element); body.find('td').click(slotClick); // slot event container slotSegmentContainer = $("
").appendTo(bodyContent); // background stripes d = cloneDate(d0); s = "
" + ""; for (i=0; i
 
"; addDays(d, dis); if (nwe) { skipWeekend(d, dis); } } s += "
"; 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 (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); setOuterWidth(topTDs.slice(-2, -1), clientWidth - axisWidth - colWidth*(colCnt-1)); bg.css({ left: axisWidth, width: clientWidth - axisWidth }); } function slotClick(ev) { var col = Math.floor((ev.pageX - bg.offset().left) / colWidth), date = addDays(cloneDate(view.visStart), dit + dis*col), 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" + "" + "" + "" + htmlEscape(formatDates(event.start, event.end, view.option('timeFormat'))) + "" + "" + htmlEscape(event.title) + "" + "" + ((event.editable || event.editable == undefined && options.editable) && !options.disableResizing && $.fn.resizable ? "
=
" : '') + "
"; } slotSegmentContainer[0].innerHTML = html; // faster than html() eventElements = slotSegmentContainer.children(); // retrieve elements, run through eventRender callback, bind event handlers for (i=0; i= 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) )); } function day2col(dayOfWeek) { return ((dayOfWeek - Math.max(firstDay,nwe)+colCnt) % colCnt)*dis+dit; } } // 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