1 ?
+ ' colspan="' + colspan + '"' :
+ '') +
+ (otherAttrs ?
+ ' ' + otherAttrs :
+ '') +
+ '>' +
+ (isDateValid ?
+ // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
+ buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) :
+ // if not valid, display text, but no link
+ innerHtml) +
+ '
';
+ }
+
+ var DayHeader = /** @class */ (function (_super) {
+ __extends(DayHeader, _super);
+ function DayHeader(context, parentEl) {
+ var _this = _super.call(this, context) || this;
+ parentEl.innerHTML = ''; // because might be nbsp
+ parentEl.appendChild(_this.el = htmlToElement('
' +
+ '
' +
+ '' +
+ '
' +
+ '
'));
+ _this.thead = _this.el.querySelector('thead');
+ return _this;
+ }
+ DayHeader.prototype.destroy = function () {
+ removeElement(this.el);
+ };
+ DayHeader.prototype.render = function (props) {
+ var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays;
+ var parts = [];
+ if (props.renderIntroHtml) {
+ parts.push(props.renderIntroHtml());
+ }
+ var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') ||
+ computeFallbackHeaderFormat(datesRepDistinctDays, dates.length));
+ for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) {
+ var date = dates_1[_i];
+ parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context));
+ }
+ if (this.isRtl) {
+ parts.reverse();
+ }
+ this.thead.innerHTML = '
' +
+ (isResizableFromStart ?
+ '' :
+ '') +
+ (isResizableFromEnd ?
+ '' :
+ '') +
+ '';
+ };
+ // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
+ SimpleDayGridEventRenderer.prototype.computeEventTimeFormat = function () {
+ return {
+ hour: 'numeric',
+ minute: '2-digit',
+ omitZeroMinute: true,
+ meridiem: 'narrow'
+ };
+ };
+ SimpleDayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
+ return false; // TODO: somehow consider the originating DayGrid's column count
+ };
+ return SimpleDayGridEventRenderer;
+ }(core.FgEventRenderer));
+
+ /* Event-rendering methods for the DayGrid class
+ ----------------------------------------------------------------------------------------------------------------------*/
+ var DayGridEventRenderer = /** @class */ (function (_super) {
+ __extends(DayGridEventRenderer, _super);
+ function DayGridEventRenderer(dayGrid) {
+ var _this = _super.call(this, dayGrid.context) || this;
+ _this.dayGrid = dayGrid;
+ return _this;
+ }
+ // Renders the given foreground event segments onto the grid
+ DayGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
+ var rowStructs = this.rowStructs = this.renderSegRows(segs);
+ // append to each row's content skeleton
+ this.dayGrid.rowEls.forEach(function (rowNode, i) {
+ rowNode.querySelector('.fc-content-skeleton > table').appendChild(rowStructs[i].tbodyEl);
+ });
+ // removes the "more.." events popover
+ if (!mirrorInfo) {
+ this.dayGrid.removeSegPopover();
+ }
+ };
+ // Unrenders all currently rendered foreground event segments
+ DayGridEventRenderer.prototype.detachSegs = function () {
+ var rowStructs = this.rowStructs || [];
+ var rowStruct;
+ while ((rowStruct = rowStructs.pop())) {
+ core.removeElement(rowStruct.tbodyEl);
+ }
+ this.rowStructs = null;
+ };
+ // Uses the given events array to generate elements that should be appended to each row's content skeleton.
+ // Returns an array of rowStruct objects (see the bottom of `renderSegRow`).
+ // PRECONDITION: each segment shoud already have a rendered and assigned `.el`
+ DayGridEventRenderer.prototype.renderSegRows = function (segs) {
+ var rowStructs = [];
+ var segRows;
+ var row;
+ segRows = this.groupSegRows(segs); // group into nested arrays
+ // iterate each row of segment groupings
+ for (row = 0; row < segRows.length; row++) {
+ rowStructs.push(this.renderSegRow(row, segRows[row]));
+ }
+ return rowStructs;
+ };
+ // Given a row # and an array of segments all in the same row, render a element, a skeleton that contains
+ // the segments. Returns object with a bunch of internal data about how the render was calculated.
+ // NOTE: modifies rowSegs
+ DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) {
+ var dayGrid = this.dayGrid;
+ var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl;
+ var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels
+ var levelCnt = Math.max(1, segLevels.length); // ensure at least one level
+ var tbody = document.createElement('tbody');
+ var segMatrix = []; // lookup for which segments are rendered into which level+col cells
+ var cellMatrix = []; // lookup for all
elements of the level+col matrix
+ var loneCellMatrix = []; // lookup for
elements that only take up a single column
+ var i;
+ var levelSegs;
+ var col;
+ var tr;
+ var j;
+ var seg;
+ var td;
+ // populates empty cells from the current column (`col`) to `endCol`
+ function emptyCellsUntil(endCol) {
+ while (col < endCol) {
+ // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell
+ td = (loneCellMatrix[i - 1] || [])[col];
+ if (td) {
+ td.rowSpan = (td.rowSpan || 1) + 1;
+ }
+ else {
+ td = document.createElement('td');
+ tr.appendChild(td);
+ }
+ cellMatrix[i][col] = td;
+ loneCellMatrix[i][col] = td;
+ col++;
+ }
+ }
+ for (i = 0; i < levelCnt; i++) { // iterate through all levels
+ levelSegs = segLevels[i];
+ col = 0;
+ tr = document.createElement('tr');
+ segMatrix.push([]);
+ cellMatrix.push([]);
+ loneCellMatrix.push([]);
+ // levelCnt might be 1 even though there are no actual levels. protect against this.
+ // this single empty row is useful for styling.
+ if (levelSegs) {
+ for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level
+ seg = levelSegs[j];
+ var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
+ var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
+ emptyCellsUntil(leftCol);
+ // create a container that occupies or more columns. append the event element.
+ td = core.createElement('td', { className: 'fc-event-container' }, seg.el);
+ if (leftCol !== rightCol) {
+ td.colSpan = rightCol - leftCol + 1;
+ }
+ else { // a single-column segment
+ loneCellMatrix[i][col] = td;
+ }
+ while (col <= rightCol) {
+ cellMatrix[i][col] = td;
+ segMatrix[i][col] = seg;
+ col++;
+ }
+ tr.appendChild(td);
+ }
+ }
+ emptyCellsUntil(colCnt); // finish off the row
+ var introHtml = dayGrid.renderProps.renderIntroHtml();
+ if (introHtml) {
+ if (dayGrid.isRtl) {
+ core.appendToElement(tr, introHtml);
+ }
+ else {
+ core.prependToElement(tr, introHtml);
+ }
+ }
+ tbody.appendChild(tr);
+ }
+ return {
+ row: row,
+ tbodyEl: tbody,
+ cellMatrix: cellMatrix,
+ segMatrix: segMatrix,
+ segLevels: segLevels,
+ segs: rowSegs
+ };
+ };
+ // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels.
+ // NOTE: modifies segs
+ DayGridEventRenderer.prototype.buildSegLevels = function (segs) {
+ var _a = this.dayGrid, isRtl = _a.isRtl, colCnt = _a.colCnt;
+ var levels = [];
+ var i;
+ var seg;
+ var j;
+ // Give preference to elements with certain criteria, so they have
+ // a chance to be closer to the top.
+ segs = this.sortEventSegs(segs);
+ for (i = 0; i < segs.length; i++) {
+ seg = segs[i];
+ // loop through levels, starting with the topmost, until the segment doesn't collide with other segments
+ for (j = 0; j < levels.length; j++) {
+ if (!isDaySegCollision(seg, levels[j])) {
+ break;
+ }
+ }
+ // `j` now holds the desired subrow index
+ seg.level = j;
+ seg.leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; // for sorting only
+ seg.rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol // for sorting only
+ ;
+ (levels[j] || (levels[j] = [])).push(seg);
+ }
+ // order segments left-to-right. very important if calendar is RTL
+ for (j = 0; j < levels.length; j++) {
+ levels[j].sort(compareDaySegCols);
+ }
+ return levels;
+ };
+ // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row
+ DayGridEventRenderer.prototype.groupSegRows = function (segs) {
+ var segRows = [];
+ var i;
+ for (i = 0; i < this.dayGrid.rowCnt; i++) {
+ segRows.push([]);
+ }
+ for (i = 0; i < segs.length; i++) {
+ segRows[segs[i].row].push(segs[i]);
+ }
+ return segRows;
+ };
+ // Computes a default `displayEventEnd` value if one is not expliclty defined
+ DayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
+ return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day
+ };
+ return DayGridEventRenderer;
+ }(SimpleDayGridEventRenderer));
+ // Computes whether two segments' columns collide. They are assumed to be in the same row.
+ function isDaySegCollision(seg, otherSegs) {
+ var i;
+ var otherSeg;
+ for (i = 0; i < otherSegs.length; i++) {
+ otherSeg = otherSegs[i];
+ if (otherSeg.firstCol <= seg.lastCol &&
+ otherSeg.lastCol >= seg.firstCol) {
+ return true;
+ }
+ }
+ return false;
+ }
+ // A cmp function for determining the leftmost event
+ function compareDaySegCols(a, b) {
+ return a.leftCol - b.leftCol;
+ }
+
+ var DayGridMirrorRenderer = /** @class */ (function (_super) {
+ __extends(DayGridMirrorRenderer, _super);
+ function DayGridMirrorRenderer() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ DayGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
+ var sourceSeg = mirrorInfo.sourceSeg;
+ var rowStructs = this.rowStructs = this.renderSegRows(segs);
+ // inject each new event skeleton into each associated row
+ this.dayGrid.rowEls.forEach(function (rowNode, row) {
+ var skeletonEl = core.htmlToElement('
'); // will be absolutely positioned
+ var skeletonTopEl;
+ var skeletonTop;
+ // If there is an original segment, match the top position. Otherwise, put it at the row's top level
+ if (sourceSeg && sourceSeg.row === row) {
+ skeletonTopEl = sourceSeg.el;
+ }
+ else {
+ skeletonTopEl = rowNode.querySelector('.fc-content-skeleton tbody');
+ if (!skeletonTopEl) { // when no events
+ skeletonTopEl = rowNode.querySelector('.fc-content-skeleton table');
+ }
+ }
+ skeletonTop = skeletonTopEl.getBoundingClientRect().top -
+ rowNode.getBoundingClientRect().top; // the offsetParent origin
+ skeletonEl.style.top = skeletonTop + 'px';
+ skeletonEl.querySelector('table').appendChild(rowStructs[row].tbodyEl);
+ rowNode.appendChild(skeletonEl);
+ });
+ };
+ return DayGridMirrorRenderer;
+ }(DayGridEventRenderer));
+
+ var DayGridFillRenderer = /** @class */ (function (_super) {
+ __extends(DayGridFillRenderer, _super);
+ function DayGridFillRenderer(dayGrid) {
+ var _this = _super.call(this, dayGrid.context) || this;
+ _this.fillSegTag = 'td'; // override the default tag name
+ _this.dayGrid = dayGrid;
+ return _this;
+ }
+ DayGridFillRenderer.prototype.renderSegs = function (type, segs) {
+ // don't render timed background events
+ if (type === 'bgEvent') {
+ segs = segs.filter(function (seg) {
+ return seg.eventRange.def.allDay;
+ });
+ }
+ _super.prototype.renderSegs.call(this, type, segs);
+ };
+ DayGridFillRenderer.prototype.attachSegs = function (type, segs) {
+ var els = [];
+ var i;
+ var seg;
+ var skeletonEl;
+ for (i = 0; i < segs.length; i++) {
+ seg = segs[i];
+ skeletonEl = this.renderFillRow(type, seg);
+ this.dayGrid.rowEls[seg.row].appendChild(skeletonEl);
+ els.push(skeletonEl);
+ }
+ return els;
+ };
+ // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.
+ DayGridFillRenderer.prototype.renderFillRow = function (type, seg) {
+ var dayGrid = this.dayGrid;
+ var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl;
+ var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
+ var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
+ var startCol = leftCol;
+ var endCol = rightCol + 1;
+ var className;
+ var skeletonEl;
+ var trEl;
+ if (type === 'businessHours') {
+ className = 'bgevent';
+ }
+ else {
+ className = type.toLowerCase();
+ }
+ skeletonEl = core.htmlToElement('
' +
+ '
' +
+ '
');
+ trEl = skeletonEl.getElementsByTagName('tr')[0];
+ if (startCol > 0) {
+ core.appendToElement(trEl,
+ // will create (startCol + 1) td's
+ new Array(startCol + 1).join('
';
+ };
+ DayGrid.prototype.renderNumberCellsHtml = function (row) {
+ var htmls = [];
+ var col;
+ var date;
+ for (col = 0; col < this.colCnt; col++) {
+ date = this.props.cells[row][col].date;
+ htmls.push(this.renderNumberCellHtml(date));
+ }
+ if (this.isRtl) {
+ htmls.reverse();
+ }
+ return htmls.join('');
+ };
+ // Generates the HTML for the
s of the "number" row in the DayGrid's content skeleton.
+ // The number row will only exist if either day numbers or week numbers are turned on.
+ DayGrid.prototype.renderNumberCellHtml = function (date) {
+ var _a = this, view = _a.view, dateEnv = _a.dateEnv;
+ var html = '';
+ var isDateValid = core.rangeContainsMarker(this.props.dateProfile.activeRange, date); // TODO: called too frequently. cache somehow.
+ var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid;
+ var classes;
+ var weekCalcFirstDow;
+ if (!isDayNumberVisible && !this.renderProps.cellWeekNumbersVisible) {
+ // no numbers in day cell (week number must be along the side)
+ return '
'; // will create an empty space above events :(
+ }
+ classes = core.getDayClasses(date, this.props.dateProfile, this.context);
+ classes.unshift('fc-day-top');
+ if (this.renderProps.cellWeekNumbersVisible) {
+ weekCalcFirstDow = dateEnv.weekDow;
+ }
+ html += '
';
+ if (this.renderProps.cellWeekNumbersVisible && (date.getUTCDay() === weekCalcFirstDow)) {
+ html += core.buildGotoAnchorHtml(view, { date: date, type: 'week' }, { 'class': 'fc-week-number' }, dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML
+ );
+ }
+ if (isDayNumberVisible) {
+ html += core.buildGotoAnchorHtml(view, date, { 'class': 'fc-day-number' }, dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML
+ );
+ }
+ html += '
';
+ return html;
+ };
+ /* Sizing
+ ------------------------------------------------------------------------------------------------------------------*/
+ DayGrid.prototype.updateSize = function (isResize) {
+ var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
+ if (isResize ||
+ this.isCellSizesDirty ||
+ this.view.calendar.isEventsUpdated // hack
+ ) {
+ this.buildPositionCaches();
+ this.isCellSizesDirty = false;
+ }
+ fillRenderer.computeSizes(isResize);
+ eventRenderer.computeSizes(isResize);
+ mirrorRenderer.computeSizes(isResize);
+ fillRenderer.assignSizes(isResize);
+ eventRenderer.assignSizes(isResize);
+ mirrorRenderer.assignSizes(isResize);
+ };
+ DayGrid.prototype.buildPositionCaches = function () {
+ this.buildColPositions();
+ this.buildRowPositions();
+ };
+ DayGrid.prototype.buildColPositions = function () {
+ this.colPositions.build();
+ };
+ DayGrid.prototype.buildRowPositions = function () {
+ this.rowPositions.build();
+ this.rowPositions.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack
+ };
+ /* Hit System
+ ------------------------------------------------------------------------------------------------------------------*/
+ DayGrid.prototype.positionToHit = function (leftPosition, topPosition) {
+ var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions;
+ var col = colPositions.leftToIndex(leftPosition);
+ var row = rowPositions.topToIndex(topPosition);
+ if (row != null && col != null) {
+ return {
+ row: row,
+ col: col,
+ dateSpan: {
+ range: this.getCellRange(row, col),
+ allDay: true
+ },
+ dayEl: this.getCellEl(row, col),
+ relativeRect: {
+ left: colPositions.lefts[col],
+ right: colPositions.rights[col],
+ top: rowPositions.tops[row],
+ bottom: rowPositions.bottoms[row]
+ }
+ };
+ }
+ };
+ /* Cell System
+ ------------------------------------------------------------------------------------------------------------------*/
+ // FYI: the first column is the leftmost column, regardless of date
+ DayGrid.prototype.getCellEl = function (row, col) {
+ return this.cellEls[row * this.colCnt + col];
+ };
+ /* Event Drag Visualization
+ ------------------------------------------------------------------------------------------------------------------*/
+ DayGrid.prototype._renderEventDrag = function (state) {
+ if (state) {
+ this.eventRenderer.hideByHash(state.affectedInstances);
+ this.fillRenderer.renderSegs('highlight', state.segs);
+ }
+ };
+ DayGrid.prototype._unrenderEventDrag = function (state) {
+ if (state) {
+ this.eventRenderer.showByHash(state.affectedInstances);
+ this.fillRenderer.unrender('highlight');
+ }
+ };
+ /* Event Resize Visualization
+ ------------------------------------------------------------------------------------------------------------------*/
+ DayGrid.prototype._renderEventResize = function (state) {
+ if (state) {
+ this.eventRenderer.hideByHash(state.affectedInstances);
+ this.fillRenderer.renderSegs('highlight', state.segs);
+ this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
+ }
+ };
+ DayGrid.prototype._unrenderEventResize = function (state) {
+ if (state) {
+ this.eventRenderer.showByHash(state.affectedInstances);
+ this.fillRenderer.unrender('highlight');
+ this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
+ }
+ };
+ /* More+ Link Popover
+ ------------------------------------------------------------------------------------------------------------------*/
+ DayGrid.prototype.removeSegPopover = function () {
+ if (this.segPopover) {
+ this.segPopover.hide(); // in handler, will call segPopover's removeElement
+ }
+ };
+ // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
+ // `levelLimit` can be false (don't limit), a number, or true (should be computed).
+ DayGrid.prototype.limitRows = function (levelLimit) {
+ var rowStructs = this.eventRenderer.rowStructs || [];
+ var row; // row #
+ var rowLevelLimit;
+ for (row = 0; row < rowStructs.length; row++) {
+ this.unlimitRow(row);
+ if (!levelLimit) {
+ rowLevelLimit = false;
+ }
+ else if (typeof levelLimit === 'number') {
+ rowLevelLimit = levelLimit;
+ }
+ else {
+ rowLevelLimit = this.computeRowLevelLimit(row);
+ }
+ if (rowLevelLimit !== false) {
+ this.limitRow(row, rowLevelLimit);
+ }
+ }
+ };
+ // Computes the number of levels a row will accomodate without going outside its bounds.
+ // Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
+ // `row` is the row number.
+ DayGrid.prototype.computeRowLevelLimit = function (row) {
+ var rowEl = this.rowEls[row]; // the containing "fake" row div
+ var rowBottom = rowEl.getBoundingClientRect().bottom; // relative to viewport!
+ var trEls = core.findChildren(this.eventRenderer.rowStructs[row].tbodyEl);
+ var i;
+ var trEl;
+ // Reveal one level
at a time and stop when we find one out of bounds
+ for (i = 0; i < trEls.length; i++) {
+ trEl = trEls[i];
+ trEl.classList.remove('fc-limited'); // reset to original state (reveal)
+ if (trEl.getBoundingClientRect().bottom > rowBottom) {
+ return i;
+ }
+ }
+ return false; // should not limit at all
+ };
+ // Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
+ // `row` is the row number.
+ // `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
+ DayGrid.prototype.limitRow = function (row, levelLimit) {
+ var _this = this;
+ var _a = this, colCnt = _a.colCnt, isRtl = _a.isRtl;
+ var rowStruct = this.eventRenderer.rowStructs[row];
+ var moreNodes = []; // array of "more" links and
DOM nodes
+ var col = 0; // col #, left-to-right (not chronologically)
+ var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
+ var cellMatrix; // a matrix (by level, then column) of all
elements in the row
+ var limitedNodes; // array of temporarily hidden level
and segment
DOM nodes
+ var i;
+ var seg;
+ var segsBelow; // array of segment objects below `seg` in the current `col`
+ var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
+ var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
+ var td;
+ var rowSpan;
+ var segMoreNodes; // array of "more"
cells that will stand-in for the current seg's cell
+ var j;
+ var moreTd;
+ var moreWrap;
+ var moreLink;
+ // Iterates through empty level cells and places "more" links inside if need be
+ var emptyCellsUntil = function (endCol) {
+ while (col < endCol) {
+ segsBelow = _this.getCellSegs(row, col, levelLimit);
+ if (segsBelow.length) {
+ td = cellMatrix[levelLimit - 1][col];
+ moreLink = _this.renderMoreLink(row, col, segsBelow);
+ moreWrap = core.createElement('div', null, moreLink);
+ td.appendChild(moreWrap);
+ moreNodes.push(moreWrap);
+ }
+ col++;
+ }
+ };
+ if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
+ levelSegs = rowStruct.segLevels[levelLimit - 1];
+ cellMatrix = rowStruct.cellMatrix;
+ limitedNodes = core.findChildren(rowStruct.tbodyEl).slice(levelLimit); // get level
elements past the limit
+ limitedNodes.forEach(function (node) {
+ node.classList.add('fc-limited'); // hide elements and get a simple DOM-nodes array
+ });
+ // iterate though segments in the last allowable level
+ for (i = 0; i < levelSegs.length; i++) {
+ seg = levelSegs[i];
+ var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
+ var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
+ emptyCellsUntil(leftCol); // process empty cells before the segment
+ // determine *all* segments below `seg` that occupy the same columns
+ colSegsBelow = [];
+ totalSegsBelow = 0;
+ while (col <= rightCol) {
+ segsBelow = this.getCellSegs(row, col, levelLimit);
+ colSegsBelow.push(segsBelow);
+ totalSegsBelow += segsBelow.length;
+ col++;
+ }
+ if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
+ td = cellMatrix[levelLimit - 1][leftCol]; // the segment's parent cell
+ rowSpan = td.rowSpan || 1;
+ segMoreNodes = [];
+ // make a replacement
to avoid border confusion.
+ if (this.isRtl) {
+ options.right = core.computeRect(moreWrap).right + 1; // +1 to be over cell border
+ }
+ else {
+ options.left = core.computeRect(moreWrap).left - 1; // -1 to be over cell border
+ }
+ this.segPopover = new Popover(options);
+ this.segPopover.show();
+ calendar.releaseAfterSizingTriggers(); // hack for eventPositioned
+ };
+ // Given the events within an array of segment objects, reslice them to be in a single day
+ DayGrid.prototype.resliceDaySegs = function (segs, dayDate) {
+ var dayStart = dayDate;
+ var dayEnd = core.addDays(dayStart, 1);
+ var dayRange = { start: dayStart, end: dayEnd };
+ var newSegs = [];
+ for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
+ var seg = segs_1[_i];
+ var eventRange = seg.eventRange;
+ var origRange = eventRange.range;
+ var slicedRange = core.intersectRanges(origRange, dayRange);
+ if (slicedRange) {
+ newSegs.push(__assign({}, seg, { eventRange: {
+ def: eventRange.def,
+ ui: __assign({}, eventRange.ui, { durationEditable: false }),
+ instance: eventRange.instance,
+ range: slicedRange
+ }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() }));
+ }
+ }
+ return newSegs;
+ };
+ // Generates the text that should be inside a "more" link, given the number of events it represents
+ DayGrid.prototype.getMoreLinkText = function (num) {
+ var opt = this.opt('eventLimitText');
+ if (typeof opt === 'function') {
+ return opt(num);
+ }
+ else {
+ return '+' + num + ' ' + opt;
+ }
+ };
+ // Returns segments within a given cell.
+ // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
+ DayGrid.prototype.getCellSegs = function (row, col, startLevel) {
+ var segMatrix = this.eventRenderer.rowStructs[row].segMatrix;
+ var level = startLevel || 0;
+ var segs = [];
+ var seg;
+ while (level < segMatrix.length) {
+ seg = segMatrix[level][col];
+ if (seg) {
+ segs.push(seg);
+ }
+ level++;
+ }
+ return segs;
+ };
+ return DayGrid;
+ }(core.DateComponent));
+
+ var WEEK_NUM_FORMAT$1 = core.createFormatter({ week: 'numeric' });
+ /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
+ ----------------------------------------------------------------------------------------------------------------------*/
+ // It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.
+ // It is responsible for managing width/height.
+ var DayGridView = /** @class */ (function (_super) {
+ __extends(DayGridView, _super);
+ function DayGridView(context, viewSpec, dateProfileGenerator, parentEl) {
+ var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
+ /* Header Rendering
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Generates the HTML that will go before the day-of week header cells
+ _this.renderHeadIntroHtml = function () {
+ var theme = _this.theme;
+ if (_this.colWeekNumbersVisible) {
+ return '' +
+ '
';
+ }
+ return '';
+ };
+ /* Day Grid Rendering
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Generates the HTML that will go before content-skeleton cells that display the day/week numbers
+ _this.renderDayGridNumberIntroHtml = function (row, dayGrid) {
+ var dateEnv = _this.dateEnv;
+ var weekStart = dayGrid.props.cells[row][0].date;
+ if (_this.colWeekNumbersVisible) {
+ return '' +
+ '
' +
+ core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
+ _this, { date: weekStart, type: 'week', forceOff: dayGrid.colCnt === 1 }, dateEnv.format(weekStart, WEEK_NUM_FORMAT$1) // inner HTML
+ ) +
+ '
';
+ }
+ return '';
+ };
+ // Generates the HTML that goes before the day bg cells for each day-row
+ _this.renderDayGridBgIntroHtml = function () {
+ var theme = _this.theme;
+ if (_this.colWeekNumbersVisible) {
+ return '
';
+ }
+ return '';
+ };
+ // Generates the HTML that goes before every other type of row generated by DayGrid.
+ // Affects mirror-skeleton and highlight-skeleton rows.
+ _this.renderDayGridIntroHtml = function () {
+ if (_this.colWeekNumbersVisible) {
+ return '
';
+ }
+ return '';
+ };
+ _this.el.classList.add('fc-dayGrid-view');
+ _this.el.innerHTML = _this.renderSkeletonHtml();
+ _this.scroller = new core.ScrollComponent('hidden', // overflow x
+ 'auto' // overflow y
+ );
+ var dayGridContainerEl = _this.scroller.el;
+ _this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl);
+ dayGridContainerEl.classList.add('fc-day-grid-container');
+ var dayGridEl = core.createElement('div', { className: 'fc-day-grid' });
+ dayGridContainerEl.appendChild(dayGridEl);
+ var cellWeekNumbersVisible;
+ if (_this.opt('weekNumbers')) {
+ if (_this.opt('weekNumbersWithinDays')) {
+ cellWeekNumbersVisible = true;
+ _this.colWeekNumbersVisible = false;
+ }
+ else {
+ cellWeekNumbersVisible = false;
+ _this.colWeekNumbersVisible = true;
+ }
+ }
+ else {
+ _this.colWeekNumbersVisible = false;
+ cellWeekNumbersVisible = false;
+ }
+ _this.dayGrid = new DayGrid(_this.context, dayGridEl, {
+ renderNumberIntroHtml: _this.renderDayGridNumberIntroHtml,
+ renderBgIntroHtml: _this.renderDayGridBgIntroHtml,
+ renderIntroHtml: _this.renderDayGridIntroHtml,
+ colWeekNumbersVisible: _this.colWeekNumbersVisible,
+ cellWeekNumbersVisible: cellWeekNumbersVisible
+ });
+ return _this;
+ }
+ DayGridView.prototype.destroy = function () {
+ _super.prototype.destroy.call(this);
+ this.dayGrid.destroy();
+ this.scroller.destroy();
+ };
+ // Builds the HTML skeleton for the view.
+ // The day-grid component will render inside of a container defined by this HTML.
+ DayGridView.prototype.renderSkeletonHtml = function () {
+ var theme = this.theme;
+ return '' +
+ '
' +
+ (this.opt('columnHeader') ?
+ '' +
+ '
' +
+ '
' +
+ '
' +
+ '' :
+ '') +
+ '' +
+ '
' +
+ '
' +
+ '
' +
+ '' +
+ '
';
+ };
+ // Generates an HTML attribute string for setting the width of the week number column, if it is known
+ DayGridView.prototype.weekNumberStyleAttr = function () {
+ if (this.weekNumberWidth != null) {
+ return 'style="width:' + this.weekNumberWidth + 'px"';
+ }
+ return '';
+ };
+ // Determines whether each row should have a constant height
+ DayGridView.prototype.hasRigidRows = function () {
+ var eventLimit = this.opt('eventLimit');
+ return eventLimit && typeof eventLimit !== 'number';
+ };
+ /* Dimensions
+ ------------------------------------------------------------------------------------------------------------------*/
+ DayGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
+ _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first
+ this.dayGrid.updateSize(isResize);
+ };
+ // Refreshes the horizontal dimensions of the view
+ DayGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
+ var dayGrid = this.dayGrid;
+ var eventLimit = this.opt('eventLimit');
+ var headRowEl = this.header ? this.header.el : null; // HACK
+ var scrollerHeight;
+ var scrollbarWidths;
+ // hack to give the view some height prior to dayGrid's columns being rendered
+ // TODO: separate setting height from scroller VS dayGrid.
+ if (!dayGrid.rowEls) {
+ if (!isAuto) {
+ scrollerHeight = this.computeScrollerHeight(viewHeight);
+ this.scroller.setHeight(scrollerHeight);
+ }
+ return;
+ }
+ if (this.colWeekNumbersVisible) {
+ // Make sure all week number cells running down the side have the same width.
+ this.weekNumberWidth = core.matchCellWidths(core.findElements(this.el, '.fc-week-number'));
+ }
+ // reset all heights to be natural
+ this.scroller.clear();
+ if (headRowEl) {
+ core.uncompensateScroll(headRowEl);
+ }
+ dayGrid.removeSegPopover(); // kill the "more" popover if displayed
+ // is the event limit a constant level number?
+ if (eventLimit && typeof eventLimit === 'number') {
+ dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
+ }
+ // distribute the height to the rows
+ // (viewHeight is a "recommended" value if isAuto)
+ scrollerHeight = this.computeScrollerHeight(viewHeight);
+ this.setGridHeight(scrollerHeight, isAuto);
+ // is the event limit dynamically calculated?
+ if (eventLimit && typeof eventLimit !== 'number') {
+ dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
+ }
+ if (!isAuto) { // should we force dimensions of the scroll container?
+ this.scroller.setHeight(scrollerHeight);
+ scrollbarWidths = this.scroller.getScrollbarWidths();
+ if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
+ if (headRowEl) {
+ core.compensateScroll(headRowEl, scrollbarWidths);
+ }
+ // doing the scrollbar compensation might have created text overflow which created more height. redo
+ scrollerHeight = this.computeScrollerHeight(viewHeight);
+ this.scroller.setHeight(scrollerHeight);
+ }
+ // guarantees the same scrollbar widths
+ this.scroller.lockOverflow(scrollbarWidths);
+ }
+ };
+ // given a desired total height of the view, returns what the height of the scroller should be
+ DayGridView.prototype.computeScrollerHeight = function (viewHeight) {
+ return viewHeight -
+ core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
+ };
+ // Sets the height of just the DayGrid component in this view
+ DayGridView.prototype.setGridHeight = function (height, isAuto) {
+ if (this.opt('monthMode')) {
+ // if auto, make the height of each row the height that it would be if there were 6 weeks
+ if (isAuto) {
+ height *= this.dayGrid.rowCnt / 6;
+ }
+ core.distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows
+ }
+ else {
+ if (isAuto) {
+ core.undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding
+ }
+ else {
+ core.distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows
+ }
+ }
+ };
+ /* Scroll
+ ------------------------------------------------------------------------------------------------------------------*/
+ DayGridView.prototype.computeDateScroll = function (timeMs) {
+ return { top: 0 };
+ };
+ DayGridView.prototype.queryDateScroll = function () {
+ return { top: this.scroller.getScrollTop() };
+ };
+ DayGridView.prototype.applyDateScroll = function (scroll) {
+ if (scroll.top !== undefined) {
+ this.scroller.setScrollTop(scroll.top);
+ }
+ };
+ return DayGridView;
+ }(core.View));
+ DayGridView.prototype.dateProfileGeneratorClass = DayGridDateProfileGenerator;
+
+ var SimpleDayGrid = /** @class */ (function (_super) {
+ __extends(SimpleDayGrid, _super);
+ function SimpleDayGrid(context, dayGrid) {
+ var _this = _super.call(this, context, dayGrid.el) || this;
+ _this.slicer = new DayGridSlicer();
+ _this.dayGrid = dayGrid;
+ context.calendar.registerInteractiveComponent(_this, { el: _this.dayGrid.el });
+ return _this;
+ }
+ SimpleDayGrid.prototype.destroy = function () {
+ _super.prototype.destroy.call(this);
+ this.calendar.unregisterInteractiveComponent(this);
+ };
+ SimpleDayGrid.prototype.render = function (props) {
+ var dayGrid = this.dayGrid;
+ var dateProfile = props.dateProfile, dayTable = props.dayTable;
+ dayGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, props.nextDayThreshold, dayGrid, dayTable), { dateProfile: dateProfile, cells: dayTable.cells, isRigid: props.isRigid }));
+ };
+ SimpleDayGrid.prototype.buildPositionCaches = function () {
+ this.dayGrid.buildPositionCaches();
+ };
+ SimpleDayGrid.prototype.queryHit = function (positionLeft, positionTop) {
+ var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop);
+ if (rawHit) {
+ return {
+ component: this.dayGrid,
+ dateSpan: rawHit.dateSpan,
+ dayEl: rawHit.dayEl,
+ rect: {
+ left: rawHit.relativeRect.left,
+ right: rawHit.relativeRect.right,
+ top: rawHit.relativeRect.top,
+ bottom: rawHit.relativeRect.bottom
+ },
+ layer: 0
+ };
+ }
+ };
+ return SimpleDayGrid;
+ }(core.DateComponent));
+ var DayGridSlicer = /** @class */ (function (_super) {
+ __extends(DayGridSlicer, _super);
+ function DayGridSlicer() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ DayGridSlicer.prototype.sliceRange = function (dateRange, dayTable) {
+ return dayTable.sliceRange(dateRange);
+ };
+ return DayGridSlicer;
+ }(core.Slicer));
+
+ var DayGridView$1 = /** @class */ (function (_super) {
+ __extends(DayGridView, _super);
+ function DayGridView(_context, viewSpec, dateProfileGenerator, parentEl) {
+ var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this;
+ _this.buildDayTable = core.memoize(buildDayTable);
+ if (_this.opt('columnHeader')) {
+ _this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container'));
+ }
+ _this.simpleDayGrid = new SimpleDayGrid(_this.context, _this.dayGrid);
+ return _this;
+ }
+ DayGridView.prototype.destroy = function () {
+ _super.prototype.destroy.call(this);
+ if (this.header) {
+ this.header.destroy();
+ }
+ this.simpleDayGrid.destroy();
+ };
+ DayGridView.prototype.render = function (props) {
+ _super.prototype.render.call(this, props);
+ var dateProfile = this.props.dateProfile;
+ var dayTable = this.dayTable =
+ this.buildDayTable(dateProfile, this.dateProfileGenerator);
+ if (this.header) {
+ this.header.receiveProps({
+ dateProfile: dateProfile,
+ dates: dayTable.headerDates,
+ datesRepDistinctDays: dayTable.rowCnt === 1,
+ renderIntroHtml: this.renderHeadIntroHtml
+ });
+ }
+ this.simpleDayGrid.receiveProps({
+ dateProfile: dateProfile,
+ dayTable: dayTable,
+ businessHours: props.businessHours,
+ dateSelection: props.dateSelection,
+ eventStore: props.eventStore,
+ eventUiBases: props.eventUiBases,
+ eventSelection: props.eventSelection,
+ eventDrag: props.eventDrag,
+ eventResize: props.eventResize,
+ isRigid: this.hasRigidRows(),
+ nextDayThreshold: this.nextDayThreshold
+ });
+ };
+ return DayGridView;
+ }(DayGridView));
+ function buildDayTable(dateProfile, dateProfileGenerator) {
+ var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator);
+ return new core.DayTable(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
+ }
+
+ var main = core.createPlugin({
+ defaultView: 'dayGridMonth',
+ views: {
+ dayGrid: DayGridView$1,
+ dayGridDay: {
+ type: 'dayGrid',
+ duration: { days: 1 }
+ },
+ dayGridWeek: {
+ type: 'dayGrid',
+ duration: { weeks: 1 }
+ },
+ dayGridMonth: {
+ type: 'dayGrid',
+ duration: { months: 1 },
+ monthMode: true,
+ fixedWeekCount: true
+ }
+ }
+ });
+
+ exports.AbstractDayGridView = DayGridView;
+ exports.DayBgRow = DayBgRow;
+ exports.DayGrid = DayGrid;
+ exports.DayGridSlicer = DayGridSlicer;
+ exports.DayGridView = DayGridView$1;
+ exports.SimpleDayGrid = SimpleDayGrid;
+ exports.buildBasicDayTable = buildDayTable;
+ exports.default = main;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
diff --git a/vendor/fullcalendar/daygrid/main.min.css b/vendor/fullcalendar/daygrid/main.min.css
new file mode 100644
index 00000000..2848b375
--- /dev/null
+++ b/vendor/fullcalendar/daygrid/main.min.css
@@ -0,0 +1,5 @@
+/*!
+FullCalendar Day Grid Plugin v4.1.0
+Docs & License: https://fullcalendar.io/
+(c) 2019 Adam Shaw
+*/.fc-dayGridDay-view .fc-content-skeleton,.fc-dayGridWeek-view .fc-content-skeleton{padding-bottom:1em}.fc-dayGrid-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid{overflow:hidden}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-day-top.fc-other-month{opacity:.3}.fc-dayGrid-view .fc-day-number,.fc-dayGrid-view .fc-week-number{padding:2px}.fc-dayGrid-view th.fc-day-number,.fc-dayGrid-view th.fc-week-number{padding:0 2px}.fc-ltr .fc-dayGrid-view .fc-day-top .fc-day-number{float:right}.fc-rtl .fc-dayGrid-view .fc-day-top .fc-day-number{float:left}.fc-ltr .fc-dayGrid-view .fc-day-top .fc-week-number{float:left;border-radius:0 0 3px}.fc-rtl .fc-dayGrid-view .fc-day-top .fc-week-number{float:right;border-radius:0 0 0 3px}.fc-dayGrid-view .fc-day-top .fc-week-number{min-width:1.5em;text-align:center;background-color:#f2f2f2;color:grey}.fc-dayGrid-view td.fc-week-number{text-align:center}.fc-dayGrid-view td.fc-week-number>*{display:inline-block;min-width:1.25em}
\ No newline at end of file
diff --git a/vendor/fullcalendar/daygrid/main.min.js b/vendor/fullcalendar/daygrid/main.min.js
new file mode 100644
index 00000000..056cfc0b
--- /dev/null
+++ b/vendor/fullcalendar/daygrid/main.min.js
@@ -0,0 +1,20 @@
+/*!
+FullCalendar Day Grid Plugin v4.1.0
+Docs & License: https://fullcalendar.io/
+(c) 2019 Adam Shaw
+*/
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):(e=e||self,t(e.FullCalendarDayGrid={},e.FullCalendar))}(this,function(e,t){"use strict";function r(e,t){function r(){this.constructor=e}l(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}function n(e,t){var r,n;for(r=0;r=e.firstCol)return!0;return!1}function i(e,t){return e.leftCol-t.leftCol}function o(e,r,n,i){var o=n.dateEnv,s=n.theme,l=t.rangeContainsMarker(r.activeRange,e),a=t.getDayClasses(e,r,n);return a.unshift("fc-day",s.getClass("widgetContent")),'
"}function s(e,r){var n=new t.DaySeries(e.renderRange,r);return new t.DayTable(n,/year|month|week/.test(e.currentRangeUnit))}/*! *****************************************************************************
+ Copyright (c) Microsoft Corporation. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of the
+ License at http://www.apache.org/licenses/LICENSE-2.0
+
+ THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
+ WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+ MERCHANTABLITY OR NON-INFRINGEMENT.
+
+ See the Apache Version 2.0 License for specific language governing permissions
+ and limitations under the License.
+ ***************************************************************************** */
+var l=function(e,t){return(l=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},a=function(){return a=Object.assign||function(e){for(var t,r=1,n=arguments.length;r'+t.htmlEscape(n)+""),i=''+(t.htmlEscape(l.title||"")||" ")+"",'
';
+ };
+ // called by ListEventRenderer
+ ListView.prototype.renderSegList = function (allSegs) {
+ var segsByDay = this.groupSegsByDay(allSegs); // sparse array
+ var dayIndex;
+ var daySegs;
+ var i;
+ var tableEl = core.htmlToElement('
');
+ var tbodyEl = tableEl.querySelector('tbody');
+ for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) {
+ daySegs = segsByDay[dayIndex];
+ if (daySegs) { // sparse array, so might be undefined
+ // append a day header
+ tbodyEl.appendChild(this.buildDayHeaderRow(this.dayDates[dayIndex]));
+ daySegs = this.eventRenderer.sortEventSegs(daySegs);
+ for (i = 0; i < daySegs.length; i++) {
+ tbodyEl.appendChild(daySegs[i].el); // append event row
+ }
+ }
+ }
+ this.contentEl.innerHTML = '';
+ this.contentEl.appendChild(tableEl);
+ };
+ // Returns a sparse array of arrays, segs grouped by their dayIndex
+ ListView.prototype.groupSegsByDay = function (segs) {
+ var segsByDay = []; // sparse array
+ var i;
+ var seg;
+ for (i = 0; i < segs.length; i++) {
+ seg = segs[i];
+ (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
+ .push(seg);
+ }
+ return segsByDay;
+ };
+ // generates the HTML for the day headers that live amongst the event rows
+ ListView.prototype.buildDayHeaderRow = function (dayDate) {
+ var dateEnv = this.dateEnv;
+ var mainFormat = core.createFormatter(this.opt('listDayFormat')); // TODO: cache
+ var altFormat = core.createFormatter(this.opt('listDayAltFormat')); // TODO: cache
+ return core.createElement('tr', {
+ className: 'fc-list-heading',
+ 'data-date': dateEnv.formatIso(dayDate, { omitTime: true })
+ }, '
' +
+ /* TODO: write CSS for this
+ (isResizableFromStart ?
+ '' :
+ ''
+ ) +
+ */
+ (isResizableFromEnd ?
+ '' :
+ '') +
+ '';
+ };
+ // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
+ // Assumed the segs are already ordered.
+ // NOTE: Also reorders the given array by date!
+ TimeGridEventRenderer.prototype.computeSegHorizontals = function (segs) {
+ var levels;
+ var level0;
+ var i;
+ levels = buildSlotSegLevels(segs);
+ computeForwardSlotSegs(levels);
+ if ((level0 = levels[0])) {
+ for (i = 0; i < level0.length; i++) {
+ computeSlotSegPressures(level0[i]);
+ }
+ for (i = 0; i < level0.length; i++) {
+ this.computeSegForwardBack(level0[i], 0, 0);
+ }
+ }
+ };
+ // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
+ // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
+ // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
+ //
+ // The segment might be part of a "series", which means consecutive segments with the same pressure
+ // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
+ // segments behind this one in the current series, and `seriesBackwardCoord` is the starting
+ // coordinate of the first segment in the series.
+ TimeGridEventRenderer.prototype.computeSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) {
+ var forwardSegs = seg.forwardSegs;
+ var i;
+ if (seg.forwardCoord === undefined) { // not already computed
+ if (!forwardSegs.length) {
+ // if there are no forward segments, this segment should butt up against the edge
+ seg.forwardCoord = 1;
+ }
+ else {
+ // sort highest pressure first
+ this.sortForwardSegs(forwardSegs);
+ // this segment's forwardCoord will be calculated from the backwardCoord of the
+ // highest-pressure forward segment.
+ this.computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
+ seg.forwardCoord = forwardSegs[0].backwardCoord;
+ }
+ // calculate the backwardCoord from the forwardCoord. consider the series
+ seg.backwardCoord = seg.forwardCoord -
+ (seg.forwardCoord - seriesBackwardCoord) / // available width for series
+ (seriesBackwardPressure + 1); // # of segments in the series
+ // use this segment's coordinates to computed the coordinates of the less-pressurized
+ // forward segments
+ for (i = 0; i < forwardSegs.length; i++) {
+ this.computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
+ }
+ }
+ };
+ TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) {
+ var objs = forwardSegs.map(buildTimeGridSegCompareObj);
+ var specs = [
+ // put higher-pressure first
+ { field: 'forwardPressure', order: -1 },
+ // put segments that are closer to initial edge first (and favor ones with no coords yet)
+ { field: 'backwardCoord', order: 1 }
+ ].concat(this.context.view.eventOrderSpecs);
+ objs.sort(function (obj0, obj1) {
+ return core.compareByFieldSpecs(obj0, obj1, specs);
+ });
+ return objs.map(function (c) {
+ return c._seg;
+ });
+ };
+ // Given foreground event segments that have already had their position coordinates computed,
+ // assigns position-related CSS values to their elements.
+ TimeGridEventRenderer.prototype.assignSegCss = function (segs) {
+ for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
+ var seg = segs_1[_i];
+ core.applyStyle(seg.el, this.generateSegCss(seg));
+ if (seg.level > 0) {
+ seg.el.classList.add('fc-time-grid-event-inset');
+ }
+ // if the event is short that the title will be cut off,
+ // attach a className that condenses the title into the time area.
+ if (seg.eventRange.def.title && seg.bottom - seg.top < 30) {
+ seg.el.classList.add('fc-short'); // TODO: "condensed" is a better name
+ }
+ }
+ };
+ // Generates an object with CSS properties/values that should be applied to an event segment element.
+ // Contains important positioning-related properties that should be applied to any event element, customized or not.
+ TimeGridEventRenderer.prototype.generateSegCss = function (seg) {
+ var shouldOverlap = this.context.options.slotEventOverlap;
+ var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
+ var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
+ var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first
+ var isRtl = this.timeGrid.isRtl;
+ var left; // amount of space from left edge, a fraction of the total width
+ var right; // amount of space from right edge, a fraction of the total width
+ if (shouldOverlap) {
+ // double the width, but don't go beyond the maximum forward coordinate (1.0)
+ forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
+ }
+ if (isRtl) {
+ left = 1 - forwardCoord;
+ right = backwardCoord;
+ }
+ else {
+ left = backwardCoord;
+ right = 1 - forwardCoord;
+ }
+ props.zIndex = seg.level + 1; // convert from 0-base to 1-based
+ props.left = left * 100 + '%';
+ props.right = right * 100 + '%';
+ if (shouldOverlap && seg.forwardPressure) {
+ // add padding to the edge so that forward stacked events don't cover the resizer's icon
+ props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
+ }
+ return props;
+ };
+ return TimeGridEventRenderer;
+ }(core.FgEventRenderer));
+ // Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is
+ // left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date.
+ function buildSlotSegLevels(segs) {
+ var levels = [];
+ var i;
+ var seg;
+ var j;
+ for (i = 0; i < segs.length; i++) {
+ seg = segs[i];
+ // go through all the levels and stop on the first level where there are no collisions
+ for (j = 0; j < levels.length; j++) {
+ if (!computeSlotSegCollisions(seg, levels[j]).length) {
+ break;
+ }
+ }
+ seg.level = j;
+ (levels[j] || (levels[j] = [])).push(seg);
+ }
+ return levels;
+ }
+ // For every segment, figure out the other segments that are in subsequent
+ // levels that also occupy the same vertical space. Accumulate in seg.forwardSegs
+ function computeForwardSlotSegs(levels) {
+ var i;
+ var level;
+ var j;
+ var seg;
+ var k;
+ for (i = 0; i < levels.length; i++) {
+ level = levels[i];
+ for (j = 0; j < level.length; j++) {
+ seg = level[j];
+ seg.forwardSegs = [];
+ for (k = i + 1; k < levels.length; k++) {
+ computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
+ }
+ }
+ }
+ }
+ // Figure out which path forward (via seg.forwardSegs) results in the longest path until
+ // the furthest edge is reached. The number of segments in this path will be seg.forwardPressure
+ function computeSlotSegPressures(seg) {
+ var forwardSegs = seg.forwardSegs;
+ var forwardPressure = 0;
+ var i;
+ var forwardSeg;
+ if (seg.forwardPressure === undefined) { // not already computed
+ for (i = 0; i < forwardSegs.length; i++) {
+ forwardSeg = forwardSegs[i];
+ // figure out the child's maximum forward path
+ computeSlotSegPressures(forwardSeg);
+ // either use the existing maximum, or use the child's forward pressure
+ // plus one (for the forwardSeg itself)
+ forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure);
+ }
+ seg.forwardPressure = forwardPressure;
+ }
+ }
+ // Find all the segments in `otherSegs` that vertically collide with `seg`.
+ // Append into an optionally-supplied `results` array and return.
+ function computeSlotSegCollisions(seg, otherSegs, results) {
+ if (results === void 0) { results = []; }
+ for (var i = 0; i < otherSegs.length; i++) {
+ if (isSlotSegCollision(seg, otherSegs[i])) {
+ results.push(otherSegs[i]);
+ }
+ }
+ return results;
+ }
+ // Do these segments occupy the same vertical space?
+ function isSlotSegCollision(seg1, seg2) {
+ return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
+ }
+ function buildTimeGridSegCompareObj(seg) {
+ var obj = core.buildSegCompareObj(seg);
+ obj.forwardPressure = seg.forwardPressure;
+ obj.backwardCoord = seg.backwardCoord;
+ return obj;
+ }
+
+ var TimeGridMirrorRenderer = /** @class */ (function (_super) {
+ __extends(TimeGridMirrorRenderer, _super);
+ function TimeGridMirrorRenderer() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ TimeGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
+ this.segsByCol = this.timeGrid.groupSegsByCol(segs);
+ this.timeGrid.attachSegsByCol(this.segsByCol, this.timeGrid.mirrorContainerEls);
+ this.sourceSeg = mirrorInfo.sourceSeg;
+ };
+ TimeGridMirrorRenderer.prototype.generateSegCss = function (seg) {
+ var props = _super.prototype.generateSegCss.call(this, seg);
+ var sourceSeg = this.sourceSeg;
+ if (sourceSeg && sourceSeg.col === seg.col) {
+ var sourceSegProps = _super.prototype.generateSegCss.call(this, sourceSeg);
+ props.left = sourceSegProps.left;
+ props.right = sourceSegProps.right;
+ props.marginLeft = sourceSegProps.marginLeft;
+ props.marginRight = sourceSegProps.marginRight;
+ }
+ return props;
+ };
+ return TimeGridMirrorRenderer;
+ }(TimeGridEventRenderer));
+
+ var TimeGridFillRenderer = /** @class */ (function (_super) {
+ __extends(TimeGridFillRenderer, _super);
+ function TimeGridFillRenderer(timeGrid) {
+ var _this = _super.call(this, timeGrid.context) || this;
+ _this.timeGrid = timeGrid;
+ return _this;
+ }
+ TimeGridFillRenderer.prototype.attachSegs = function (type, segs) {
+ var timeGrid = this.timeGrid;
+ var containerEls;
+ // TODO: more efficient lookup
+ if (type === 'bgEvent') {
+ containerEls = timeGrid.bgContainerEls;
+ }
+ else if (type === 'businessHours') {
+ containerEls = timeGrid.businessContainerEls;
+ }
+ else if (type === 'highlight') {
+ containerEls = timeGrid.highlightContainerEls;
+ }
+ timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls);
+ return segs.map(function (seg) {
+ return seg.el;
+ });
+ };
+ TimeGridFillRenderer.prototype.computeSegSizes = function (segs) {
+ this.timeGrid.computeSegVerticals(segs);
+ };
+ TimeGridFillRenderer.prototype.assignSegSizes = function (segs) {
+ this.timeGrid.assignSegVerticals(segs);
+ };
+ return TimeGridFillRenderer;
+ }(core.FillRenderer));
+
+ /* A component that renders one or more columns of vertical time slots
+ ----------------------------------------------------------------------------------------------------------------------*/
+ // potential nice values for the slot-duration and interval-duration
+ // from largest to smallest
+ var AGENDA_STOCK_SUB_DURATIONS = [
+ { hours: 1 },
+ { minutes: 30 },
+ { minutes: 15 },
+ { seconds: 30 },
+ { seconds: 15 }
+ ];
+ var TimeGrid = /** @class */ (function (_super) {
+ __extends(TimeGrid, _super);
+ function TimeGrid(context, el, renderProps) {
+ var _this = _super.call(this, context, el) || this;
+ _this.isSlatSizesDirty = false;
+ _this.isColSizesDirty = false;
+ _this.renderSlats = core.memoizeRendering(_this._renderSlats);
+ var eventRenderer = _this.eventRenderer = new TimeGridEventRenderer(_this);
+ var fillRenderer = _this.fillRenderer = new TimeGridFillRenderer(_this);
+ _this.mirrorRenderer = new TimeGridMirrorRenderer(_this);
+ var renderColumns = _this.renderColumns = core.memoizeRendering(_this._renderColumns, _this._unrenderColumns);
+ _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderColumns]);
+ _this.renderDateSelection = core.memoizeRendering(_this._renderDateSelection, _this._unrenderDateSelection, [renderColumns]);
+ _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderColumns]);
+ _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderColumns]);
+ _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
+ _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderColumns]);
+ _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderColumns]);
+ _this.processOptions();
+ el.innerHTML =
+ '' +
+ '' +
+ '';
+ _this.rootBgContainerEl = el.querySelector('.fc-bg');
+ _this.slatContainerEl = el.querySelector('.fc-slats');
+ _this.bottomRuleEl = el.querySelector('.fc-divider');
+ _this.renderProps = renderProps;
+ return _this;
+ }
+ /* Options
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Parses various options into properties of this object
+ TimeGrid.prototype.processOptions = function () {
+ var slotDuration = this.opt('slotDuration');
+ var snapDuration = this.opt('snapDuration');
+ var snapsPerSlot;
+ var input;
+ slotDuration = core.createDuration(slotDuration);
+ snapDuration = snapDuration ? core.createDuration(snapDuration) : slotDuration;
+ snapsPerSlot = core.wholeDivideDurations(slotDuration, snapDuration);
+ if (snapsPerSlot === null) {
+ snapDuration = slotDuration;
+ snapsPerSlot = 1;
+ // TODO: say warning?
+ }
+ this.slotDuration = slotDuration;
+ this.snapDuration = snapDuration;
+ this.snapsPerSlot = snapsPerSlot;
+ // might be an array value (for TimelineView).
+ // if so, getting the most granular entry (the last one probably).
+ input = this.opt('slotLabelFormat');
+ if (Array.isArray(input)) {
+ input = input[input.length - 1];
+ }
+ this.labelFormat = core.createFormatter(input || {
+ hour: 'numeric',
+ minute: '2-digit',
+ omitZeroMinute: true,
+ meridiem: 'short'
+ });
+ input = this.opt('slotLabelInterval');
+ this.labelInterval = input ?
+ core.createDuration(input) :
+ this.computeLabelInterval(slotDuration);
+ };
+ // Computes an automatic value for slotLabelInterval
+ TimeGrid.prototype.computeLabelInterval = function (slotDuration) {
+ var i;
+ var labelInterval;
+ var slotsPerLabel;
+ // find the smallest stock label interval that results in more than one slots-per-label
+ for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
+ labelInterval = core.createDuration(AGENDA_STOCK_SUB_DURATIONS[i]);
+ slotsPerLabel = core.wholeDivideDurations(labelInterval, slotDuration);
+ if (slotsPerLabel !== null && slotsPerLabel > 1) {
+ return labelInterval;
+ }
+ }
+ return slotDuration; // fall back
+ };
+ /* Rendering
+ ------------------------------------------------------------------------------------------------------------------*/
+ TimeGrid.prototype.render = function (props) {
+ var cells = props.cells;
+ this.colCnt = cells.length;
+ this.renderSlats(props.dateProfile);
+ this.renderColumns(props.cells, props.dateProfile);
+ this.renderBusinessHours(props.businessHourSegs);
+ this.renderDateSelection(props.dateSelectionSegs);
+ this.renderFgEvents(props.fgEventSegs);
+ this.renderBgEvents(props.bgEventSegs);
+ this.renderEventSelection(props.eventSelection);
+ this.renderEventDrag(props.eventDrag);
+ this.renderEventResize(props.eventResize);
+ };
+ TimeGrid.prototype.destroy = function () {
+ _super.prototype.destroy.call(this);
+ // should unrender everything else too
+ this.renderSlats.unrender();
+ this.renderColumns.unrender();
+ };
+ TimeGrid.prototype.updateSize = function (isResize) {
+ var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
+ if (isResize || this.isSlatSizesDirty) {
+ this.buildSlatPositions();
+ this.isSlatSizesDirty = false;
+ }
+ if (isResize || this.isColSizesDirty) {
+ this.buildColPositions();
+ this.isColSizesDirty = false;
+ }
+ fillRenderer.computeSizes(isResize);
+ eventRenderer.computeSizes(isResize);
+ mirrorRenderer.computeSizes(isResize);
+ fillRenderer.assignSizes(isResize);
+ eventRenderer.assignSizes(isResize);
+ mirrorRenderer.assignSizes(isResize);
+ };
+ TimeGrid.prototype._renderSlats = function (dateProfile) {
+ var theme = this.theme;
+ this.slatContainerEl.innerHTML =
+ '
' +
+ this.renderSlatRowHtml(dateProfile) +
+ '
';
+ this.slatEls = core.findElements(this.slatContainerEl, 'tr');
+ this.slatPositions = new core.PositionCache(this.el, this.slatEls, false, true // vertical
+ );
+ this.isSlatSizesDirty = true;
+ };
+ // Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
+ TimeGrid.prototype.renderSlatRowHtml = function (dateProfile) {
+ var _a = this, dateEnv = _a.dateEnv, theme = _a.theme, isRtl = _a.isRtl;
+ var html = '';
+ var dayStart = core.startOfDay(dateProfile.renderRange.start);
+ var slotTime = dateProfile.minTime;
+ var slotIterator = core.createDuration(0);
+ var slotDate; // will be on the view's first day, but we only care about its time
+ var isLabeled;
+ var axisHtml;
+ // Calculate the time for each slot
+ while (core.asRoughMs(slotTime) < core.asRoughMs(dateProfile.maxTime)) {
+ slotDate = dateEnv.add(dayStart, slotTime);
+ isLabeled = core.wholeDivideDurations(slotIterator, this.labelInterval) !== null;
+ axisHtml =
+ '
');
+ this.colContainerEls = core.findElements(skeletonEl, '.fc-content-col');
+ this.mirrorContainerEls = core.findElements(skeletonEl, '.fc-mirror-container');
+ this.fgContainerEls = core.findElements(skeletonEl, '.fc-event-container:not(.fc-mirror-container)');
+ this.bgContainerEls = core.findElements(skeletonEl, '.fc-bgevent-container');
+ this.highlightContainerEls = core.findElements(skeletonEl, '.fc-highlight-container');
+ this.businessContainerEls = core.findElements(skeletonEl, '.fc-business-container');
+ if (this.isRtl) {
+ this.colContainerEls.reverse();
+ this.mirrorContainerEls.reverse();
+ this.fgContainerEls.reverse();
+ this.bgContainerEls.reverse();
+ this.highlightContainerEls.reverse();
+ this.businessContainerEls.reverse();
+ }
+ this.el.appendChild(skeletonEl);
+ };
+ TimeGrid.prototype.unrenderContentSkeleton = function () {
+ core.removeElement(this.contentSkeletonEl);
+ };
+ // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col
+ TimeGrid.prototype.groupSegsByCol = function (segs) {
+ var segsByCol = [];
+ var i;
+ for (i = 0; i < this.colCnt; i++) {
+ segsByCol.push([]);
+ }
+ for (i = 0; i < segs.length; i++) {
+ segsByCol[segs[i].col].push(segs[i]);
+ }
+ return segsByCol;
+ };
+ // Given segments grouped by column, insert the segments' elements into a parallel array of container
+ // elements, each living within a column.
+ TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) {
+ var col;
+ var segs;
+ var i;
+ for (col = 0; col < this.colCnt; col++) { // iterate each column grouping
+ segs = segsByCol[col];
+ for (i = 0; i < segs.length; i++) {
+ containerEls[col].appendChild(segs[i].el);
+ }
+ }
+ };
+ /* Now Indicator
+ ------------------------------------------------------------------------------------------------------------------*/
+ TimeGrid.prototype.getNowIndicatorUnit = function () {
+ return 'minute'; // will refresh on the minute
+ };
+ TimeGrid.prototype.renderNowIndicator = function (segs, date) {
+ // HACK: if date columns not ready for some reason (scheduler)
+ if (!this.colContainerEls) {
+ return;
+ }
+ var top = this.computeDateTop(date);
+ var nodes = [];
+ var i;
+ // render lines within the columns
+ for (i = 0; i < segs.length; i++) {
+ var lineEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-line' });
+ lineEl.style.top = top + 'px';
+ this.colContainerEls[segs[i].col].appendChild(lineEl);
+ nodes.push(lineEl);
+ }
+ // render an arrow over the axis
+ if (segs.length > 0) { // is the current time in view?
+ var arrowEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' });
+ arrowEl.style.top = top + 'px';
+ this.contentSkeletonEl.appendChild(arrowEl);
+ nodes.push(arrowEl);
+ }
+ this.nowIndicatorEls = nodes;
+ };
+ TimeGrid.prototype.unrenderNowIndicator = function () {
+ if (this.nowIndicatorEls) {
+ this.nowIndicatorEls.forEach(core.removeElement);
+ this.nowIndicatorEls = null;
+ }
+ };
+ /* Coordinates
+ ------------------------------------------------------------------------------------------------------------------*/
+ TimeGrid.prototype.getTotalSlatHeight = function () {
+ return this.slatContainerEl.offsetHeight;
+ };
+ // Computes the top coordinate, relative to the bounds of the grid, of the given date.
+ // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
+ TimeGrid.prototype.computeDateTop = function (when, startOfDayDate) {
+ if (!startOfDayDate) {
+ startOfDayDate = core.startOfDay(when);
+ }
+ return this.computeTimeTop(when.valueOf() - startOfDayDate.valueOf());
+ };
+ // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
+ TimeGrid.prototype.computeTimeTop = function (timeMs) {
+ var len = this.slatEls.length;
+ var dateProfile = this.props.dateProfile;
+ var slatCoverage = (timeMs - core.asRoughMs(dateProfile.minTime)) / core.asRoughMs(this.slotDuration); // floating-point value of # of slots covered
+ var slatIndex;
+ var slatRemainder;
+ // compute a floating-point number for how many slats should be progressed through.
+ // from 0 to number of slats (inclusive)
+ // constrained because minTime/maxTime might be customized.
+ slatCoverage = Math.max(0, slatCoverage);
+ slatCoverage = Math.min(len, slatCoverage);
+ // an integer index of the furthest whole slat
+ // from 0 to number slats (*exclusive*, so len-1)
+ slatIndex = Math.floor(slatCoverage);
+ slatIndex = Math.min(slatIndex, len - 1);
+ // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
+ // could be 1.0 if slatCoverage is covering *all* the slots
+ slatRemainder = slatCoverage - slatIndex;
+ return this.slatPositions.tops[slatIndex] +
+ this.slatPositions.getHeight(slatIndex) * slatRemainder;
+ };
+ // For each segment in an array, computes and assigns its top and bottom properties
+ TimeGrid.prototype.computeSegVerticals = function (segs) {
+ var eventMinHeight = this.opt('timeGridEventMinHeight');
+ var i;
+ var seg;
+ var dayDate;
+ for (i = 0; i < segs.length; i++) {
+ seg = segs[i];
+ dayDate = this.props.cells[seg.col].date;
+ seg.top = this.computeDateTop(seg.start, dayDate);
+ seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.end, dayDate));
+ }
+ };
+ // Given segments that already have their top/bottom properties computed, applies those values to
+ // the segments' elements.
+ TimeGrid.prototype.assignSegVerticals = function (segs) {
+ var i;
+ var seg;
+ for (i = 0; i < segs.length; i++) {
+ seg = segs[i];
+ core.applyStyle(seg.el, this.generateSegVerticalCss(seg));
+ }
+ };
+ // Generates an object with CSS properties for the top/bottom coordinates of a segment element
+ TimeGrid.prototype.generateSegVerticalCss = function (seg) {
+ return {
+ top: seg.top,
+ bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container
+ };
+ };
+ /* Sizing
+ ------------------------------------------------------------------------------------------------------------------*/
+ TimeGrid.prototype.buildPositionCaches = function () {
+ this.buildColPositions();
+ this.buildSlatPositions();
+ };
+ TimeGrid.prototype.buildColPositions = function () {
+ this.colPositions.build();
+ };
+ TimeGrid.prototype.buildSlatPositions = function () {
+ this.slatPositions.build();
+ };
+ /* Hit System
+ ------------------------------------------------------------------------------------------------------------------*/
+ TimeGrid.prototype.positionToHit = function (positionLeft, positionTop) {
+ var _a = this, dateEnv = _a.dateEnv, snapsPerSlot = _a.snapsPerSlot, slatPositions = _a.slatPositions, colPositions = _a.colPositions;
+ var colIndex = colPositions.leftToIndex(positionLeft);
+ var slatIndex = slatPositions.topToIndex(positionTop);
+ if (colIndex != null && slatIndex != null) {
+ var slatTop = slatPositions.tops[slatIndex];
+ var slatHeight = slatPositions.getHeight(slatIndex);
+ var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
+ var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
+ var snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
+ var dayDate = this.props.cells[colIndex].date;
+ var time = core.addDurations(this.props.dateProfile.minTime, core.multiplyDuration(this.snapDuration, snapIndex));
+ var start = dateEnv.add(dayDate, time);
+ var end = dateEnv.add(start, this.snapDuration);
+ return {
+ col: colIndex,
+ dateSpan: {
+ range: { start: start, end: end },
+ allDay: false
+ },
+ dayEl: this.colEls[colIndex],
+ relativeRect: {
+ left: colPositions.lefts[colIndex],
+ right: colPositions.rights[colIndex],
+ top: slatTop,
+ bottom: slatTop + slatHeight
+ }
+ };
+ }
+ };
+ /* Event Drag Visualization
+ ------------------------------------------------------------------------------------------------------------------*/
+ TimeGrid.prototype._renderEventDrag = function (state) {
+ if (state) {
+ this.eventRenderer.hideByHash(state.affectedInstances);
+ if (state.isEvent) {
+ this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
+ }
+ else {
+ this.fillRenderer.renderSegs('highlight', state.segs);
+ }
+ }
+ };
+ TimeGrid.prototype._unrenderEventDrag = function (state) {
+ if (state) {
+ this.eventRenderer.showByHash(state.affectedInstances);
+ this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
+ this.fillRenderer.unrender('highlight');
+ }
+ };
+ /* Event Resize Visualization
+ ------------------------------------------------------------------------------------------------------------------*/
+ TimeGrid.prototype._renderEventResize = function (state) {
+ if (state) {
+ this.eventRenderer.hideByHash(state.affectedInstances);
+ this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
+ }
+ };
+ TimeGrid.prototype._unrenderEventResize = function (state) {
+ if (state) {
+ this.eventRenderer.showByHash(state.affectedInstances);
+ this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
+ }
+ };
+ /* Selection
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
+ TimeGrid.prototype._renderDateSelection = function (segs) {
+ if (segs) {
+ if (this.opt('selectMirror')) {
+ this.mirrorRenderer.renderSegs(segs, { isSelecting: true });
+ }
+ else {
+ this.fillRenderer.renderSegs('highlight', segs);
+ }
+ }
+ };
+ TimeGrid.prototype._unrenderDateSelection = function (segs) {
+ this.mirrorRenderer.unrender(segs, { isSelecting: true });
+ this.fillRenderer.unrender('highlight');
+ };
+ return TimeGrid;
+ }(core.DateComponent));
+
+ var AllDaySplitter = /** @class */ (function (_super) {
+ __extends(AllDaySplitter, _super);
+ function AllDaySplitter() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ AllDaySplitter.prototype.getKeyInfo = function () {
+ return {
+ allDay: {},
+ timed: {}
+ };
+ };
+ AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) {
+ if (dateSpan.allDay) {
+ return ['allDay'];
+ }
+ else {
+ return ['timed'];
+ }
+ };
+ AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) {
+ if (!eventDef.allDay) {
+ return ['timed'];
+ }
+ else if (core.hasBgRendering(eventDef)) {
+ return ['timed', 'allDay'];
+ }
+ else {
+ return ['allDay'];
+ }
+ };
+ return AllDaySplitter;
+ }(core.Splitter));
+
+ var TIMEGRID_ALL_DAY_EVENT_LIMIT = 5;
+ var WEEK_HEADER_FORMAT = core.createFormatter({ week: 'short' });
+ /* An abstract class for all timegrid-related views. Displays one more columns with time slots running vertically.
+ ----------------------------------------------------------------------------------------------------------------------*/
+ // Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
+ // Responsible for managing width/height.
+ var TimeGridView = /** @class */ (function (_super) {
+ __extends(TimeGridView, _super);
+ function TimeGridView(context, viewSpec, dateProfileGenerator, parentEl) {
+ var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
+ _this.splitter = new AllDaySplitter();
+ /* Header Render Methods
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Generates the HTML that will go before the day-of week header cells
+ _this.renderHeadIntroHtml = function () {
+ var _a = _this, theme = _a.theme, dateEnv = _a.dateEnv;
+ var range = _this.props.dateProfile.renderRange;
+ var dayCnt = core.diffDays(range.start, range.end);
+ var weekText;
+ if (_this.opt('weekNumbers')) {
+ weekText = dateEnv.format(range.start, WEEK_HEADER_FORMAT);
+ return '' +
+ '
' +
+ core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
+ _this, { date: range.start, type: 'week', forceOff: dayCnt > 1 }, core.htmlEscape(weekText) // inner HTML
+ ) +
+ '
';
+ }
+ else {
+ return '
';
+ }
+ };
+ /* Time Grid Render Methods
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
+ _this.renderTimeGridBgIntroHtml = function () {
+ var theme = _this.theme;
+ return '
';
+ };
+ // Generates the HTML that goes before all other types of cells.
+ // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
+ _this.renderTimeGridIntroHtml = function () {
+ return '
';
+ };
+ /* Day Grid Render Methods
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Generates the HTML that goes before the all-day cells
+ _this.renderDayGridBgIntroHtml = function () {
+ var theme = _this.theme;
+ return '' +
+ '
';
+ };
+ // Generates the HTML that goes before all other types of cells.
+ // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
+ _this.renderDayGridIntroHtml = function () {
+ return '
';
+ };
+ _this.el.classList.add('fc-timeGrid-view');
+ _this.el.innerHTML = _this.renderSkeletonHtml();
+ _this.scroller = new core.ScrollComponent('hidden', // overflow x
+ 'auto' // overflow y
+ );
+ var timeGridWrapEl = _this.scroller.el;
+ _this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl);
+ timeGridWrapEl.classList.add('fc-time-grid-container');
+ var timeGridEl = core.createElement('div', { className: 'fc-time-grid' });
+ timeGridWrapEl.appendChild(timeGridEl);
+ _this.timeGrid = new TimeGrid(_this.context, timeGridEl, {
+ renderBgIntroHtml: _this.renderTimeGridBgIntroHtml,
+ renderIntroHtml: _this.renderTimeGridIntroHtml
+ });
+ if (_this.opt('allDaySlot')) { // should we display the "all-day" area?
+ _this.dayGrid = new daygrid.DayGrid(// the all-day subcomponent of this view
+ _this.context, _this.el.querySelector('.fc-day-grid'), {
+ renderNumberIntroHtml: _this.renderDayGridIntroHtml,
+ renderBgIntroHtml: _this.renderDayGridBgIntroHtml,
+ renderIntroHtml: _this.renderDayGridIntroHtml,
+ colWeekNumbersVisible: false,
+ cellWeekNumbersVisible: false
+ });
+ // have the day-grid extend it's coordinate area over the dividing the two grids
+ _this.dayGrid.bottomCoordPadding = _this.el.querySelector('.fc-divider').offsetHeight;
+ }
+ return _this;
+ }
+ TimeGridView.prototype.destroy = function () {
+ _super.prototype.destroy.call(this);
+ this.timeGrid.destroy();
+ if (this.dayGrid) {
+ this.dayGrid.destroy();
+ }
+ this.scroller.destroy();
+ };
+ /* Rendering
+ ------------------------------------------------------------------------------------------------------------------*/
+ // Builds the HTML skeleton for the view.
+ // The day-grid and time-grid components will render inside containers defined by this HTML.
+ TimeGridView.prototype.renderSkeletonHtml = function () {
+ var theme = this.theme;
+ return '' +
+ '