fullcalendar-daygrid.js 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669
  1. /*!
  2. FullCalendar Day Grid Plugin v4.4.2
  3. Docs & License: https://fullcalendar.io/
  4. (c) 2019 Adam Shaw
  5. */
  6. (function (global, factory) {
  7. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
  8. typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
  9. (global = global || self, factory(global.FullCalendarDayGrid = {}, global.FullCalendar));
  10. }(this, function (exports, core) { 'use strict';
  11. /*! *****************************************************************************
  12. Copyright (c) Microsoft Corporation.
  13. Permission to use, copy, modify, and/or distribute this software for any
  14. purpose with or without fee is hereby granted.
  15. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  16. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  17. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  18. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  19. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  20. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. PERFORMANCE OF THIS SOFTWARE.
  22. ***************************************************************************** */
  23. /* global Reflect, Promise */
  24. var extendStatics = function(d, b) {
  25. extendStatics = Object.setPrototypeOf ||
  26. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  27. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  28. return extendStatics(d, b);
  29. };
  30. function __extends(d, b) {
  31. extendStatics(d, b);
  32. function __() { this.constructor = d; }
  33. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  34. }
  35. var __assign = function() {
  36. __assign = Object.assign || function __assign(t) {
  37. for (var s, i = 1, n = arguments.length; i < n; i++) {
  38. s = arguments[i];
  39. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  40. }
  41. return t;
  42. };
  43. return __assign.apply(this, arguments);
  44. };
  45. var DayGridDateProfileGenerator = /** @class */ (function (_super) {
  46. __extends(DayGridDateProfileGenerator, _super);
  47. function DayGridDateProfileGenerator() {
  48. return _super !== null && _super.apply(this, arguments) || this;
  49. }
  50. // Computes the date range that will be rendered.
  51. DayGridDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) {
  52. var dateEnv = this.dateEnv;
  53. var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay);
  54. var start = renderRange.start;
  55. var end = renderRange.end;
  56. var endOfWeek;
  57. // year and month views should be aligned with weeks. this is already done for week
  58. if (/^(year|month)$/.test(currentRangeUnit)) {
  59. start = dateEnv.startOfWeek(start);
  60. // make end-of-week if not already
  61. endOfWeek = dateEnv.startOfWeek(end);
  62. if (endOfWeek.valueOf() !== end.valueOf()) {
  63. end = core.addWeeks(endOfWeek, 1);
  64. }
  65. }
  66. // ensure 6 weeks
  67. if (this.options.monthMode &&
  68. this.options.fixedWeekCount) {
  69. var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
  70. core.diffWeeks(start, end));
  71. end = core.addWeeks(end, 6 - rowCnt);
  72. }
  73. return { start: start, end: end };
  74. };
  75. return DayGridDateProfileGenerator;
  76. }(core.DateProfileGenerator));
  77. /* A rectangular panel that is absolutely positioned over other content
  78. ------------------------------------------------------------------------------------------------------------------------
  79. Options:
  80. - className (string)
  81. - content (HTML string, element, or element array)
  82. - parentEl
  83. - top
  84. - left
  85. - right (the x coord of where the right edge should be. not a "CSS" right)
  86. - autoHide (boolean)
  87. - show (callback)
  88. - hide (callback)
  89. */
  90. var Popover = /** @class */ (function () {
  91. function Popover(options) {
  92. var _this = this;
  93. this.isHidden = true;
  94. this.margin = 10; // the space required between the popover and the edges of the scroll container
  95. // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
  96. this.documentMousedown = function (ev) {
  97. // only hide the popover if the click happened outside the popover
  98. if (_this.el && !_this.el.contains(ev.target)) {
  99. _this.hide();
  100. }
  101. };
  102. this.options = options;
  103. }
  104. // Shows the popover on the specified position. Renders it if not already
  105. Popover.prototype.show = function () {
  106. if (this.isHidden) {
  107. if (!this.el) {
  108. this.render();
  109. }
  110. this.el.style.display = '';
  111. this.position();
  112. this.isHidden = false;
  113. this.trigger('show');
  114. }
  115. };
  116. // Hides the popover, through CSS, but does not remove it from the DOM
  117. Popover.prototype.hide = function () {
  118. if (!this.isHidden) {
  119. this.el.style.display = 'none';
  120. this.isHidden = true;
  121. this.trigger('hide');
  122. }
  123. };
  124. // Creates `this.el` and renders content inside of it
  125. Popover.prototype.render = function () {
  126. var _this = this;
  127. var options = this.options;
  128. var el = this.el = core.createElement('div', {
  129. className: 'fc-popover ' + (options.className || ''),
  130. style: {
  131. top: '0',
  132. left: '0'
  133. }
  134. });
  135. if (typeof options.content === 'function') {
  136. options.content(el);
  137. }
  138. options.parentEl.appendChild(el);
  139. // when a click happens on anything inside with a 'fc-close' className, hide the popover
  140. core.listenBySelector(el, 'click', '.fc-close', function (ev) {
  141. _this.hide();
  142. });
  143. if (options.autoHide) {
  144. document.addEventListener('mousedown', this.documentMousedown);
  145. }
  146. };
  147. // Hides and unregisters any handlers
  148. Popover.prototype.destroy = function () {
  149. this.hide();
  150. if (this.el) {
  151. core.removeElement(this.el);
  152. this.el = null;
  153. }
  154. document.removeEventListener('mousedown', this.documentMousedown);
  155. };
  156. // Positions the popover optimally, using the top/left/right options
  157. Popover.prototype.position = function () {
  158. var options = this.options;
  159. var el = this.el;
  160. var elDims = el.getBoundingClientRect(); // only used for width,height
  161. var origin = core.computeRect(el.offsetParent);
  162. var clippingRect = core.computeClippingRect(options.parentEl);
  163. var top; // the "position" (not "offset") values for the popover
  164. var left; //
  165. // compute top and left
  166. top = options.top || 0;
  167. if (options.left !== undefined) {
  168. left = options.left;
  169. }
  170. else if (options.right !== undefined) {
  171. left = options.right - elDims.width; // derive the left value from the right value
  172. }
  173. else {
  174. left = 0;
  175. }
  176. // constrain to the view port. if constrained by two edges, give precedence to top/left
  177. top = Math.min(top, clippingRect.bottom - elDims.height - this.margin);
  178. top = Math.max(top, clippingRect.top + this.margin);
  179. left = Math.min(left, clippingRect.right - elDims.width - this.margin);
  180. left = Math.max(left, clippingRect.left + this.margin);
  181. core.applyStyle(el, {
  182. top: top - origin.top,
  183. left: left - origin.left
  184. });
  185. };
  186. // Triggers a callback. Calls a function in the option hash of the same name.
  187. // Arguments beyond the first `name` are forwarded on.
  188. // TODO: better code reuse for this. Repeat code
  189. // can kill this???
  190. Popover.prototype.trigger = function (name) {
  191. if (this.options[name]) {
  192. this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
  193. }
  194. };
  195. return Popover;
  196. }());
  197. /* Event-rendering methods for the DayGrid class
  198. ----------------------------------------------------------------------------------------------------------------------*/
  199. // "Simple" is bad a name. has nothing to do with SimpleDayGrid
  200. var SimpleDayGridEventRenderer = /** @class */ (function (_super) {
  201. __extends(SimpleDayGridEventRenderer, _super);
  202. function SimpleDayGridEventRenderer() {
  203. return _super !== null && _super.apply(this, arguments) || this;
  204. }
  205. // Builds the HTML to be used for the default element for an individual segment
  206. SimpleDayGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
  207. var context = this.context;
  208. var eventRange = seg.eventRange;
  209. var eventDef = eventRange.def;
  210. var eventUi = eventRange.ui;
  211. var allDay = eventDef.allDay;
  212. var isDraggable = core.computeEventDraggable(context, eventDef, eventUi);
  213. var isResizableFromStart = allDay && seg.isStart && core.computeEventStartResizable(context, eventDef, eventUi);
  214. var isResizableFromEnd = allDay && seg.isEnd && core.computeEventEndResizable(context, eventDef, eventUi);
  215. var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo);
  216. var skinCss = core.cssToStr(this.getSkinCss(eventUi));
  217. var timeHtml = '';
  218. var timeText;
  219. var titleHtml;
  220. classes.unshift('fc-day-grid-event', 'fc-h-event');
  221. // Only display a timed events time if it is the starting segment
  222. if (seg.isStart) {
  223. timeText = this.getTimeText(eventRange);
  224. if (timeText) {
  225. timeHtml = '<span class="fc-time">' + core.htmlEscape(timeText) + '</span>';
  226. }
  227. }
  228. titleHtml =
  229. '<span class="fc-title">' +
  230. (core.htmlEscape(eventDef.title || '') || '&nbsp;') + // we always want one line of height
  231. '</span>';
  232. return '<a class="' + classes.join(' ') + '"' +
  233. (eventDef.url ?
  234. ' href="' + core.htmlEscape(eventDef.url) + '"' :
  235. '') +
  236. (skinCss ?
  237. ' style="' + skinCss + '"' :
  238. '') +
  239. '>' +
  240. '<div class="fc-content">' +
  241. (context.options.dir === 'rtl' ?
  242. titleHtml + ' ' + timeHtml : // put a natural space in between
  243. timeHtml + ' ' + titleHtml //
  244. ) +
  245. '</div>' +
  246. (isResizableFromStart ?
  247. '<div class="fc-resizer fc-start-resizer"></div>' :
  248. '') +
  249. (isResizableFromEnd ?
  250. '<div class="fc-resizer fc-end-resizer"></div>' :
  251. '') +
  252. '</a>';
  253. };
  254. // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
  255. SimpleDayGridEventRenderer.prototype.computeEventTimeFormat = function () {
  256. return {
  257. hour: 'numeric',
  258. minute: '2-digit',
  259. omitZeroMinute: true,
  260. meridiem: 'narrow'
  261. };
  262. };
  263. SimpleDayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
  264. return false; // TODO: somehow consider the originating DayGrid's column count
  265. };
  266. return SimpleDayGridEventRenderer;
  267. }(core.FgEventRenderer));
  268. /* Event-rendering methods for the DayGrid class
  269. ----------------------------------------------------------------------------------------------------------------------*/
  270. var DayGridEventRenderer = /** @class */ (function (_super) {
  271. __extends(DayGridEventRenderer, _super);
  272. function DayGridEventRenderer(dayGrid) {
  273. var _this = _super.call(this) || this;
  274. _this.dayGrid = dayGrid;
  275. return _this;
  276. }
  277. // Renders the given foreground event segments onto the grid
  278. DayGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
  279. var rowStructs = this.rowStructs = this.renderSegRows(segs);
  280. // append to each row's content skeleton
  281. this.dayGrid.rowEls.forEach(function (rowNode, i) {
  282. rowNode.querySelector('.fc-content-skeleton > table').appendChild(rowStructs[i].tbodyEl);
  283. });
  284. // removes the "more.." events popover
  285. if (!mirrorInfo) {
  286. this.dayGrid.removeSegPopover();
  287. }
  288. };
  289. // Unrenders all currently rendered foreground event segments
  290. DayGridEventRenderer.prototype.detachSegs = function () {
  291. var rowStructs = this.rowStructs || [];
  292. var rowStruct;
  293. while ((rowStruct = rowStructs.pop())) {
  294. core.removeElement(rowStruct.tbodyEl);
  295. }
  296. this.rowStructs = null;
  297. };
  298. // Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton.
  299. // Returns an array of rowStruct objects (see the bottom of `renderSegRow`).
  300. // PRECONDITION: each segment shoud already have a rendered and assigned `.el`
  301. DayGridEventRenderer.prototype.renderSegRows = function (segs) {
  302. var rowStructs = [];
  303. var segRows;
  304. var row;
  305. segRows = this.groupSegRows(segs); // group into nested arrays
  306. // iterate each row of segment groupings
  307. for (row = 0; row < segRows.length; row++) {
  308. rowStructs.push(this.renderSegRow(row, segRows[row]));
  309. }
  310. return rowStructs;
  311. };
  312. // Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains
  313. // the segments. Returns object with a bunch of internal data about how the render was calculated.
  314. // NOTE: modifies rowSegs
  315. DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) {
  316. var isRtl = this.context.isRtl;
  317. var dayGrid = this.dayGrid;
  318. var colCnt = dayGrid.colCnt;
  319. var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels
  320. var levelCnt = Math.max(1, segLevels.length); // ensure at least one level
  321. var tbody = document.createElement('tbody');
  322. var segMatrix = []; // lookup for which segments are rendered into which level+col cells
  323. var cellMatrix = []; // lookup for all <td> elements of the level+col matrix
  324. var loneCellMatrix = []; // lookup for <td> elements that only take up a single column
  325. var i;
  326. var levelSegs;
  327. var col;
  328. var tr;
  329. var j;
  330. var seg;
  331. var td;
  332. // populates empty cells from the current column (`col`) to `endCol`
  333. function emptyCellsUntil(endCol) {
  334. while (col < endCol) {
  335. // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell
  336. td = (loneCellMatrix[i - 1] || [])[col];
  337. if (td) {
  338. td.rowSpan = (td.rowSpan || 1) + 1;
  339. }
  340. else {
  341. td = document.createElement('td');
  342. tr.appendChild(td);
  343. }
  344. cellMatrix[i][col] = td;
  345. loneCellMatrix[i][col] = td;
  346. col++;
  347. }
  348. }
  349. for (i = 0; i < levelCnt; i++) { // iterate through all levels
  350. levelSegs = segLevels[i];
  351. col = 0;
  352. tr = document.createElement('tr');
  353. segMatrix.push([]);
  354. cellMatrix.push([]);
  355. loneCellMatrix.push([]);
  356. // levelCnt might be 1 even though there are no actual levels. protect against this.
  357. // this single empty row is useful for styling.
  358. if (levelSegs) {
  359. for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level
  360. seg = levelSegs[j];
  361. var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
  362. var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
  363. emptyCellsUntil(leftCol);
  364. // create a container that occupies or more columns. append the event element.
  365. td = core.createElement('td', { className: 'fc-event-container' }, seg.el);
  366. if (leftCol !== rightCol) {
  367. td.colSpan = rightCol - leftCol + 1;
  368. }
  369. else { // a single-column segment
  370. loneCellMatrix[i][col] = td;
  371. }
  372. while (col <= rightCol) {
  373. cellMatrix[i][col] = td;
  374. segMatrix[i][col] = seg;
  375. col++;
  376. }
  377. tr.appendChild(td);
  378. }
  379. }
  380. emptyCellsUntil(colCnt); // finish off the row
  381. var introHtml = dayGrid.renderProps.renderIntroHtml();
  382. if (introHtml) {
  383. if (isRtl) {
  384. core.appendToElement(tr, introHtml);
  385. }
  386. else {
  387. core.prependToElement(tr, introHtml);
  388. }
  389. }
  390. tbody.appendChild(tr);
  391. }
  392. return {
  393. row: row,
  394. tbodyEl: tbody,
  395. cellMatrix: cellMatrix,
  396. segMatrix: segMatrix,
  397. segLevels: segLevels,
  398. segs: rowSegs
  399. };
  400. };
  401. // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels.
  402. // NOTE: modifies segs
  403. DayGridEventRenderer.prototype.buildSegLevels = function (segs) {
  404. var isRtl = this.context.isRtl;
  405. var colCnt = this.dayGrid.colCnt;
  406. var levels = [];
  407. var i;
  408. var seg;
  409. var j;
  410. // Give preference to elements with certain criteria, so they have
  411. // a chance to be closer to the top.
  412. segs = this.sortEventSegs(segs);
  413. for (i = 0; i < segs.length; i++) {
  414. seg = segs[i];
  415. // loop through levels, starting with the topmost, until the segment doesn't collide with other segments
  416. for (j = 0; j < levels.length; j++) {
  417. if (!isDaySegCollision(seg, levels[j])) {
  418. break;
  419. }
  420. }
  421. // `j` now holds the desired subrow index
  422. seg.level = j;
  423. seg.leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; // for sorting only
  424. seg.rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol // for sorting only
  425. ;
  426. (levels[j] || (levels[j] = [])).push(seg);
  427. }
  428. // order segments left-to-right. very important if calendar is RTL
  429. for (j = 0; j < levels.length; j++) {
  430. levels[j].sort(compareDaySegCols);
  431. }
  432. return levels;
  433. };
  434. // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row
  435. DayGridEventRenderer.prototype.groupSegRows = function (segs) {
  436. var segRows = [];
  437. var i;
  438. for (i = 0; i < this.dayGrid.rowCnt; i++) {
  439. segRows.push([]);
  440. }
  441. for (i = 0; i < segs.length; i++) {
  442. segRows[segs[i].row].push(segs[i]);
  443. }
  444. return segRows;
  445. };
  446. // Computes a default `displayEventEnd` value if one is not expliclty defined
  447. DayGridEventRenderer.prototype.computeDisplayEventEnd = function () {
  448. return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day
  449. };
  450. return DayGridEventRenderer;
  451. }(SimpleDayGridEventRenderer));
  452. // Computes whether two segments' columns collide. They are assumed to be in the same row.
  453. function isDaySegCollision(seg, otherSegs) {
  454. var i;
  455. var otherSeg;
  456. for (i = 0; i < otherSegs.length; i++) {
  457. otherSeg = otherSegs[i];
  458. if (otherSeg.firstCol <= seg.lastCol &&
  459. otherSeg.lastCol >= seg.firstCol) {
  460. return true;
  461. }
  462. }
  463. return false;
  464. }
  465. // A cmp function for determining the leftmost event
  466. function compareDaySegCols(a, b) {
  467. return a.leftCol - b.leftCol;
  468. }
  469. var DayGridMirrorRenderer = /** @class */ (function (_super) {
  470. __extends(DayGridMirrorRenderer, _super);
  471. function DayGridMirrorRenderer() {
  472. return _super !== null && _super.apply(this, arguments) || this;
  473. }
  474. DayGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
  475. var sourceSeg = mirrorInfo.sourceSeg;
  476. var rowStructs = this.rowStructs = this.renderSegRows(segs);
  477. // inject each new event skeleton into each associated row
  478. this.dayGrid.rowEls.forEach(function (rowNode, row) {
  479. var skeletonEl = core.htmlToElement('<div class="fc-mirror-skeleton"><table></table></div>'); // will be absolutely positioned
  480. var skeletonTopEl;
  481. var skeletonTop;
  482. // If there is an original segment, match the top position. Otherwise, put it at the row's top level
  483. if (sourceSeg && sourceSeg.row === row) {
  484. skeletonTopEl = sourceSeg.el;
  485. }
  486. else {
  487. skeletonTopEl = rowNode.querySelector('.fc-content-skeleton tbody');
  488. if (!skeletonTopEl) { // when no events
  489. skeletonTopEl = rowNode.querySelector('.fc-content-skeleton table');
  490. }
  491. }
  492. skeletonTop = skeletonTopEl.getBoundingClientRect().top -
  493. rowNode.getBoundingClientRect().top; // the offsetParent origin
  494. skeletonEl.style.top = skeletonTop + 'px';
  495. skeletonEl.querySelector('table').appendChild(rowStructs[row].tbodyEl);
  496. rowNode.appendChild(skeletonEl);
  497. });
  498. };
  499. return DayGridMirrorRenderer;
  500. }(DayGridEventRenderer));
  501. var EMPTY_CELL_HTML = '<td style="pointer-events:none"></td>';
  502. var DayGridFillRenderer = /** @class */ (function (_super) {
  503. __extends(DayGridFillRenderer, _super);
  504. function DayGridFillRenderer(dayGrid) {
  505. var _this = _super.call(this) || this;
  506. _this.fillSegTag = 'td'; // override the default tag name
  507. _this.dayGrid = dayGrid;
  508. return _this;
  509. }
  510. DayGridFillRenderer.prototype.renderSegs = function (type, context, segs) {
  511. // don't render timed background events
  512. if (type === 'bgEvent') {
  513. segs = segs.filter(function (seg) {
  514. return seg.eventRange.def.allDay;
  515. });
  516. }
  517. _super.prototype.renderSegs.call(this, type, context, segs);
  518. };
  519. DayGridFillRenderer.prototype.attachSegs = function (type, segs) {
  520. var els = [];
  521. var i;
  522. var seg;
  523. var skeletonEl;
  524. for (i = 0; i < segs.length; i++) {
  525. seg = segs[i];
  526. skeletonEl = this.renderFillRow(type, seg);
  527. this.dayGrid.rowEls[seg.row].appendChild(skeletonEl);
  528. els.push(skeletonEl);
  529. }
  530. return els;
  531. };
  532. // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.
  533. DayGridFillRenderer.prototype.renderFillRow = function (type, seg) {
  534. var dayGrid = this.dayGrid;
  535. var isRtl = this.context.isRtl;
  536. var colCnt = dayGrid.colCnt;
  537. var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
  538. var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
  539. var startCol = leftCol;
  540. var endCol = rightCol + 1;
  541. var className;
  542. var skeletonEl;
  543. var trEl;
  544. if (type === 'businessHours') {
  545. className = 'bgevent';
  546. }
  547. else {
  548. className = type.toLowerCase();
  549. }
  550. skeletonEl = core.htmlToElement('<div class="fc-' + className + '-skeleton">' +
  551. '<table><tr></tr></table>' +
  552. '</div>');
  553. trEl = skeletonEl.getElementsByTagName('tr')[0];
  554. if (startCol > 0) {
  555. core.appendToElement(trEl,
  556. // will create (startCol + 1) td's
  557. new Array(startCol + 1).join(EMPTY_CELL_HTML));
  558. }
  559. seg.el.colSpan = endCol - startCol;
  560. trEl.appendChild(seg.el);
  561. if (endCol < colCnt) {
  562. core.appendToElement(trEl,
  563. // will create (colCnt - endCol) td's
  564. new Array(colCnt - endCol + 1).join(EMPTY_CELL_HTML));
  565. }
  566. var introHtml = dayGrid.renderProps.renderIntroHtml();
  567. if (introHtml) {
  568. if (isRtl) {
  569. core.appendToElement(trEl, introHtml);
  570. }
  571. else {
  572. core.prependToElement(trEl, introHtml);
  573. }
  574. }
  575. return skeletonEl;
  576. };
  577. return DayGridFillRenderer;
  578. }(core.FillRenderer));
  579. var DayTile = /** @class */ (function (_super) {
  580. __extends(DayTile, _super);
  581. function DayTile(el) {
  582. var _this = _super.call(this, el) || this;
  583. var eventRenderer = _this.eventRenderer = new DayTileEventRenderer(_this);
  584. var renderFrame = _this.renderFrame = core.memoizeRendering(_this._renderFrame);
  585. _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderFrame]);
  586. _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
  587. _this.renderEventDrag = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]);
  588. _this.renderEventResize = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]);
  589. return _this;
  590. }
  591. DayTile.prototype.firstContext = function (context) {
  592. context.calendar.registerInteractiveComponent(this, {
  593. el: this.el,
  594. useEventCenter: false
  595. });
  596. };
  597. DayTile.prototype.render = function (props, context) {
  598. this.renderFrame(props.date);
  599. this.renderFgEvents(context, props.fgSegs);
  600. this.renderEventSelection(props.eventSelection);
  601. this.renderEventDrag(props.eventDragInstances);
  602. this.renderEventResize(props.eventResizeInstances);
  603. };
  604. DayTile.prototype.destroy = function () {
  605. _super.prototype.destroy.call(this);
  606. this.renderFrame.unrender(); // should unrender everything else
  607. this.context.calendar.unregisterInteractiveComponent(this);
  608. };
  609. DayTile.prototype._renderFrame = function (date) {
  610. var _a = this.context, theme = _a.theme, dateEnv = _a.dateEnv, options = _a.options;
  611. var title = dateEnv.format(date, core.createFormatter(options.dayPopoverFormat) // TODO: cache
  612. );
  613. this.el.innerHTML =
  614. '<div class="fc-header ' + theme.getClass('popoverHeader') + '">' +
  615. '<span class="fc-title">' +
  616. core.htmlEscape(title) +
  617. '</span>' +
  618. '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' +
  619. '</div>' +
  620. '<div class="fc-body ' + theme.getClass('popoverContent') + '">' +
  621. '<div class="fc-event-container"></div>' +
  622. '</div>';
  623. this.segContainerEl = this.el.querySelector('.fc-event-container');
  624. };
  625. DayTile.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
  626. var date = this.props.date; // HACK
  627. if (positionLeft < elWidth && positionTop < elHeight) {
  628. return {
  629. component: this,
  630. dateSpan: {
  631. allDay: true,
  632. range: { start: date, end: core.addDays(date, 1) }
  633. },
  634. dayEl: this.el,
  635. rect: {
  636. left: 0,
  637. top: 0,
  638. right: elWidth,
  639. bottom: elHeight
  640. },
  641. layer: 1
  642. };
  643. }
  644. };
  645. return DayTile;
  646. }(core.DateComponent));
  647. var DayTileEventRenderer = /** @class */ (function (_super) {
  648. __extends(DayTileEventRenderer, _super);
  649. function DayTileEventRenderer(dayTile) {
  650. var _this = _super.call(this) || this;
  651. _this.dayTile = dayTile;
  652. return _this;
  653. }
  654. DayTileEventRenderer.prototype.attachSegs = function (segs) {
  655. for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
  656. var seg = segs_1[_i];
  657. this.dayTile.segContainerEl.appendChild(seg.el);
  658. }
  659. };
  660. DayTileEventRenderer.prototype.detachSegs = function (segs) {
  661. for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
  662. var seg = segs_2[_i];
  663. core.removeElement(seg.el);
  664. }
  665. };
  666. return DayTileEventRenderer;
  667. }(SimpleDayGridEventRenderer));
  668. var DayBgRow = /** @class */ (function () {
  669. function DayBgRow(context) {
  670. this.context = context;
  671. }
  672. DayBgRow.prototype.renderHtml = function (props) {
  673. var parts = [];
  674. if (props.renderIntroHtml) {
  675. parts.push(props.renderIntroHtml());
  676. }
  677. for (var _i = 0, _a = props.cells; _i < _a.length; _i++) {
  678. var cell = _a[_i];
  679. parts.push(renderCellHtml(cell.date, props.dateProfile, this.context, cell.htmlAttrs));
  680. }
  681. if (!props.cells.length) {
  682. parts.push('<td class="fc-day ' + this.context.theme.getClass('widgetContent') + '"></td>');
  683. }
  684. if (this.context.options.dir === 'rtl') {
  685. parts.reverse();
  686. }
  687. return '<tr>' + parts.join('') + '</tr>';
  688. };
  689. return DayBgRow;
  690. }());
  691. function renderCellHtml(date, dateProfile, context, otherAttrs) {
  692. var dateEnv = context.dateEnv, theme = context.theme;
  693. var isDateValid = core.rangeContainsMarker(dateProfile.activeRange, date); // TODO: called too frequently. cache somehow.
  694. var classes = core.getDayClasses(date, dateProfile, context);
  695. classes.unshift('fc-day', theme.getClass('widgetContent'));
  696. return '<td class="' + classes.join(' ') + '"' +
  697. (isDateValid ?
  698. ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
  699. '') +
  700. (otherAttrs ?
  701. ' ' + otherAttrs :
  702. '') +
  703. '></td>';
  704. }
  705. var DAY_NUM_FORMAT = core.createFormatter({ day: 'numeric' });
  706. var WEEK_NUM_FORMAT = core.createFormatter({ week: 'numeric' });
  707. var DayGrid = /** @class */ (function (_super) {
  708. __extends(DayGrid, _super);
  709. function DayGrid(el, renderProps) {
  710. var _this = _super.call(this, el) || this;
  711. _this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid
  712. _this.isCellSizesDirty = false;
  713. _this.renderProps = renderProps;
  714. var eventRenderer = _this.eventRenderer = new DayGridEventRenderer(_this);
  715. var fillRenderer = _this.fillRenderer = new DayGridFillRenderer(_this);
  716. _this.mirrorRenderer = new DayGridMirrorRenderer(_this);
  717. var renderCells = _this.renderCells = core.memoizeRendering(_this._renderCells, _this._unrenderCells);
  718. _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderCells]);
  719. _this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'), [renderCells]);
  720. _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderCells]);
  721. _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderCells]);
  722. _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
  723. _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderCells]);
  724. _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderCells]);
  725. return _this;
  726. }
  727. DayGrid.prototype.render = function (props, context) {
  728. var cells = props.cells;
  729. this.rowCnt = cells.length;
  730. this.colCnt = cells[0].length;
  731. this.renderCells(cells, props.isRigid);
  732. this.renderBusinessHours(context, props.businessHourSegs);
  733. this.renderDateSelection(context, props.dateSelectionSegs);
  734. this.renderBgEvents(context, props.bgEventSegs);
  735. this.renderFgEvents(context, props.fgEventSegs);
  736. this.renderEventSelection(props.eventSelection);
  737. this.renderEventDrag(props.eventDrag);
  738. this.renderEventResize(props.eventResize);
  739. if (this.segPopoverTile) {
  740. this.updateSegPopoverTile();
  741. }
  742. };
  743. DayGrid.prototype.destroy = function () {
  744. _super.prototype.destroy.call(this);
  745. this.renderCells.unrender(); // will unrender everything else
  746. };
  747. DayGrid.prototype.getCellRange = function (row, col) {
  748. var start = this.props.cells[row][col].date;
  749. var end = core.addDays(start, 1);
  750. return { start: start, end: end };
  751. };
  752. DayGrid.prototype.updateSegPopoverTile = function (date, segs) {
  753. var ownProps = this.props;
  754. this.segPopoverTile.receiveProps({
  755. date: date || this.segPopoverTile.props.date,
  756. fgSegs: segs || this.segPopoverTile.props.fgSegs,
  757. eventSelection: ownProps.eventSelection,
  758. eventDragInstances: ownProps.eventDrag ? ownProps.eventDrag.affectedInstances : null,
  759. eventResizeInstances: ownProps.eventResize ? ownProps.eventResize.affectedInstances : null
  760. }, this.context);
  761. };
  762. /* Date Rendering
  763. ------------------------------------------------------------------------------------------------------------------*/
  764. DayGrid.prototype._renderCells = function (cells, isRigid) {
  765. var _a = this.context, calendar = _a.calendar, view = _a.view, isRtl = _a.isRtl, dateEnv = _a.dateEnv;
  766. var _b = this, rowCnt = _b.rowCnt, colCnt = _b.colCnt;
  767. var html = '';
  768. var row;
  769. var col;
  770. for (row = 0; row < rowCnt; row++) {
  771. html += this.renderDayRowHtml(row, isRigid);
  772. }
  773. this.el.innerHTML = html;
  774. this.rowEls = core.findElements(this.el, '.fc-row');
  775. this.cellEls = core.findElements(this.el, '.fc-day, .fc-disabled-day');
  776. if (isRtl) {
  777. this.cellEls.reverse();
  778. }
  779. this.rowPositions = new core.PositionCache(this.el, this.rowEls, false, true // vertical
  780. );
  781. this.colPositions = new core.PositionCache(this.el, this.cellEls.slice(0, colCnt), // only the first row
  782. true, false // horizontal
  783. );
  784. // trigger dayRender with each cell's element
  785. for (row = 0; row < rowCnt; row++) {
  786. for (col = 0; col < colCnt; col++) {
  787. calendar.publiclyTrigger('dayRender', [
  788. {
  789. date: dateEnv.toDate(cells[row][col].date),
  790. el: this.getCellEl(row, col),
  791. view: view
  792. }
  793. ]);
  794. }
  795. }
  796. this.isCellSizesDirty = true;
  797. };
  798. DayGrid.prototype._unrenderCells = function () {
  799. this.removeSegPopover();
  800. };
  801. // Generates the HTML for a single row, which is a div that wraps a table.
  802. // `row` is the row number.
  803. DayGrid.prototype.renderDayRowHtml = function (row, isRigid) {
  804. var theme = this.context.theme;
  805. var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')];
  806. if (isRigid) {
  807. classes.push('fc-rigid');
  808. }
  809. var bgRow = new DayBgRow(this.context);
  810. return '' +
  811. '<div class="' + classes.join(' ') + '">' +
  812. '<div class="fc-bg">' +
  813. '<table class="' + theme.getClass('tableGrid') + '">' +
  814. bgRow.renderHtml({
  815. cells: this.props.cells[row],
  816. dateProfile: this.props.dateProfile,
  817. renderIntroHtml: this.renderProps.renderBgIntroHtml
  818. }) +
  819. '</table>' +
  820. '</div>' +
  821. '<div class="fc-content-skeleton">' +
  822. '<table>' +
  823. (this.getIsNumbersVisible() ?
  824. '<thead>' +
  825. this.renderNumberTrHtml(row) +
  826. '</thead>' :
  827. '') +
  828. '</table>' +
  829. '</div>' +
  830. '</div>';
  831. };
  832. DayGrid.prototype.getIsNumbersVisible = function () {
  833. return this.getIsDayNumbersVisible() ||
  834. this.renderProps.cellWeekNumbersVisible ||
  835. this.renderProps.colWeekNumbersVisible;
  836. };
  837. DayGrid.prototype.getIsDayNumbersVisible = function () {
  838. return this.rowCnt > 1;
  839. };
  840. /* Grid Number Rendering
  841. ------------------------------------------------------------------------------------------------------------------*/
  842. DayGrid.prototype.renderNumberTrHtml = function (row) {
  843. var isRtl = this.context.isRtl;
  844. var intro = this.renderProps.renderNumberIntroHtml(row, this);
  845. return '' +
  846. '<tr>' +
  847. (isRtl ? '' : intro) +
  848. this.renderNumberCellsHtml(row) +
  849. (isRtl ? intro : '') +
  850. '</tr>';
  851. };
  852. DayGrid.prototype.renderNumberCellsHtml = function (row) {
  853. var htmls = [];
  854. var col;
  855. var date;
  856. for (col = 0; col < this.colCnt; col++) {
  857. date = this.props.cells[row][col].date;
  858. htmls.push(this.renderNumberCellHtml(date));
  859. }
  860. if (this.context.isRtl) {
  861. htmls.reverse();
  862. }
  863. return htmls.join('');
  864. };
  865. // Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton.
  866. // The number row will only exist if either day numbers or week numbers are turned on.
  867. DayGrid.prototype.renderNumberCellHtml = function (date) {
  868. var _a = this.context, dateEnv = _a.dateEnv, options = _a.options;
  869. var html = '';
  870. var isDateValid = core.rangeContainsMarker(this.props.dateProfile.activeRange, date); // TODO: called too frequently. cache somehow.
  871. var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid;
  872. var classes;
  873. var weekCalcFirstDow;
  874. if (!isDayNumberVisible && !this.renderProps.cellWeekNumbersVisible) {
  875. // no numbers in day cell (week number must be along the side)
  876. return '<td></td>'; // will create an empty space above events :(
  877. }
  878. classes = core.getDayClasses(date, this.props.dateProfile, this.context);
  879. classes.unshift('fc-day-top');
  880. if (this.renderProps.cellWeekNumbersVisible) {
  881. weekCalcFirstDow = dateEnv.weekDow;
  882. }
  883. html += '<td class="' + classes.join(' ') + '"' +
  884. (isDateValid ?
  885. ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
  886. '') +
  887. '>';
  888. if (this.renderProps.cellWeekNumbersVisible && (date.getUTCDay() === weekCalcFirstDow)) {
  889. html += core.buildGotoAnchorHtml(options, dateEnv, { date: date, type: 'week' }, { 'class': 'fc-week-number' }, dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML
  890. );
  891. }
  892. if (isDayNumberVisible) {
  893. html += core.buildGotoAnchorHtml(options, dateEnv, date, { 'class': 'fc-day-number' }, dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML
  894. );
  895. }
  896. html += '</td>';
  897. return html;
  898. };
  899. /* Sizing
  900. ------------------------------------------------------------------------------------------------------------------*/
  901. DayGrid.prototype.updateSize = function (isResize) {
  902. var calendar = this.context.calendar;
  903. var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
  904. if (isResize ||
  905. this.isCellSizesDirty ||
  906. calendar.isEventsUpdated // hack
  907. ) {
  908. this.buildPositionCaches();
  909. this.isCellSizesDirty = false;
  910. }
  911. fillRenderer.computeSizes(isResize);
  912. eventRenderer.computeSizes(isResize);
  913. mirrorRenderer.computeSizes(isResize);
  914. fillRenderer.assignSizes(isResize);
  915. eventRenderer.assignSizes(isResize);
  916. mirrorRenderer.assignSizes(isResize);
  917. };
  918. DayGrid.prototype.buildPositionCaches = function () {
  919. this.buildColPositions();
  920. this.buildRowPositions();
  921. };
  922. DayGrid.prototype.buildColPositions = function () {
  923. this.colPositions.build();
  924. };
  925. DayGrid.prototype.buildRowPositions = function () {
  926. this.rowPositions.build();
  927. this.rowPositions.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack
  928. };
  929. /* Hit System
  930. ------------------------------------------------------------------------------------------------------------------*/
  931. DayGrid.prototype.positionToHit = function (leftPosition, topPosition) {
  932. var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions;
  933. var col = colPositions.leftToIndex(leftPosition);
  934. var row = rowPositions.topToIndex(topPosition);
  935. if (row != null && col != null) {
  936. return {
  937. row: row,
  938. col: col,
  939. dateSpan: {
  940. range: this.getCellRange(row, col),
  941. allDay: true
  942. },
  943. dayEl: this.getCellEl(row, col),
  944. relativeRect: {
  945. left: colPositions.lefts[col],
  946. right: colPositions.rights[col],
  947. top: rowPositions.tops[row],
  948. bottom: rowPositions.bottoms[row]
  949. }
  950. };
  951. }
  952. };
  953. /* Cell System
  954. ------------------------------------------------------------------------------------------------------------------*/
  955. // FYI: the first column is the leftmost column, regardless of date
  956. DayGrid.prototype.getCellEl = function (row, col) {
  957. return this.cellEls[row * this.colCnt + col];
  958. };
  959. /* Event Drag Visualization
  960. ------------------------------------------------------------------------------------------------------------------*/
  961. DayGrid.prototype._renderEventDrag = function (state) {
  962. if (state) {
  963. this.eventRenderer.hideByHash(state.affectedInstances);
  964. this.fillRenderer.renderSegs('highlight', this.context, state.segs);
  965. }
  966. };
  967. DayGrid.prototype._unrenderEventDrag = function (state) {
  968. if (state) {
  969. this.eventRenderer.showByHash(state.affectedInstances);
  970. this.fillRenderer.unrender('highlight', this.context);
  971. }
  972. };
  973. /* Event Resize Visualization
  974. ------------------------------------------------------------------------------------------------------------------*/
  975. DayGrid.prototype._renderEventResize = function (state) {
  976. if (state) {
  977. this.eventRenderer.hideByHash(state.affectedInstances);
  978. this.fillRenderer.renderSegs('highlight', this.context, state.segs);
  979. this.mirrorRenderer.renderSegs(this.context, state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
  980. }
  981. };
  982. DayGrid.prototype._unrenderEventResize = function (state) {
  983. if (state) {
  984. this.eventRenderer.showByHash(state.affectedInstances);
  985. this.fillRenderer.unrender('highlight', this.context);
  986. this.mirrorRenderer.unrender(this.context, state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
  987. }
  988. };
  989. /* More+ Link Popover
  990. ------------------------------------------------------------------------------------------------------------------*/
  991. DayGrid.prototype.removeSegPopover = function () {
  992. if (this.segPopover) {
  993. this.segPopover.hide(); // in handler, will call segPopover's removeElement
  994. }
  995. };
  996. // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid.
  997. // `levelLimit` can be false (don't limit), a number, or true (should be computed).
  998. DayGrid.prototype.limitRows = function (levelLimit) {
  999. var rowStructs = this.eventRenderer.rowStructs || [];
  1000. var row; // row #
  1001. var rowLevelLimit;
  1002. for (row = 0; row < rowStructs.length; row++) {
  1003. this.unlimitRow(row);
  1004. if (!levelLimit) {
  1005. rowLevelLimit = false;
  1006. }
  1007. else if (typeof levelLimit === 'number') {
  1008. rowLevelLimit = levelLimit;
  1009. }
  1010. else {
  1011. rowLevelLimit = this.computeRowLevelLimit(row);
  1012. }
  1013. if (rowLevelLimit !== false) {
  1014. this.limitRow(row, rowLevelLimit);
  1015. }
  1016. }
  1017. };
  1018. // Computes the number of levels a row will accomodate without going outside its bounds.
  1019. // Assumes the row is "rigid" (maintains a constant height regardless of what is inside).
  1020. // `row` is the row number.
  1021. DayGrid.prototype.computeRowLevelLimit = function (row) {
  1022. var rowEl = this.rowEls[row]; // the containing "fake" row div
  1023. var rowBottom = rowEl.getBoundingClientRect().bottom; // relative to viewport!
  1024. var trEls = core.findChildren(this.eventRenderer.rowStructs[row].tbodyEl);
  1025. var i;
  1026. var trEl;
  1027. // Reveal one level <tr> at a time and stop when we find one out of bounds
  1028. for (i = 0; i < trEls.length; i++) {
  1029. trEl = trEls[i];
  1030. trEl.classList.remove('fc-limited'); // reset to original state (reveal)
  1031. if (trEl.getBoundingClientRect().bottom > rowBottom) {
  1032. return i;
  1033. }
  1034. }
  1035. return false; // should not limit at all
  1036. };
  1037. // Limits the given grid row to the maximum number of levels and injects "more" links if necessary.
  1038. // `row` is the row number.
  1039. // `levelLimit` is a number for the maximum (inclusive) number of levels allowed.
  1040. DayGrid.prototype.limitRow = function (row, levelLimit) {
  1041. var _this = this;
  1042. var colCnt = this.colCnt;
  1043. var isRtl = this.context.isRtl;
  1044. var rowStruct = this.eventRenderer.rowStructs[row];
  1045. var moreNodes = []; // array of "more" <a> links and <td> DOM nodes
  1046. var col = 0; // col #, left-to-right (not chronologically)
  1047. var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right
  1048. var cellMatrix; // a matrix (by level, then column) of all <td> elements in the row
  1049. var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes
  1050. var i;
  1051. var seg;
  1052. var segsBelow; // array of segment objects below `seg` in the current `col`
  1053. var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies
  1054. var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)
  1055. var td;
  1056. var rowSpan;
  1057. var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell
  1058. var j;
  1059. var moreTd;
  1060. var moreWrap;
  1061. var moreLink;
  1062. // Iterates through empty level cells and places "more" links inside if need be
  1063. var emptyCellsUntil = function (endCol) {
  1064. while (col < endCol) {
  1065. segsBelow = _this.getCellSegs(row, col, levelLimit);
  1066. if (segsBelow.length) {
  1067. td = cellMatrix[levelLimit - 1][col];
  1068. moreLink = _this.renderMoreLink(row, col, segsBelow);
  1069. moreWrap = core.createElement('div', null, moreLink);
  1070. td.appendChild(moreWrap);
  1071. moreNodes.push(moreWrap);
  1072. }
  1073. col++;
  1074. }
  1075. };
  1076. if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?
  1077. levelSegs = rowStruct.segLevels[levelLimit - 1];
  1078. cellMatrix = rowStruct.cellMatrix;
  1079. limitedNodes = core.findChildren(rowStruct.tbodyEl).slice(levelLimit); // get level <tr> elements past the limit
  1080. limitedNodes.forEach(function (node) {
  1081. node.classList.add('fc-limited'); // hide elements and get a simple DOM-nodes array
  1082. });
  1083. // iterate though segments in the last allowable level
  1084. for (i = 0; i < levelSegs.length; i++) {
  1085. seg = levelSegs[i];
  1086. var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol;
  1087. var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol;
  1088. emptyCellsUntil(leftCol); // process empty cells before the segment
  1089. // determine *all* segments below `seg` that occupy the same columns
  1090. colSegsBelow = [];
  1091. totalSegsBelow = 0;
  1092. while (col <= rightCol) {
  1093. segsBelow = this.getCellSegs(row, col, levelLimit);
  1094. colSegsBelow.push(segsBelow);
  1095. totalSegsBelow += segsBelow.length;
  1096. col++;
  1097. }
  1098. if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links?
  1099. td = cellMatrix[levelLimit - 1][leftCol]; // the segment's parent cell
  1100. rowSpan = td.rowSpan || 1;
  1101. segMoreNodes = [];
  1102. // make a replacement <td> for each column the segment occupies. will be one for each colspan
  1103. for (j = 0; j < colSegsBelow.length; j++) {
  1104. moreTd = core.createElement('td', { className: 'fc-more-cell', rowSpan: rowSpan });
  1105. segsBelow = colSegsBelow[j];
  1106. moreLink = this.renderMoreLink(row, leftCol + j, [seg].concat(segsBelow) // count seg as hidden too
  1107. );
  1108. moreWrap = core.createElement('div', null, moreLink);
  1109. moreTd.appendChild(moreWrap);
  1110. segMoreNodes.push(moreTd);
  1111. moreNodes.push(moreTd);
  1112. }
  1113. td.classList.add('fc-limited');
  1114. core.insertAfterElement(td, segMoreNodes);
  1115. limitedNodes.push(td);
  1116. }
  1117. }
  1118. emptyCellsUntil(this.colCnt); // finish off the level
  1119. rowStruct.moreEls = moreNodes; // for easy undoing later
  1120. rowStruct.limitedEls = limitedNodes; // for easy undoing later
  1121. }
  1122. };
  1123. // Reveals all levels and removes all "more"-related elements for a grid's row.
  1124. // `row` is a row number.
  1125. DayGrid.prototype.unlimitRow = function (row) {
  1126. var rowStruct = this.eventRenderer.rowStructs[row];
  1127. if (rowStruct.moreEls) {
  1128. rowStruct.moreEls.forEach(core.removeElement);
  1129. rowStruct.moreEls = null;
  1130. }
  1131. if (rowStruct.limitedEls) {
  1132. rowStruct.limitedEls.forEach(function (limitedEl) {
  1133. limitedEl.classList.remove('fc-limited');
  1134. });
  1135. rowStruct.limitedEls = null;
  1136. }
  1137. };
  1138. // Renders an <a> element that represents hidden event element for a cell.
  1139. // Responsible for attaching click handler as well.
  1140. DayGrid.prototype.renderMoreLink = function (row, col, hiddenSegs) {
  1141. var _this = this;
  1142. var _a = this.context, calendar = _a.calendar, view = _a.view, dateEnv = _a.dateEnv, options = _a.options, isRtl = _a.isRtl;
  1143. var a = core.createElement('a', { className: 'fc-more' });
  1144. a.innerText = this.getMoreLinkText(hiddenSegs.length);
  1145. a.addEventListener('click', function (ev) {
  1146. var clickOption = options.eventLimitClick;
  1147. var _col = isRtl ? _this.colCnt - col - 1 : col; // HACK: props.cells has different dir system?
  1148. var date = _this.props.cells[row][_col].date;
  1149. var moreEl = ev.currentTarget;
  1150. var dayEl = _this.getCellEl(row, col);
  1151. var allSegs = _this.getCellSegs(row, col);
  1152. // rescope the segments to be within the cell's date
  1153. var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
  1154. var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);
  1155. if (typeof clickOption === 'function') {
  1156. // the returned value can be an atomic option
  1157. clickOption = calendar.publiclyTrigger('eventLimitClick', [
  1158. {
  1159. date: dateEnv.toDate(date),
  1160. allDay: true,
  1161. dayEl: dayEl,
  1162. moreEl: moreEl,
  1163. segs: reslicedAllSegs,
  1164. hiddenSegs: reslicedHiddenSegs,
  1165. jsEvent: ev,
  1166. view: view
  1167. }
  1168. ]);
  1169. }
  1170. if (clickOption === 'popover') {
  1171. _this.showSegPopover(row, col, moreEl, reslicedAllSegs);
  1172. }
  1173. else if (typeof clickOption === 'string') { // a view name
  1174. calendar.zoomTo(date, clickOption);
  1175. }
  1176. });
  1177. return a;
  1178. };
  1179. // Reveals the popover that displays all events within a cell
  1180. DayGrid.prototype.showSegPopover = function (row, col, moreLink, segs) {
  1181. var _this = this;
  1182. var _a = this.context, calendar = _a.calendar, view = _a.view, theme = _a.theme, isRtl = _a.isRtl;
  1183. var _col = isRtl ? this.colCnt - col - 1 : col; // HACK: props.cells has different dir system?
  1184. var moreWrap = moreLink.parentNode; // the <div> wrapper around the <a>
  1185. var topEl; // the element we want to match the top coordinate of
  1186. var options;
  1187. if (this.rowCnt === 1) {
  1188. topEl = view.el; // will cause the popover to cover any sort of header
  1189. }
  1190. else {
  1191. topEl = this.rowEls[row]; // will align with top of row
  1192. }
  1193. options = {
  1194. className: 'fc-more-popover ' + theme.getClass('popover'),
  1195. parentEl: view.el,
  1196. top: core.computeRect(topEl).top,
  1197. autoHide: true,
  1198. content: function (el) {
  1199. _this.segPopoverTile = new DayTile(el);
  1200. _this.updateSegPopoverTile(_this.props.cells[row][_col].date, segs);
  1201. },
  1202. hide: function () {
  1203. _this.segPopoverTile.destroy();
  1204. _this.segPopoverTile = null;
  1205. _this.segPopover.destroy();
  1206. _this.segPopover = null;
  1207. }
  1208. };
  1209. // Determine horizontal coordinate.
  1210. // We use the moreWrap instead of the <td> to avoid border confusion.
  1211. if (isRtl) {
  1212. options.right = core.computeRect(moreWrap).right + 1; // +1 to be over cell border
  1213. }
  1214. else {
  1215. options.left = core.computeRect(moreWrap).left - 1; // -1 to be over cell border
  1216. }
  1217. this.segPopover = new Popover(options);
  1218. this.segPopover.show();
  1219. calendar.releaseAfterSizingTriggers(); // hack for eventPositioned
  1220. };
  1221. // Given the events within an array of segment objects, reslice them to be in a single day
  1222. DayGrid.prototype.resliceDaySegs = function (segs, dayDate) {
  1223. var dayStart = dayDate;
  1224. var dayEnd = core.addDays(dayStart, 1);
  1225. var dayRange = { start: dayStart, end: dayEnd };
  1226. var newSegs = [];
  1227. for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
  1228. var seg = segs_1[_i];
  1229. var eventRange = seg.eventRange;
  1230. var origRange = eventRange.range;
  1231. var slicedRange = core.intersectRanges(origRange, dayRange);
  1232. if (slicedRange) {
  1233. newSegs.push(__assign({}, seg, { eventRange: {
  1234. def: eventRange.def,
  1235. ui: __assign({}, eventRange.ui, { durationEditable: false }),
  1236. instance: eventRange.instance,
  1237. range: slicedRange
  1238. }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() }));
  1239. }
  1240. }
  1241. return newSegs;
  1242. };
  1243. // Generates the text that should be inside a "more" link, given the number of events it represents
  1244. DayGrid.prototype.getMoreLinkText = function (num) {
  1245. var opt = this.context.options.eventLimitText;
  1246. if (typeof opt === 'function') {
  1247. return opt(num);
  1248. }
  1249. else {
  1250. return '+' + num + ' ' + opt;
  1251. }
  1252. };
  1253. // Returns segments within a given cell.
  1254. // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.
  1255. DayGrid.prototype.getCellSegs = function (row, col, startLevel) {
  1256. var segMatrix = this.eventRenderer.rowStructs[row].segMatrix;
  1257. var level = startLevel || 0;
  1258. var segs = [];
  1259. var seg;
  1260. while (level < segMatrix.length) {
  1261. seg = segMatrix[level][col];
  1262. if (seg) {
  1263. segs.push(seg);
  1264. }
  1265. level++;
  1266. }
  1267. return segs;
  1268. };
  1269. return DayGrid;
  1270. }(core.DateComponent));
  1271. var WEEK_NUM_FORMAT$1 = core.createFormatter({ week: 'numeric' });
  1272. /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
  1273. ----------------------------------------------------------------------------------------------------------------------*/
  1274. // It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.
  1275. // It is responsible for managing width/height.
  1276. var AbstractDayGridView = /** @class */ (function (_super) {
  1277. __extends(AbstractDayGridView, _super);
  1278. function AbstractDayGridView() {
  1279. var _this = _super !== null && _super.apply(this, arguments) || this;
  1280. _this.processOptions = core.memoize(_this._processOptions);
  1281. _this.renderSkeleton = core.memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
  1282. /* Header Rendering
  1283. ------------------------------------------------------------------------------------------------------------------*/
  1284. // Generates the HTML that will go before the day-of week header cells
  1285. _this.renderHeadIntroHtml = function () {
  1286. var _a = _this.context, theme = _a.theme, options = _a.options;
  1287. if (_this.colWeekNumbersVisible) {
  1288. return '' +
  1289. '<th class="fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.weekNumberStyleAttr() + '>' +
  1290. '<span>' + // needed for matchCellWidths
  1291. core.htmlEscape(options.weekLabel) +
  1292. '</span>' +
  1293. '</th>';
  1294. }
  1295. return '';
  1296. };
  1297. /* Day Grid Rendering
  1298. ------------------------------------------------------------------------------------------------------------------*/
  1299. // Generates the HTML that will go before content-skeleton cells that display the day/week numbers
  1300. _this.renderDayGridNumberIntroHtml = function (row, dayGrid) {
  1301. var _a = _this.context, options = _a.options, dateEnv = _a.dateEnv;
  1302. var weekStart = dayGrid.props.cells[row][0].date;
  1303. if (_this.colWeekNumbersVisible) {
  1304. return '' +
  1305. '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '>' +
  1306. core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
  1307. options, dateEnv, { date: weekStart, type: 'week', forceOff: dayGrid.colCnt === 1 }, dateEnv.format(weekStart, WEEK_NUM_FORMAT$1) // inner HTML
  1308. ) +
  1309. '</td>';
  1310. }
  1311. return '';
  1312. };
  1313. // Generates the HTML that goes before the day bg cells for each day-row
  1314. _this.renderDayGridBgIntroHtml = function () {
  1315. var theme = _this.context.theme;
  1316. if (_this.colWeekNumbersVisible) {
  1317. return '<td class="fc-week-number ' + theme.getClass('widgetContent') + '" ' + _this.weekNumberStyleAttr() + '></td>';
  1318. }
  1319. return '';
  1320. };
  1321. // Generates the HTML that goes before every other type of row generated by DayGrid.
  1322. // Affects mirror-skeleton and highlight-skeleton rows.
  1323. _this.renderDayGridIntroHtml = function () {
  1324. if (_this.colWeekNumbersVisible) {
  1325. return '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '></td>';
  1326. }
  1327. return '';
  1328. };
  1329. return _this;
  1330. }
  1331. AbstractDayGridView.prototype._processOptions = function (options) {
  1332. if (options.weekNumbers) {
  1333. if (options.weekNumbersWithinDays) {
  1334. this.cellWeekNumbersVisible = true;
  1335. this.colWeekNumbersVisible = false;
  1336. }
  1337. else {
  1338. this.cellWeekNumbersVisible = false;
  1339. this.colWeekNumbersVisible = true;
  1340. }
  1341. }
  1342. else {
  1343. this.colWeekNumbersVisible = false;
  1344. this.cellWeekNumbersVisible = false;
  1345. }
  1346. };
  1347. AbstractDayGridView.prototype.render = function (props, context) {
  1348. _super.prototype.render.call(this, props, context);
  1349. this.processOptions(context.options);
  1350. this.renderSkeleton(context);
  1351. };
  1352. AbstractDayGridView.prototype.destroy = function () {
  1353. _super.prototype.destroy.call(this);
  1354. this.renderSkeleton.unrender();
  1355. };
  1356. AbstractDayGridView.prototype._renderSkeleton = function (context) {
  1357. this.el.classList.add('fc-dayGrid-view');
  1358. this.el.innerHTML = this.renderSkeletonHtml();
  1359. this.scroller = new core.ScrollComponent('hidden', // overflow x
  1360. 'auto' // overflow y
  1361. );
  1362. var dayGridContainerEl = this.scroller.el;
  1363. this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl);
  1364. dayGridContainerEl.classList.add('fc-day-grid-container');
  1365. var dayGridEl = core.createElement('div', { className: 'fc-day-grid' });
  1366. dayGridContainerEl.appendChild(dayGridEl);
  1367. this.dayGrid = new DayGrid(dayGridEl, {
  1368. renderNumberIntroHtml: this.renderDayGridNumberIntroHtml,
  1369. renderBgIntroHtml: this.renderDayGridBgIntroHtml,
  1370. renderIntroHtml: this.renderDayGridIntroHtml,
  1371. colWeekNumbersVisible: this.colWeekNumbersVisible,
  1372. cellWeekNumbersVisible: this.cellWeekNumbersVisible
  1373. });
  1374. };
  1375. AbstractDayGridView.prototype._unrenderSkeleton = function () {
  1376. this.el.classList.remove('fc-dayGrid-view');
  1377. this.dayGrid.destroy();
  1378. this.scroller.destroy();
  1379. };
  1380. // Builds the HTML skeleton for the view.
  1381. // The day-grid component will render inside of a container defined by this HTML.
  1382. AbstractDayGridView.prototype.renderSkeletonHtml = function () {
  1383. var _a = this.context, theme = _a.theme, options = _a.options;
  1384. return '' +
  1385. '<table class="' + theme.getClass('tableGrid') + '">' +
  1386. (options.columnHeader ?
  1387. '<thead class="fc-head">' +
  1388. '<tr>' +
  1389. '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
  1390. '</tr>' +
  1391. '</thead>' :
  1392. '') +
  1393. '<tbody class="fc-body">' +
  1394. '<tr>' +
  1395. '<td class="' + theme.getClass('widgetContent') + '"></td>' +
  1396. '</tr>' +
  1397. '</tbody>' +
  1398. '</table>';
  1399. };
  1400. // Generates an HTML attribute string for setting the width of the week number column, if it is known
  1401. AbstractDayGridView.prototype.weekNumberStyleAttr = function () {
  1402. if (this.weekNumberWidth != null) {
  1403. return 'style="width:' + this.weekNumberWidth + 'px"';
  1404. }
  1405. return '';
  1406. };
  1407. // Determines whether each row should have a constant height
  1408. AbstractDayGridView.prototype.hasRigidRows = function () {
  1409. var eventLimit = this.context.options.eventLimit;
  1410. return eventLimit && typeof eventLimit !== 'number';
  1411. };
  1412. /* Dimensions
  1413. ------------------------------------------------------------------------------------------------------------------*/
  1414. AbstractDayGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
  1415. _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first
  1416. this.dayGrid.updateSize(isResize);
  1417. };
  1418. // Refreshes the horizontal dimensions of the view
  1419. AbstractDayGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
  1420. var dayGrid = this.dayGrid;
  1421. var eventLimit = this.context.options.eventLimit;
  1422. var headRowEl = this.header ? this.header.el : null; // HACK
  1423. var scrollerHeight;
  1424. var scrollbarWidths;
  1425. // hack to give the view some height prior to dayGrid's columns being rendered
  1426. // TODO: separate setting height from scroller VS dayGrid.
  1427. if (!dayGrid.rowEls) {
  1428. if (!isAuto) {
  1429. scrollerHeight = this.computeScrollerHeight(viewHeight);
  1430. this.scroller.setHeight(scrollerHeight);
  1431. }
  1432. return;
  1433. }
  1434. if (this.colWeekNumbersVisible) {
  1435. // Make sure all week number cells running down the side have the same width.
  1436. this.weekNumberWidth = core.matchCellWidths(core.findElements(this.el, '.fc-week-number'));
  1437. }
  1438. // reset all heights to be natural
  1439. this.scroller.clear();
  1440. if (headRowEl) {
  1441. core.uncompensateScroll(headRowEl);
  1442. }
  1443. dayGrid.removeSegPopover(); // kill the "more" popover if displayed
  1444. // is the event limit a constant level number?
  1445. if (eventLimit && typeof eventLimit === 'number') {
  1446. dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
  1447. }
  1448. // distribute the height to the rows
  1449. // (viewHeight is a "recommended" value if isAuto)
  1450. scrollerHeight = this.computeScrollerHeight(viewHeight);
  1451. this.setGridHeight(scrollerHeight, isAuto);
  1452. // is the event limit dynamically calculated?
  1453. if (eventLimit && typeof eventLimit !== 'number') {
  1454. dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
  1455. }
  1456. if (!isAuto) { // should we force dimensions of the scroll container?
  1457. this.scroller.setHeight(scrollerHeight);
  1458. scrollbarWidths = this.scroller.getScrollbarWidths();
  1459. if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
  1460. if (headRowEl) {
  1461. core.compensateScroll(headRowEl, scrollbarWidths);
  1462. }
  1463. // doing the scrollbar compensation might have created text overflow which created more height. redo
  1464. scrollerHeight = this.computeScrollerHeight(viewHeight);
  1465. this.scroller.setHeight(scrollerHeight);
  1466. }
  1467. // guarantees the same scrollbar widths
  1468. this.scroller.lockOverflow(scrollbarWidths);
  1469. }
  1470. };
  1471. // given a desired total height of the view, returns what the height of the scroller should be
  1472. AbstractDayGridView.prototype.computeScrollerHeight = function (viewHeight) {
  1473. return viewHeight -
  1474. core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
  1475. };
  1476. // Sets the height of just the DayGrid component in this view
  1477. AbstractDayGridView.prototype.setGridHeight = function (height, isAuto) {
  1478. if (this.context.options.monthMode) {
  1479. // if auto, make the height of each row the height that it would be if there were 6 weeks
  1480. if (isAuto) {
  1481. height *= this.dayGrid.rowCnt / 6;
  1482. }
  1483. core.distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows
  1484. }
  1485. else {
  1486. if (isAuto) {
  1487. core.undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding
  1488. }
  1489. else {
  1490. core.distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows
  1491. }
  1492. }
  1493. };
  1494. /* Scroll
  1495. ------------------------------------------------------------------------------------------------------------------*/
  1496. AbstractDayGridView.prototype.computeDateScroll = function (duration) {
  1497. return { top: 0 };
  1498. };
  1499. AbstractDayGridView.prototype.queryDateScroll = function () {
  1500. return { top: this.scroller.getScrollTop() };
  1501. };
  1502. AbstractDayGridView.prototype.applyDateScroll = function (scroll) {
  1503. if (scroll.top !== undefined) {
  1504. this.scroller.setScrollTop(scroll.top);
  1505. }
  1506. };
  1507. return AbstractDayGridView;
  1508. }(core.View));
  1509. AbstractDayGridView.prototype.dateProfileGeneratorClass = DayGridDateProfileGenerator;
  1510. var SimpleDayGrid = /** @class */ (function (_super) {
  1511. __extends(SimpleDayGrid, _super);
  1512. function SimpleDayGrid(dayGrid) {
  1513. var _this = _super.call(this, dayGrid.el) || this;
  1514. _this.slicer = new DayGridSlicer();
  1515. _this.dayGrid = dayGrid;
  1516. return _this;
  1517. }
  1518. SimpleDayGrid.prototype.firstContext = function (context) {
  1519. context.calendar.registerInteractiveComponent(this, { el: this.dayGrid.el });
  1520. };
  1521. SimpleDayGrid.prototype.destroy = function () {
  1522. _super.prototype.destroy.call(this);
  1523. this.context.calendar.unregisterInteractiveComponent(this);
  1524. };
  1525. SimpleDayGrid.prototype.render = function (props, context) {
  1526. var dayGrid = this.dayGrid;
  1527. var dateProfile = props.dateProfile, dayTable = props.dayTable;
  1528. dayGrid.receiveContext(context); // hack because context is used in sliceProps
  1529. dayGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, props.nextDayThreshold, context.calendar, dayGrid, dayTable), { dateProfile: dateProfile, cells: dayTable.cells, isRigid: props.isRigid }), context);
  1530. };
  1531. SimpleDayGrid.prototype.buildPositionCaches = function () {
  1532. this.dayGrid.buildPositionCaches();
  1533. };
  1534. SimpleDayGrid.prototype.queryHit = function (positionLeft, positionTop) {
  1535. var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop);
  1536. if (rawHit) {
  1537. return {
  1538. component: this.dayGrid,
  1539. dateSpan: rawHit.dateSpan,
  1540. dayEl: rawHit.dayEl,
  1541. rect: {
  1542. left: rawHit.relativeRect.left,
  1543. right: rawHit.relativeRect.right,
  1544. top: rawHit.relativeRect.top,
  1545. bottom: rawHit.relativeRect.bottom
  1546. },
  1547. layer: 0
  1548. };
  1549. }
  1550. };
  1551. return SimpleDayGrid;
  1552. }(core.DateComponent));
  1553. var DayGridSlicer = /** @class */ (function (_super) {
  1554. __extends(DayGridSlicer, _super);
  1555. function DayGridSlicer() {
  1556. return _super !== null && _super.apply(this, arguments) || this;
  1557. }
  1558. DayGridSlicer.prototype.sliceRange = function (dateRange, dayTable) {
  1559. return dayTable.sliceRange(dateRange);
  1560. };
  1561. return DayGridSlicer;
  1562. }(core.Slicer));
  1563. var DayGridView = /** @class */ (function (_super) {
  1564. __extends(DayGridView, _super);
  1565. function DayGridView() {
  1566. var _this = _super !== null && _super.apply(this, arguments) || this;
  1567. _this.buildDayTable = core.memoize(buildDayTable);
  1568. return _this;
  1569. }
  1570. DayGridView.prototype.render = function (props, context) {
  1571. _super.prototype.render.call(this, props, context); // will call _renderSkeleton/_unrenderSkeleton
  1572. var dateProfile = this.props.dateProfile;
  1573. var dayTable = this.dayTable =
  1574. this.buildDayTable(dateProfile, props.dateProfileGenerator);
  1575. if (this.header) {
  1576. this.header.receiveProps({
  1577. dateProfile: dateProfile,
  1578. dates: dayTable.headerDates,
  1579. datesRepDistinctDays: dayTable.rowCnt === 1,
  1580. renderIntroHtml: this.renderHeadIntroHtml
  1581. }, context);
  1582. }
  1583. this.simpleDayGrid.receiveProps({
  1584. dateProfile: dateProfile,
  1585. dayTable: dayTable,
  1586. businessHours: props.businessHours,
  1587. dateSelection: props.dateSelection,
  1588. eventStore: props.eventStore,
  1589. eventUiBases: props.eventUiBases,
  1590. eventSelection: props.eventSelection,
  1591. eventDrag: props.eventDrag,
  1592. eventResize: props.eventResize,
  1593. isRigid: this.hasRigidRows(),
  1594. nextDayThreshold: this.context.nextDayThreshold
  1595. }, context);
  1596. };
  1597. DayGridView.prototype._renderSkeleton = function (context) {
  1598. _super.prototype._renderSkeleton.call(this, context);
  1599. if (context.options.columnHeader) {
  1600. this.header = new core.DayHeader(this.el.querySelector('.fc-head-container'));
  1601. }
  1602. this.simpleDayGrid = new SimpleDayGrid(this.dayGrid);
  1603. };
  1604. DayGridView.prototype._unrenderSkeleton = function () {
  1605. _super.prototype._unrenderSkeleton.call(this);
  1606. if (this.header) {
  1607. this.header.destroy();
  1608. }
  1609. this.simpleDayGrid.destroy();
  1610. };
  1611. return DayGridView;
  1612. }(AbstractDayGridView));
  1613. function buildDayTable(dateProfile, dateProfileGenerator) {
  1614. var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator);
  1615. return new core.DayTable(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
  1616. }
  1617. var main = core.createPlugin({
  1618. defaultView: 'dayGridMonth',
  1619. views: {
  1620. dayGrid: DayGridView,
  1621. dayGridDay: {
  1622. type: 'dayGrid',
  1623. duration: { days: 1 }
  1624. },
  1625. dayGridWeek: {
  1626. type: 'dayGrid',
  1627. duration: { weeks: 1 }
  1628. },
  1629. dayGridMonth: {
  1630. type: 'dayGrid',
  1631. duration: { months: 1 },
  1632. monthMode: true,
  1633. fixedWeekCount: true
  1634. }
  1635. }
  1636. });
  1637. exports.AbstractDayGridView = AbstractDayGridView;
  1638. exports.DayBgRow = DayBgRow;
  1639. exports.DayGrid = DayGrid;
  1640. exports.DayGridSlicer = DayGridSlicer;
  1641. exports.DayGridView = DayGridView;
  1642. exports.SimpleDayGrid = SimpleDayGrid;
  1643. exports.buildBasicDayTable = buildDayTable;
  1644. exports.default = main;
  1645. Object.defineProperty(exports, '__esModule', { value: true });
  1646. }));