UNPKG

sleek-dashboard

Version:

Premium & Free Bootstrap 4 admin dashboard template by TAFcoder.com

1,040 lines (1,024 loc) 80.3 kB
/*! FullCalendar Day Grid Plugin v4.3.0 Docs & License: https://fullcalendar.io/ (c) 2019 Adam Shaw */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : (global = global || self, factory(global.FullCalendarDayGrid = {}, global.FullCalendar)); }(this, function (exports, core) { 'use strict'; /*! ***************************************************************************** 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. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var DayGridDateProfileGenerator = /** @class */ (function (_super) { __extends(DayGridDateProfileGenerator, _super); function DayGridDateProfileGenerator() { return _super !== null && _super.apply(this, arguments) || this; } // Computes the date range that will be rendered. DayGridDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { var dateEnv = this.dateEnv; var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay); var start = renderRange.start; var end = renderRange.end; var endOfWeek; // year and month views should be aligned with weeks. this is already done for week if (/^(year|month)$/.test(currentRangeUnit)) { start = dateEnv.startOfWeek(start); // make end-of-week if not already endOfWeek = dateEnv.startOfWeek(end); if (endOfWeek.valueOf() !== end.valueOf()) { end = core.addWeeks(endOfWeek, 1); } } // ensure 6 weeks if (this.options.monthMode && this.options.fixedWeekCount) { var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays core.diffWeeks(start, end)); end = core.addWeeks(end, 6 - rowCnt); } return { start: start, end: end }; }; return DayGridDateProfileGenerator; }(core.DateProfileGenerator)); /* A rectangular panel that is absolutely positioned over other content ------------------------------------------------------------------------------------------------------------------------ Options: - className (string) - content (HTML string, element, or element array) - parentEl - top - left - right (the x coord of where the right edge should be. not a "CSS" right) - autoHide (boolean) - show (callback) - hide (callback) */ var Popover = /** @class */ (function () { function Popover(options) { var _this = this; this.isHidden = true; this.margin = 10; // the space required between the popover and the edges of the scroll container // Triggered when the user clicks *anywhere* in the document, for the autoHide feature this.documentMousedown = function (ev) { // only hide the popover if the click happened outside the popover if (_this.el && !_this.el.contains(ev.target)) { _this.hide(); } }; this.options = options; } // Shows the popover on the specified position. Renders it if not already Popover.prototype.show = function () { if (this.isHidden) { if (!this.el) { this.render(); } this.el.style.display = ''; this.position(); this.isHidden = false; this.trigger('show'); } }; // Hides the popover, through CSS, but does not remove it from the DOM Popover.prototype.hide = function () { if (!this.isHidden) { this.el.style.display = 'none'; this.isHidden = true; this.trigger('hide'); } }; // Creates `this.el` and renders content inside of it Popover.prototype.render = function () { var _this = this; var options = this.options; var el = this.el = core.createElement('div', { className: 'fc-popover ' + (options.className || ''), style: { top: '0', left: '0' } }); if (typeof options.content === 'function') { options.content(el); } options.parentEl.appendChild(el); // when a click happens on anything inside with a 'fc-close' className, hide the popover core.listenBySelector(el, 'click', '.fc-close', function (ev) { _this.hide(); }); if (options.autoHide) { document.addEventListener('mousedown', this.documentMousedown); } }; // Hides and unregisters any handlers Popover.prototype.destroy = function () { this.hide(); if (this.el) { core.removeElement(this.el); this.el = null; } document.removeEventListener('mousedown', this.documentMousedown); }; // Positions the popover optimally, using the top/left/right options Popover.prototype.position = function () { var options = this.options; var el = this.el; var elDims = el.getBoundingClientRect(); // only used for width,height var origin = core.computeRect(el.offsetParent); var clippingRect = core.computeClippingRect(options.parentEl); var top; // the "position" (not "offset") values for the popover var left; // // compute top and left top = options.top || 0; if (options.left !== undefined) { left = options.left; } else if (options.right !== undefined) { left = options.right - elDims.width; // derive the left value from the right value } else { left = 0; } // constrain to the view port. if constrained by two edges, give precedence to top/left top = Math.min(top, clippingRect.bottom - elDims.height - this.margin); top = Math.max(top, clippingRect.top + this.margin); left = Math.min(left, clippingRect.right - elDims.width - this.margin); left = Math.max(left, clippingRect.left + this.margin); core.applyStyle(el, { top: top - origin.top, left: left - origin.left }); }; // Triggers a callback. Calls a function in the option hash of the same name. // Arguments beyond the first `name` are forwarded on. // TODO: better code reuse for this. Repeat code // can kill this??? Popover.prototype.trigger = function (name) { if (this.options[name]) { this.options[name].apply(this, Array.prototype.slice.call(arguments, 1)); } }; return Popover; }()); /* Event-rendering methods for the DayGrid class ----------------------------------------------------------------------------------------------------------------------*/ // "Simple" is bad a name. has nothing to do with SimpleDayGrid var SimpleDayGridEventRenderer = /** @class */ (function (_super) { __extends(SimpleDayGridEventRenderer, _super); function SimpleDayGridEventRenderer() { return _super !== null && _super.apply(this, arguments) || this; } // Builds the HTML to be used for the default element for an individual segment SimpleDayGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { var _a = this.context, view = _a.view, options = _a.options; var eventRange = seg.eventRange; var eventDef = eventRange.def; var eventUi = eventRange.ui; var allDay = eventDef.allDay; var isDraggable = view.computeEventDraggable(eventDef, eventUi); var isResizableFromStart = allDay && seg.isStart && view.computeEventStartResizable(eventDef, eventUi); var isResizableFromEnd = allDay && seg.isEnd && view.computeEventEndResizable(eventDef, eventUi); var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); var skinCss = core.cssToStr(this.getSkinCss(eventUi)); var timeHtml = ''; var timeText; var titleHtml; classes.unshift('fc-day-grid-event', 'fc-h-event'); // Only display a timed events time if it is the starting segment if (seg.isStart) { timeText = this.getTimeText(eventRange); if (timeText) { timeHtml = '<span class="fc-time">' + core.htmlEscape(timeText) + '</span>'; } } titleHtml = '<span class="fc-title">' + (core.htmlEscape(eventDef.title || '') || '&nbsp;') + // we always want one line of height '</span>'; return '<a class="' + classes.join(' ') + '"' + (eventDef.url ? ' href="' + core.htmlEscape(eventDef.url) + '"' : '') + (skinCss ? ' style="' + skinCss + '"' : '') + '>' + '<div class="fc-content">' + (options.dir === 'rtl' ? titleHtml + ' ' + timeHtml : // put a natural space in between timeHtml + ' ' + titleHtml // ) + '</div>' + (isResizableFromStart ? '<div class="fc-resizer fc-start-resizer"></div>' : '') + (isResizableFromEnd ? '<div class="fc-resizer fc-end-resizer"></div>' : '') + '</a>'; }; // 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 <tbody> 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 <tbody> 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 <td> elements of the level+col matrix var loneCellMatrix = []; // lookup for <td> 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('<div class="fc-mirror-skeleton"><table></table></div>'); // 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 EMPTY_CELL_HTML = '<td style="pointer-events:none"></td>'; 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('<div class="fc-' + className + '-skeleton">' + '<table><tr></tr></table>' + '</div>'); trEl = skeletonEl.getElementsByTagName('tr')[0]; if (startCol > 0) { core.appendToElement(trEl, // will create (startCol + 1) td's new Array(startCol + 1).join(EMPTY_CELL_HTML)); } seg.el.colSpan = endCol - startCol; trEl.appendChild(seg.el); if (endCol < colCnt) { core.appendToElement(trEl, // will create (colCnt - endCol) td's new Array(colCnt - endCol + 1).join(EMPTY_CELL_HTML)); } var introHtml = dayGrid.renderProps.renderIntroHtml(); if (introHtml) { if (dayGrid.isRtl) { core.appendToElement(trEl, introHtml); } else { core.prependToElement(trEl, introHtml); } } return skeletonEl; }; return DayGridFillRenderer; }(core.FillRenderer)); var DayTile = /** @class */ (function (_super) { __extends(DayTile, _super); function DayTile(context, el) { var _this = _super.call(this, context, el) || this; var eventRenderer = _this.eventRenderer = new DayTileEventRenderer(_this); var renderFrame = _this.renderFrame = core.memoizeRendering(_this._renderFrame); _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderFrame]); _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); _this.renderEventDrag = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); _this.renderEventResize = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); context.calendar.registerInteractiveComponent(_this, { el: _this.el, useEventCenter: false }); return _this; } DayTile.prototype.render = function (props) { this.renderFrame(props.date); this.renderFgEvents(props.fgSegs); this.renderEventSelection(props.eventSelection); this.renderEventDrag(props.eventDragInstances); this.renderEventResize(props.eventResizeInstances); }; DayTile.prototype.destroy = function () { _super.prototype.destroy.call(this); this.renderFrame.unrender(); // should unrender everything else this.calendar.unregisterInteractiveComponent(this); }; DayTile.prototype._renderFrame = function (date) { var _a = this, theme = _a.theme, dateEnv = _a.dateEnv; var title = dateEnv.format(date, core.createFormatter(this.opt('dayPopoverFormat')) // TODO: cache ); this.el.innerHTML = '<div class="fc-header ' + theme.getClass('popoverHeader') + '">' + '<span class="fc-title">' + core.htmlEscape(title) + '</span>' + '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' + '</div>' + '<div class="fc-body ' + theme.getClass('popoverContent') + '">' + '<div class="fc-event-container"></div>' + '</div>'; this.segContainerEl = this.el.querySelector('.fc-event-container'); }; DayTile.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { var date = this.props.date; // HACK if (positionLeft < elWidth && positionTop < elHeight) { return { component: this, dateSpan: { allDay: true, range: { start: date, end: core.addDays(date, 1) } }, dayEl: this.el, rect: { left: 0, top: 0, right: elWidth, bottom: elHeight }, layer: 1 }; } }; return DayTile; }(core.DateComponent)); var DayTileEventRenderer = /** @class */ (function (_super) { __extends(DayTileEventRenderer, _super); function DayTileEventRenderer(dayTile) { var _this = _super.call(this, dayTile.context) || this; _this.dayTile = dayTile; return _this; } DayTileEventRenderer.prototype.attachSegs = function (segs) { for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { var seg = segs_1[_i]; this.dayTile.segContainerEl.appendChild(seg.el); } }; DayTileEventRenderer.prototype.detachSegs = function (segs) { for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { var seg = segs_2[_i]; core.removeElement(seg.el); } }; return DayTileEventRenderer; }(SimpleDayGridEventRenderer)); var DayBgRow = /** @class */ (function () { function DayBgRow(context) { this.context = context; } DayBgRow.prototype.renderHtml = function (props) { var parts = []; if (props.renderIntroHtml) { parts.push(props.renderIntroHtml()); } for (var _i = 0, _a = props.cells; _i < _a.length; _i++) { var cell = _a[_i]; parts.push(renderCellHtml(cell.date, props.dateProfile, this.context, cell.htmlAttrs)); } if (!props.cells.length) { parts.push('<td class="fc-day ' + this.context.theme.getClass('widgetContent') + '"></td>'); } if (this.context.options.dir === 'rtl') { parts.reverse(); } return '<tr>' + parts.join('') + '</tr>'; }; return DayBgRow; }()); function renderCellHtml(date, dateProfile, context, otherAttrs) { var dateEnv = context.dateEnv, theme = context.theme; var isDateValid = core.rangeContainsMarker(dateProfile.activeRange, date); // TODO: called too frequently. cache somehow. var classes = core.getDayClasses(date, dateProfile, context); classes.unshift('fc-day', theme.getClass('widgetContent')); return '<td class="' + classes.join(' ') + '"' + (isDateValid ? ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : '') + (otherAttrs ? ' ' + otherAttrs : '') + '></td>'; } var DAY_NUM_FORMAT = core.createFormatter({ day: 'numeric' }); var WEEK_NUM_FORMAT = core.createFormatter({ week: 'numeric' }); var DayGrid = /** @class */ (function (_super) { __extends(DayGrid, _super); function DayGrid(context, el, renderProps) { var _this = _super.call(this, context, el) || this; _this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid _this.isCellSizesDirty = false; var eventRenderer = _this.eventRenderer = new DayGridEventRenderer(_this); var fillRenderer = _this.fillRenderer = new DayGridFillRenderer(_this); _this.mirrorRenderer = new DayGridMirrorRenderer(_this); var renderCells = _this.renderCells = core.memoizeRendering(_this._renderCells, _this._unrenderCells); _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderCells]); _this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'), [renderCells]); _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderCells]); _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderCells]); _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderCells]); _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderCells]); _this.renderProps = renderProps; return _this; } DayGrid.prototype.render = function (props) { var cells = props.cells; this.rowCnt = cells.length; this.colCnt = cells[0].length; this.renderCells(cells, props.isRigid); this.renderBusinessHours(props.businessHourSegs); this.renderDateSelection(props.dateSelectionSegs); this.renderBgEvents(props.bgEventSegs); this.renderFgEvents(props.fgEventSegs); this.renderEventSelection(props.eventSelection); this.renderEventDrag(props.eventDrag); this.renderEventResize(props.eventResize); if (this.segPopoverTile) { this.updateSegPopoverTile(); } }; DayGrid.prototype.destroy = function () { _super.prototype.destroy.call(this); this.renderCells.unrender(); // will unrender everything else }; DayGrid.prototype.getCellRange = function (row, col) { var start = this.props.cells[row][col].date; var end = core.addDays(start, 1); return { start: start, end: end }; }; DayGrid.prototype.updateSegPopoverTile = function (date, segs) { var ownProps = this.props; this.segPopoverTile.receiveProps({ date: date || this.segPopoverTile.props.date, fgSegs: segs || this.segPopoverTile.props.fgSegs, eventSelection: ownProps.eventSelection, eventDragInstances: ownProps.eventDrag ? ownProps.eventDrag.affectedInstances : null, eventResizeInstances: ownProps.eventResize ? ownProps.eventResize.affectedInstances : null }); }; /* Date Rendering ------------------------------------------------------------------------------------------------------------------*/ DayGrid.prototype._renderCells = function (cells, isRigid) { var _a = this, view = _a.view, dateEnv = _a.dateEnv; var _b = this, rowCnt = _b.rowCnt, colCnt = _b.colCnt; var html = ''; var row; var col; for (row = 0; row < rowCnt; row++) { html += this.renderDayRowHtml(row, isRigid); } this.el.innerHTML = html; this.rowEls = core.findElements(this.el, '.fc-row'); this.cellEls = core.findElements(this.el, '.fc-day, .fc-disabled-day'); if (this.isRtl) { this.cellEls.reverse(); } this.rowPositions = new core.PositionCache(this.el, this.rowEls, false, true // vertical ); this.colPositions = new core.PositionCache(this.el, this.cellEls.slice(0, colCnt), // only the first row true, false // horizontal ); // trigger dayRender with each cell's element for (row = 0; row < rowCnt; row++) { for (col = 0; col < colCnt; col++) { this.publiclyTrigger('dayRender', [ { date: dateEnv.toDate(cells[row][col].date), el: this.getCellEl(row, col), view: view } ]); } } this.isCellSizesDirty = true; }; DayGrid.prototype._unrenderCells = function () { this.removeSegPopover(); }; // Generates the HTML for a single row, which is a div that wraps a table. // `row` is the row number. DayGrid.prototype.renderDayRowHtml = function (row, isRigid) { var theme = this.theme; var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')]; if (isRigid) { classes.push('fc-rigid'); } var bgRow = new DayBgRow(this.context); return '' + '<div class="' + classes.join(' ') + '">' + '<div class="fc-bg">' + '<table class="' + theme.getClass('tableGrid') + '">' + bgRow.renderHtml({ cells: this.props.cells[row], dateProfile: this.props.dateProfile, renderIntroHtml: this.renderProps.renderBgIntroHtml }) + '</table>' + '</div>' + '<div class="fc-content-skeleton">' + '<table>' + (this.getIsNumbersVisible() ? '<thead>' + this.renderNumberTrHtml(row) + '</thead>' : '') + '</table>' + '</div>' + '</div>'; }; DayGrid.prototype.getIsNumbersVisible = function () { return this.getIsDayNumbersVisible() || this.renderProps.cellWeekNumbersVisible || this.renderProps.colWeekNumbersVisible; }; DayGrid.prototype.getIsDayNumbersVisible = function () { return this.rowCnt > 1; }; /* Grid Number Rendering ------------------------------------------------------------------------------------------------------------------*/ DayGrid.prototype.renderNumberTrHtml = function (row) { var intro = this.renderProps.renderNumberIntroHtml(row, this); return '' + '<tr>' + (this.isRtl ? '' : intro) + this.renderNumberCellsHtml(row) + (this.isRtl ? intro : '') + '</tr>'; }; 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 <td>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 '<td></td>'; // 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 += '<td class="' + classes.join(' ') + '"' + (isDateValid ? ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : '') + '>'; 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 += '</td>'; 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 <tr> 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)