1/*1790294974000*/ 2/*! 3FullCalendar Core Package v4.1.0 4Docs & License: https://fullcalendar.io/ 5(c) 2019 Adam Shaw 6*/ 7(function (global, factory) { 8 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 9 typeof define === 'function' && define.amd ? define(['exports'], factory) : 10 (global = global || self, factory(global.FullCalendar = {})); 11}(this, function (exports) { 'use strict'; 12 13 // Creating 14 // ---------------------------------------------------------------------------------------------------------------- 15 var elementPropHash = { 16 className: true, 17 colSpan: true, 18 rowSpan: true 19 }; 20 var containerTagHash = { 21 '<tr': 'tbody', 22 '<td': 'tr' 23 }; 24 function createElement(tagName, attrs, content) { 25 var el = document.createElement(tagName); 26 if (attrs) { 27 for (var attrName in attrs) { 28 if (attrName === 'style') { 29 applyStyle(el, attrs[attrName]); 30 } 31 else if (elementPropHash[attrName]) { 32 el[attrName] = attrs[attrName]; 33 } 34 else { 35 el.setAttribute(attrName, attrs[attrName]); 36 } 37 } 38 } 39 if (typeof content === 'string') { 40 el.innerHTML = content; // shortcut. no need to process HTML in any way 41 } 42 else if (content != null) { 43 appendToElement(el, content); 44 } 45 return el; 46 } 47 function htmlToElement(html) { 48 html = html.trim(); 49 var container = document.createElement(computeContainerTag(html)); 50 container.innerHTML = html; 51 return container.firstChild; 52 } 53 function htmlToElements(html) { 54 return Array.prototype.slice.call(htmlToNodeList(html)); 55 } 56 function htmlToNodeList(html) { 57 html = html.trim(); 58 var container = document.createElement(computeContainerTag(html)); 59 container.innerHTML = html; 60 return container.childNodes; 61 } 62 // assumes html already trimmed and tag names are lowercase 63 function computeContainerTag(html) { 64 return containerTagHash[html.substr(0, 3) // faster than using regex 65 ] || 'div'; 66 } 67 function appendToElement(el, content) { 68 var childNodes = normalizeContent(content); 69 for (var i = 0; i < childNodes.length; i++) { 70 el.appendChild(childNodes[i]); 71 } 72 } 73 function prependToElement(parent, content) { 74 var newEls = normalizeContent(content); 75 var afterEl = parent.firstChild || null; // if no firstChild, will append to end, but that's okay, b/c there were no children 76 for (var i = 0; i < newEls.length; i++) { 77 parent.insertBefore(newEls[i], afterEl); 78 } 79 } 80 function insertAfterElement(refEl, content) { 81 var newEls = normalizeContent(content); 82 var afterEl = refEl.nextSibling || null; 83 for (var i = 0; i < newEls.length; i++) { 84 refEl.parentNode.insertBefore(newEls[i], afterEl); 85 } 86 } 87 function normalizeContent(content) { 88 var els; 89 if (typeof content === 'string') { 90 els = htmlToElements(content); 91 } 92 else if (content instanceof Node) { 93 els = [content]; 94 } 95 else { // Node[] or NodeList 96 els = Array.prototype.slice.call(content); 97 } 98 return els; 99 } 100 function removeElement(el) { 101 if (el.parentNode) { 102 el.parentNode.removeChild(el); 103 } 104 } 105 // Querying 106 // ---------------------------------------------------------------------------------------------------------------- 107 // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest 108 var matchesMethod = Element.prototype.matches || 109 Element.prototype.matchesSelector || 110 Element.prototype.msMatchesSelector; 111 var closestMethod = Element.prototype.closest || function (selector) { 112 // polyfill 113 var el = this; 114 if (!document.documentElement.contains(el)) { 115 return null; 116 } 117 do { 118 if (elementMatches(el, selector)) { 119 return el; 120 } 121 el = el.parentElement || el.parentNode; 122 } while (el !== null && el.nodeType === 1); 123 return null; 124 }; 125 function elementClosest(el, selector) { 126 return closestMethod.call(el, selector); 127 } 128 function elementMatches(el, selector) { 129 return matchesMethod.call(el, selector); 130 } 131 // accepts multiple subject els 132 // returns a real array. good for methods like forEach 133 function findElements(container, selector) { 134 var containers = container instanceof HTMLElement ? [container] : container; 135 var allMatches = []; 136 for (var i = 0; i < containers.length; i++) { 137 var matches = containers[i].querySelectorAll(selector); 138 for (var j = 0; j < matches.length; j++) { 139 allMatches.push(matches[j]); 140 } 141 } 142 return allMatches; 143 } 144 // accepts multiple subject els 145 // only queries direct child elements 146 function findChildren(parent, selector) { 147 var parents = parent instanceof HTMLElement ? [parent] : parent; 148 var allMatches = []; 149 for (var i = 0; i < parents.length; i++) { 150 var childNodes = parents[i].children; // only ever elements 151 for (var j = 0; j < childNodes.length; j++) { 152 var childNode = childNodes[j]; 153 if (!selector || elementMatches(childNode, selector)) { 154 allMatches.push(childNode); 155 } 156 } 157 } 158 return allMatches; 159 } 160 // Attributes 161 // ---------------------------------------------------------------------------------------------------------------- 162 function forceClassName(el, className, bool) { 163 if (bool) { 164 el.classList.add(className); 165 } 166 else { 167 el.classList.remove(className); 168 } 169 } 170 // Style 171 // ---------------------------------------------------------------------------------------------------------------- 172 var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i; 173 function applyStyle(el, props) { 174 for (var propName in props) { 175 applyStyleProp(el, propName, props[propName]); 176 } 177 } 178 function applyStyleProp(el, name, val) { 179 if (val == null) { 180 el.style[name] = ''; 181 } 182 else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) { 183 el.style[name] = val + 'px'; 184 } 185 else { 186 el.style[name] = val; 187 } 188 } 189 190 function pointInsideRect(point, rect) { 191 return point.left >= rect.left && 192 point.left < rect.right && 193 point.top >
193= rect.top && 194 point.top < rect.bottom; 195 } 196 // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false 197 function intersectRects(rect1, rect2) { 198 var res = { 199 left: Math.max(rect1.left, rect2.left), 200 right: Math.min(rect1.right, rect2.right), 201 top: Math.max(rect1.top, rect2.top), 202 bottom: Math.min(rect1.bottom, rect2.bottom) 203 }; 204 if (res.left < res.right && res.top < res.bottom) { 205 return res; 206 } 207 return false; 208 } 209 function translateRect(rect, deltaX, deltaY) { 210 return { 211 left: rect.left + deltaX, 212 right: rect.right + deltaX, 213 top: rect.top + deltaY, 214 bottom: rect.bottom + deltaY 215 }; 216 } 217 // Returns a new point that will have been moved to reside within the given rectangle 218 function constrainPoint(point, rect) { 219 return { 220 left: Math.min(Math.max(point.left, rect.left), rect.right), 221 top: Math.min(Math.max(point.top, rect.top), rect.bottom) 222 }; 223 } 224 // Returns a point that is the center of the given rectangle 225 function getRectCenter(rect) { 226 return { 227 left: (rect.left + rect.right) / 2, 228 top: (rect.top + rect.bottom) / 2 229 }; 230 } 231 // Subtracts point2's coordinates from point1's coordinates, returning a delta 232 function diffPoints(point1, point2) { 233 return { 234 left: point1.left - point2.left, 235 top: point1.top - point2.top 236 }; 237 } 238 239 // Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side 240 var isRtlScrollbarOnLeft = null; 241 function getIsRtlScrollbarOnLeft() { 242 if (isRtlScrollbarOnLeft === null) { 243 isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft(); 244 } 245 return isRtlScrollbarOnLeft; 246 } 247 function computeIsRtlScrollbarOnLeft() { 248 var outerEl = createElement('div', { 249 style: { 250 position: 'absolute', 251 top: -1000, 252 left: 0, 253 border: 0, 254 padding: 0, 255 overflow: 'scroll', 256 direction: 'rtl' 257 } 258 }, '<div></div>'); 259 document.body.appendChild(outerEl); 260 var innerEl = outerEl.firstChild; 261 var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left; 262 removeElement(outerEl); 263 return res; 264 } 265 // The scrollbar width computations in computeEdges are sometimes flawed when it comes to 266 // retina displays, rounding, and IE11. Massage them into a usable value. 267 function sanitizeScrollbarWidth(width) { 268 width = Math.max(0, width); // no negatives 269 width = Math.round(width); 270 return width; 271 } 272 273 function computeEdges(el, getPadding) { 274 if (getPadding === void 0) { getPadding = false; } 275 var computedStyle = window.getComputedStyle(el); 276 var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0; 277 var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0; 278 var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0; 279 var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; 280 var scrollbarLeftRight = sanitizeScrollbarWidth(el.offsetWidth - el.clientWidth - borderLeft - borderRight); 281 var scrollbarBottom = sanitizeScrollbarWidth(el.offsetHeight - el.clientHeight - borderTop - borderBottom); 282 var res = { 283 borderLeft: borderLeft, 284 borderRight: borderRight, 285 borderTop: borderTop, 286 borderBottom: borderBottom, 287 scrollbarBottom: scrollbarBottom, 288 scrollbarLeft: 0, 289 scrollbarRight: 0 290 }; 291 if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side? 292 res.scrollbarLeft = scrollbarLeftRight; 293 } 294 else { 295 res.scrollbarRight = scrollbarLeftRight; 296 } 297 if (getPadding) { 298 res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0; 299 res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0; 300 res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0; 301 res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0; 302 } 303 return res; 304 } 305 function computeInnerRect(el, goWithinPadding) { 306 if (goWithinPadding === void 0) { goWithinPadding = false; } 307 var outerRect = computeRect(el); 308 var edges = computeEdges(el, goWithinPadding); 309 var res = { 310 left: outerRect.left + edges.borderLeft + edges.scrollbarLeft, 311 right: outerRect.right - edges.borderRight - edges.scrollbarRight, 312 top: outerRect.top + edges.borderTop, 313 bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom 314 }; 315 if (goWithinPadding) { 316 res.left += edges.paddingLeft; 317 res.right -= edges.paddingRight; 318 res.top += edges.paddingTop; 319 res.bottom -= edges.paddingBottom; 320 } 321 return res; 322 } 323 function computeRect(el) { 324 var rect = el.getBoundingClientRect(); 325 return { 326 left: rect.left + window.pageXOffset, 327 top: rect.top + window.pageYOffset, 328 right: rect.right + window.pageXOffset, 329 bottom: rect.bottom + window.pageYOffset 330 }; 331 } 332 function computeViewportRect() { 333 return { 334 left: window.pageXOffset, 335 right: window.pageXOffset + document.documentElement.clientWidth, 336 top: window.pageYOffset, 337 bottom: window.pageYOffset + document.documentElement.clientHeight 338 }; 339 } 340 function computeHeightAndMargins(el) { 341 var computed = window.getComputedStyle(el); 342 return el.getBoundingClientRect().height + 343 parseInt(computed.marginTop, 10) + 344 parseInt(computed.marginBottom, 10); 345 } 346 // does not return window 347 function getClippingParents(el) { 348 var parents = []; 349 while (el instanceof HTMLElement) { // will stop when gets to document or null 350 var computedStyle = window.getComputedStyle(el); 351 if (computedStyle.position === 'fixed') { 352 break; 353 } 354 if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) { 355 parents.push(el); 356 } 357 el = el.parentNode; 358 } 359 return parents; 360 }
361 function computeClippingRect(el) { 362 return getClippingParents(el) 363 .map(function (el) { 364 return computeInnerRect(el); 365 }) 366 .concat(computeViewportRect()) 367 .reduce(function (rect0, rect1) { 368 return intersectRects(rect0, rect1) || rect1; // should always intersect 369 }); 370 } 371 372 // Stops a mouse/touch event from doing it's native browser action 373 function preventDefault(ev) { 374 ev.preventDefault(); 375 } 376 // Event Delegation 377 // ---------------------------------------------------------------------------------------------------------------- 378 function listenBySelector(container, eventType, selector, handler) { 379 function realHandler(ev) { 380 var matchedChild = elementClosest(ev.target, selector); 381 if (matchedChild) { 382 handler.call(matchedChild, ev, matchedChild); 383 } 384 } 385 container.addEventListener(eventType, realHandler); 386 return function () { 387 container.removeEventListener(eventType, realHandler); 388 }; 389 } 390 function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) { 391 var currentMatchedChild; 392 return listenBySelector(container, 'mouseover', selector, function (ev, matchedChild) { 393 if (matchedChild !== currentMatchedChild) { 394 currentMatchedChild = matchedChild; 395 onMouseEnter(ev, matchedChild); 396 var realOnMouseLeave_1 = function (ev) { 397 currentMatchedChild = null; 398 onMouseLeave(ev, matchedChild); 399 matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1); 400 }; 401 // listen to the next mouseleave, and then unattach 402 matchedChild.addEventListener('mouseleave', realOnMouseLeave_1); 403 } 404 }); 405 } 406 // Animation 407 // ---------------------------------------------------------------------------------------------------------------- 408 var transitionEventNames = [ 409 'webkitTransitionEnd', 410 'otransitionend', 411 'oTransitionEnd', 412 'msTransitionEnd', 413 'transitionend' 414 ]; 415 // triggered only when the next single subsequent transition finishes 416 function whenTransitionDone(el, callback) { 417 var realCallback = function (ev) { 418 callback(ev); 419 transitionEventNames.forEach(function (eventName) { 420 el.removeEventListener(eventName, realCallback); 421 }); 422 }; 423 transitionEventNames.forEach(function (eventName) { 424 el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes 425 }); 426 } 427 428 var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; 429 // Adding 430 function addWeeks(m, n) { 431 var a = dateToUtcArray(m); 432 a[2] += n * 7; 433 return arrayToUtcDate(a); 434 } 435 function addDays(m, n) { 436 var a = dateToUtcArray(m); 437 a[2] += n; 438 return arrayToUtcDate(a); 439 } 440 function addMs(m, n) { 441 var a = dateToUtcArray(m); 442 a[6] += n; 443 return arrayToUtcDate(a); 444 } 445 // Diffing (all return floats) 446 function diffWeeks(m0, m1) { 447 return diffDays(m0, m1) / 7; 448 } 449 function diffDays(m0, m1) { 450 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24); 451 } 452 function diffHours(m0, m1) { 453 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60); 454 } 455 function diffMinutes(m0, m1) { 456 return (m1.valueOf() - m0.valueOf()) / (1000 * 60); 457 } 458 function diffSeconds(m0, m1) { 459 return (m1.valueOf() - m0.valueOf()) / 1000; 460 } 461 function diffDayAndTime(m0, m1) { 462 var m0day = startOfDay(m0); 463 var m1day = startOfDay(m1); 464 return { 465 years: 0, 466 months: 0, 467 days: Math.round(diffDays(m0day, m1day)), 468 milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()) 469 }; 470 } 471 // Diffing Whole Units 472 function diffWholeWeeks(m0, m1) { 473 var d = diffWholeDays(m0, m1); 474 if (d !== null && d % 7 === 0) { 475 return d / 7; 476 } 477 return null; 478 } 479 function diffWholeDays(m0, m1) { 480 if (timeAsMs(m0) === timeAsMs(m1)) { 481 return Math.round(diffDays(m0, m1)); 482 } 483 return null; 484 } 485 // Start-Of 486 function startOfDay(m) { 487 return arrayToUtcDate([ 488 m.getUTCFullYear(), 489 m.getUTCMonth(), 490 m.getUTCDate() 491 ]); 492 } 493 function startOfHour(m) { 494 return arrayToUtcDate([ 495 m.getUTCFullYear(), 496 m.getUTCMonth(), 497 m.getUTCDate(), 498 m.getUTCHours() 499 ]); 500 } 501 function startOfMinute(m) { 502 return arrayToUtcDate([ 503 m.getUTCFullYear(), 504 m.getUTCMonth(), 505 m.getUTCDate(), 506 m.getUTCHours(), 507 m.getUTCMinutes() 508 ]); 509 } 510 function startOfSecond(m) { 511 return arrayToUtcDate([ 512 m.getUTCFullYear(), 513 m.getUTCMonth(), 514 m.getUTCDate(), 515 m.getUTCHours(), 516 m.getUTCMinutes(), 517 m.getUTCSeconds() 518 ]); 519 } 520 // Week Computation 521 function weekOfYear(marker, dow, doy) { 522 var y = marker.getUTCFullYear(); 523 var w = weekOfGivenYear(marker, y, dow, doy); 524 if (w < 1) { 525 return weekOfGivenYear(marker, y - 1, dow, doy); 526 } 527 var nextW = weekOfGivenYear(marker, y + 1, dow, doy); 528 if (nextW >= 1) { 529 return Math.min(w, nextW); 530 } 531 return w; 532 } 533 function weekOfGivenYear(marker, year, dow, doy) { 534 var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]); 535 var dayStart = startOfDay(marker); 536 var days = Math.round(diffDays(firstWeekStart, dayStart)); 537 return Math.floor(days / 7) + 1; // zero-indexed 538 } 539 // start-of-first-week - start-of-year 540 function firstWeekOffset(year, dow, doy) { 541 // first-week day -- which january is always in the first week (4 for iso, 1 for other) 542 var fwd = 7 + dow - doy; 543 // first-week day local weekday -- which local weekday is fwd 544 var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7; 545 return -fwdlw + fwd - 1; 546 } 547 // Array Conversion 548 function dateToLocalArray(date) { 549 return [ 550 date.getFullYear(), 551 date.getMonth(), 552 date.getDate(), 553 date.getHours(), 554 date.getMinutes(), 555 date.getSeconds(), 556 date.getMilliseconds() 557 ]; 558 } 559 function arrayToLocalDate(a) { 560 return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month 561 a[3] || 0, a[4] || 0, a[5] || 0); 562 } 563 function dateToUtcArray(date) { 564 return [ 565 date.getUTCFullYear(), 566 date.getUTCMonth(), 567 date.getUTCDate(), 568 date.getUTCHours(), 569 date.getUTCMinutes(), 570 date.getUTCSeconds(), 571 date.getUTCMilliseconds() 572 ]; 573 } 574 function arrayToUtcDate(a) { 575 // according to web standards (and Safari), a month index is required. 576 // massage if only given a year. 577 if (a.length === 1) { 578 a = a.concat([0]); 579 } 580 return new Date(Date.UTC.apply(Date, a)); 581 } 582 // Other Utils 583 function isValidDate(m) { 584 return !isNaN(m.valueOf()); 585 } 586 function timeAsMs(m) { 587 return m.getUTCHours() * 1000 * 60 * 60 + 588 m.getUTCMinutes() * 1000 * 60 + 589 m.getUTCSeconds() * 1000 + 590 m.getUTCMilliseconds(); 591 } 592 593 var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
594 var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/; 595 // Parsing and Creation 596 function createDuration(input, unit) { 597 var _a; 598 if (typeof input === 'string') { 599 return parseString(input); 600 } 601 else if (typeof input === 'object' && input) { // non-null object 602 return normalizeObject(input); 603 } 604 else if (typeof input === 'number') { 605 return normalizeObject((_a = {}, _a[unit || 'milliseconds'] = input, _a)); 606 } 607 else { 608 return null; 609 } 610 } 611 function parseString(s) { 612 var m = PARSE_RE.exec(s); 613 if (m) { 614 var sign = m[1] ? -1 : 1; 615 return { 616 years: 0, 617 months: 0, 618 days: sign * (m[2] ? parseInt(m[2], 10) : 0), 619 milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours 620 (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes 621 (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds 622 (m[6] ? parseInt(m[6], 10) : 0) // ms 623 ) 624 }; 625 } 626 return null; 627 } 628 function normalizeObject(obj) { 629 return { 630 years: obj.years || obj.year || 0, 631 months: obj.months || obj.month || 0, 632 days: (obj.days || obj.day || 0) + 633 getWeeksFromInput(obj) * 7, 634 milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours 635 (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes 636 (obj.seconds || obj.second || 0) * 1000 + // seconds 637 (obj.milliseconds || obj.millisecond || obj.ms || 0) // ms 638 }; 639 } 640 function getWeeksFromInput(obj) { 641 return obj.weeks || obj.week || 0; 642 } 643 // Equality 644 function durationsEqual(d0, d1) { 645 return d0.years === d1.years && 646 d0.months === d1.months && 647 d0.days === d1.days && 648 d0.milliseconds === d1.milliseconds; 649 } 650 function isSingleDay(dur) { 651 return dur.years === 0 && dur.months === 0 && dur.days === 1 && dur.milliseconds === 0; 652 } 653 // Simple Math 654 function addDurations(d0, d1) { 655 return { 656 years: d0.years + d1.years, 657 months: d0.months + d1.months, 658 days: d0.days + d1.days, 659 milliseconds: d0.milliseconds + d1.milliseconds 660 }; 661 } 662 function subtractDurations(d1, d0) { 663 return { 664 years: d1.years - d0.years, 665 months: d1.months - d0.months, 666 days: d1.days - d0.days, 667 milliseconds: d1.milliseconds - d0.milliseconds 668 }; 669 } 670 function multiplyDuration(d, n) { 671 return { 672 years: d.years * n, 673 months: d.months * n, 674 days: d.days * n, 675 milliseconds: d.milliseconds * n 676 }; 677 } 678 // Conversions 679 // "Rough" because they are based on average-case Gregorian months/years 680 function asRoughYears(dur) { 681 return asRoughDays(dur) / 365; 682 } 683 function asRoughMonths(dur) { 684 return asRoughDays(dur) / 30; 685 } 686 function asRoughDays(dur) { 687 return asRoughMs(dur) / 864e5; 688 } 689 function asRoughMinutes(dur) { 690 return asRoughMs(dur) / (1000 * 60); 691 } 692 function asRoughSeconds(dur) { 693 return asRoughMs(dur) / 1000; 694 } 695 function asRoughMs(dur) { 696 return dur.years * (365 * 864e5) + 697 dur.months * (30 * 864e5) + 698 dur.days * 864e5 + 699 dur.milliseconds; 700 } 701 // Advanced Math 702 function wholeDivideDurations(numerator, denominator) { 703 var res = null; 704 for (var i = 0; i < INTERNAL_UNITS.length; i++) { 705 var unit = INTERNAL_UNITS[i]; 706 if (denominator[unit]) { 707 var localRes = numerator[unit] / denominator[unit]; 708 if (!isInt(localRes) || (res !== null && res !== localRes)) { 709 return null; 710 } 711 res = localRes; 712 } 713 else if (numerator[unit]) { 714 // needs to divide by something but can't! 715 return null; 716 } 717 } 718 return res; 719 } 720 function greatestDurationDenominator(dur, dontReturnWeeks) { 721 var ms = dur.milliseconds; 722 if (ms) { 723 if (ms % 1000 !== 0) { 724 return { unit: 'millisecond', value: ms }; 725 } 726 if (ms % (1000 * 60) !== 0) { 727 return { unit: 'second', value: ms / 1000 }; 728 } 729 if (ms % (1000 * 60 * 60) !== 0) { 730 return { unit: 'minute', value: ms / (1000 * 60) }; 731 } 732 if (ms) { 733 return { unit: 'hour', value: ms / (1000 * 60 * 60) }; 734 } 735 } 736 if (dur.days) { 737 if (!dontReturnWeeks && dur.days % 7 === 0) { 738 return { unit: 'week', value: dur.days / 7 }; 739 } 740 return { unit: 'day', value: dur.days }; 741 } 742 if (dur.months) { 743 return { unit: 'month', value: dur.months }; 744 } 745 if (dur.years) { 746 return { unit: 'year', value: dur.years }; 747 } 748 return { unit: 'millisecond', value: 0 }; 749 } 750 751 /* FullCalendar-specific DOM Utilities 752 ----------------------------------------------------------------------------------------------------------------------*/ 753 // Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left 754 // and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that. 755 function compensateScroll(rowEl, scrollbarWidths) { 756 if (scrollbarWidths.left) { 757 applyStyle(rowEl, { 758 borderLeftWidth: 1, 759 marginLeft: scrollbarWidths.left - 1 760 }); 761 } 762 if (scrollbarWidths.right) { 763 applyStyle(rowEl, { 764 borderRightWidth: 1, 765 marginRight: scrollbarWidths.right - 1 766 }); 767 } 768 } 769 // Undoes compensateScroll and restores all borders/margins 770 function uncompensateScroll(rowEl) { 771 applyStyle(rowEl, { 772 marginLeft: '', 773 marginRight: '', 774 borderLeftWidth: '', 775 borderRightWidth: '' 776 }); 777 }
778 // Make the mouse cursor express that an event is not allowed in the current area 779 function disableCursor() { 780 document.body.classList.add('fc-not-allowed'); 781 } 782 // Returns the mouse cursor to its original look 783 function enableCursor() { 784 document.body.classList.remove('fc-not-allowed'); 785 } 786 // Given a total available height to fill, have `els` (essentially child rows) expand to accomodate. 787 // By default, all elements that are shorter than the recommended height are expanded uniformly, not considering 788 // any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and 789 // reduces the available height. 790 function distributeHeight(els, availableHeight, shouldRedistribute) { 791 // *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions, 792 // and it is better to be shorter than taller, to avoid creating unnecessary scrollbars. 793 var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element 794 var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE* 795 var flexEls = []; // elements that are allowed to expand. array of DOM nodes 796 var flexOffsets = []; // amount of vertical space it takes up 797 var flexHeights = []; // actual css height 798 var usedHeight = 0; 799 undistributeHeight(els); // give all elements their natural height 800 // find elements that are below the recommended height (expandable). 801 // important to query for heights in a single first pass (to avoid reflow oscillation). 802 els.forEach(function (el, i) { 803 var minOffset = i === els.length - 1 ? minOffset2 : minOffset1; 804 var naturalOffset = computeHeightAndMargins(el); 805 if (naturalOffset < minOffset) { 806 flexEls.push(el); 807 flexOffsets.push(naturalOffset); 808 flexHeights.push(el.offsetHeight); 809 } 810 else { 811 // this element stretches past recommended height (non-expandable). mark the space as occupied. 812 usedHeight += naturalOffset; 813 } 814 }); 815 // readjust the recommended height to only consider the height available to non-maxed-out rows. 816 if (shouldRedistribute) { 817 availableHeight -= usedHeight; 818 minOffset1 = Math.floor(availableHeight / flexEls.length); 819 minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE* 820 } 821 // assign heights to all expandable elements 822 flexEls.forEach(function (el, i) { 823 var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1; 824 var naturalOffset = flexOffsets[i]; 825 var naturalHeight = flexHeights[i]; 826 var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding 827 if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things 828 el.style.height = newHeight + 'px'; 829 } 830 }); 831 } 832 // Undoes distrubuteHeight, restoring all els to their natural height 833 function undistributeHeight(els) { 834 els.forEach(function (el) { 835 el.style.height = ''; 836 }); 837 } 838 // Given `els`, a set of <td> cells, find the cell with the largest natural width and set the widths of all the 839 // cells to be that width. 840 // PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline 841 function matchCellWidths(els) { 842 var maxInnerWidth = 0; 843 els.forEach(function (el) { 844 var innerEl = el.firstChild; // hopefully an element 845 if (innerEl instanceof HTMLElement) { 846 var innerWidth_1 = innerEl.offsetWidth; 847 if (innerWidth_1 > maxInnerWidth) { 848 maxInnerWidth = innerWidth_1; 849 } 850 } 851 }); 852 maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance
853 els.forEach(function (el) { 854 el.style.width = maxInnerWidth + 'px'; 855 }); 856 return maxInnerWidth; 857 } 858 // Given one element that resides inside another, 859 // Subtracts the height of the inner element from the outer element. 860 function subtractInnerElHeight(outerEl, innerEl) { 861 // effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked 862 var reflowStyleProps = { 863 position: 'relative', 864 left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll 865 }; 866 applyStyle(outerEl, reflowStyleProps); 867 applyStyle(innerEl, reflowStyleProps); 868 var diff = outerEl.offsetHeight - innerEl.offsetHeight; // grab the dimensions 869 // undo hack 870 var resetStyleProps = { position: '', left: '' }; 871 applyStyle(outerEl, resetStyleProps); 872 applyStyle(innerEl, resetStyleProps); 873 return diff; 874 } 875 /* Selection 876 ----------------------------------------------------------------------------------------------------------------------*/ 877 function preventSelection(el) { 878 el.classList.add('fc-unselectable'); 879 el.addEventListener('selectstart', preventDefault); 880 } 881 function allowSelection(el) { 882 el.classList.remove('fc-unselectable'); 883 el.removeEventListener('selectstart', preventDefault); 884 } 885 /* Context Menu 886 ----------------------------------------------------------------------------------------------------------------------*/ 887 function preventContextMenu(el) { 888 el.addEventListener('contextmenu', preventDefault); 889 } 890 function allowContextMenu(el) { 891 el.removeEventListener('contextmenu', preventDefault); 892 } 893 /* Object Ordering by Field 894 ----------------------------------------------------------------------------------------------------------------------*/ 895 function parseFieldSpecs(input) { 896 var specs = []; 897 var tokens = []; 898 var i; 899 var token; 900 if (typeof input === 'string') { 901 tokens = input.split(/\s*,\s*/); 902 } 903 else if (typeof input === 'function') { 904 tokens = [input]; 905 } 906 else if (Array.isArray(input)) { 907 tokens = input; 908 } 909 for (i = 0; i < tokens.length; i++) { 910 token = tokens[i]; 911 if (typeof token === 'string') { 912 specs.push(token.charAt(0) === '-' ? 913 { field: token.substring(1), order: -1 } : 914 { field: token, order: 1 }); 915 } 916 else if (typeof token === 'function') { 917 specs.push({ func: token }); 918 } 919 } 920 return specs; 921 } 922 function compareByFieldSpecs(obj0, obj1, fieldSpecs) { 923 var i; 924 var cmp; 925 for (i = 0; i < fieldSpecs.length; i++) { 926 cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]); 927 if (cmp) { 928 return cmp; 929 } 930 } 931 return 0; 932 } 933 function compareByFieldSpec(obj0, obj1, fieldSpec) { 934 if (fieldSpec.func) { 935 return fieldSpec.func(obj0, obj1); 936 } 937 return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) 938 * (fieldSpec.order || 1); 939 } 940 function flexibleCompare(a, b) { 941 if (!a && !b) { 942 return 0; 943 } 944 if (b == null) { 945 return -1; 946 } 947 if (a == null) { 948 return 1; 949 } 950 if (typeof a === 'string' || typeof b === 'string') { 951 return String(a).localeCompare(String(b)); 952 } 953 return a - b; 954 } 955 /* String Utilities 956 ----------------------------------------------------------------------------------------------------------------------*/ 957 function capitaliseFirstLetter(str) { 958 return str.charAt(0).toUpperCase() + str.slice(1); 959 } 960 function padStart(val, len) { 961 var s = String(val); 962 return '000'.substr(0, len - s.length) + s; 963 } 964 /* Number Utilities 965 ----------------------------------------------------------------------------------------------------------------------*/ 966 function compareNumbers(a, b) { 967 return a - b; 968 } 969 function isInt(n) { 970 return n % 1 === 0; 971 } 972 /* Weird Utilities 973 ----------------------------------------------------------------------------------------------------------------------*/ 974 function applyAll(functions, thisObj, args) { 975 if (typeof functions === 'function') { // supplied a single function 976 functions = [functions]; 977 } 978 if (functions) { 979 var i = void 0; 980 var ret = void 0; 981 for (i = 0; i < functions.length; i++) { 982 ret = functions[i].apply(thisObj, args) || ret; 983 } 984 return ret; 985 } 986 } 987 function firstDefined() { 988 var args = []; 989 for (var _i = 0; _i < arguments.length; _i++) { 990 args[_i] = arguments[_i]; 991 } 992 for (var i = 0; i < args.length; i++) { 993 if (args[i] !== undefined) { 994 return args[i]; 995 } 996 } 997 } 998 // Returns a function, that, as long as it continues to be invoked, will not 999 // be triggered. The function will be called after it stops being called for 1000 // N milliseconds. If `immediate` is passed, trigger the function on the 1001 // leading edge, instead of the trailing. 1002 // https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714 1003 function debounce(func, wait) { 1004 var timeout; 1005 var args; 1006 var context; 1007 var timestamp; 1008 var result; 1009 var later = function () { 1010 var last = new Date().valueOf() - timestamp; 1011 if (last < wait) { 1012 timeout = setTimeout(later, wait - last); 1013 } 1014 else { 1015 timeout = null;
1016 result = func.apply(context, args); 1017 context = args = null; 1018 } 1019 }; 1020 return function () { 1021 context = this; 1022 args = arguments; 1023 timestamp = new Date().valueOf(); 1024 if (!timeout) { 1025 timeout = setTimeout(later, wait); 1026 } 1027 return result; 1028 }; 1029 } 1030 // Number and Boolean are only types that defaults or not computed for 1031 // TODO: write more comments 1032 function refineProps(rawProps, processors, defaults, leftoverProps) { 1033 if (defaults === void 0) { defaults = {}; } 1034 var refined = {}; 1035 for (var key in processors) { 1036 var processor = processors[key]; 1037 if (rawProps[key] !== undefined) { 1038 // found 1039 if (processor === Function) { 1040 refined[key] = typeof rawProps[key] === 'function' ? rawProps[key] : null; 1041 } 1042 else if (processor) { // a refining function? 1043 refined[key] = processor(rawProps[key]); 1044 } 1045 else { 1046 refined[key] = rawProps[key]; 1047 } 1048 } 1049 else if (defaults[key] !== undefined) { 1050 // there's an explicit default 1051 refined[key] = defaults[key]; 1052 } 1053 else { 1054 // must compute a default 1055 if (processor === String) { 1056 refined[key] = ''; // empty string is default for String 1057 } 1058 else if (!processor || processor === Number || processor === Boolean || processor === Function) { 1059 refined[key] = null; // assign null for other non-custom processor funcs 1060 } 1061 else { 1062 refined[key] = processor(null); // run the custom processor func 1063 } 1064 } 1065 } 1066 if (leftoverProps) { 1067 for (var key in rawProps) { 1068 if (processors[key] === undefined) { 1069 leftoverProps[key] = rawProps[key]; 1070 } 1071 } 1072 } 1073 return refined; 1074 } 1075 /* 1076 Get a snapshot of an object, so we can compare it to later revisions. 1077 Intentionally only works with arrays, jaja 1078 */ 1079 function freezeRaw(raw) { 1080 if (Array.isArray(raw)) { 1081 return Array.prototype.slice.call(raw); 1082 } 1083 return raw; 1084 } 1085 /* Date stuff that doesn't belong in datelib core 1086 ----------------------------------------------------------------------------------------------------------------------*/ 1087 // given a timed range, computes an all-day range that has the same exact duration, 1088 // but whose start time is aligned with the start of the day. 1089 function computeAlignedDayRange(timedRange) { 1090 var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1; 1091 var start = startOfDay(timedRange.start); 1092 var end = addDays(start, dayCnt); 1093 return { start: start, end: end }; 1094 } 1095 // given a timed range, computes an all-day range based on how for the end date bleeds into the next day 1096 // TODO: give nextDayThreshold a default arg 1097 function computeVisibleDayRange(timedRange, nextDayThreshold) { 1098 if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); } 1099 var startDay = null; 1100 var endDay = null; 1101 if (timedRange.end) { 1102 endDay = startOfDay(timedRange.end); 1103 var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay` 1104 // If the end time is actually inclusively part of the next day and is equal to or 1105 // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`. 1106 // Otherwise, leaving it as inclusive will cause it to exclude `endDay`. 1107 if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) { 1108 endDay = addDays(endDay, 1); 1109 } 1110 } 1111 if (timedRange.start) { 1112 startDay = startOfDay(timedRange.start); // the beginning of the day the range starts 1113 // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day. 1114 if (endDay && endDay <= startDay) { 1115 endDay = addDays(startDay, 1); 1116 } 1117 } 1118 return { start: startDay, end: endDay }; 1119 } 1120 // spans from one day into another? 1121 function isMultiDayRange(range) { 1122 var visibleRange = computeVisibleDayRange(range); 1123 return diffDays(visibleRange.start, visibleRange.end) > 1; 1124 } 1125 function diffDates(date0, date1, dateEnv, largeUnit) { 1126 if (largeUnit === 'year') { 1127 return createDuration(dateEnv.diffWholeYears(date0, date1), 'year'); 1128 } 1129 else if (largeUnit === 'month') { 1130 return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month'); 1131 } 1132 else { 1133 return diffDayAndTime(date0, date1); // returns a duration 1134 } 1135 } 1136 1137 /*! ***************************************************************************** 1138 Copyright (c) Microsoft Corporation. All rights reserved. 1139 Licensed under the Apache License, Version 2.0 (the "License");
1139 you may not use 1140 this file except in compliance with the License. You may obtain a copy of the 1141 License at http://www.apache.org/licenses/LICENSE-2.0 1142 1143 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1144 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 1145 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 1146 MERCHANTABLITY OR NON-INFRINGEMENT. 1147 1148 See the Apache Version 2.0 License for specific language governing permissions 1149 and limitations under the License. 1150 ***************************************************************************** */ 1151 /* global Reflect, Promise */ 1152 1153 var extendStatics = function(d, b) { 1154 extendStatics = Object.setPrototypeOf || 1155 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 1156 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 1157 return extendStatics(d, b); 1158 }; 1159 1160 function __extends(d, b) { 1161 extendStatics(d, b); 1162 function __() { this.constructor = d; } 1163 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 1164 } 1165 1166 var __assign = function() { 1167 __assign = Object.assign || function __assign(t) { 1168 for (var s, i = 1, n = arguments.length; i < n; i++) { 1169 s = arguments[i]; 1170 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 1171 } 1172 return t; 1173 }; 1174 return __assign.apply(this, arguments); 1175 }; 1176 1177 function parseRecurring(eventInput, allDayDefault, dateEnv, recurringTypes, leftovers) { 1178 for (var i = 0; i < recurringTypes.length; i++) { 1179 var localLeftovers = {}; 1180 var parsed = recurringTypes[i].parse(eventInput, localLeftovers, dateEnv); 1181 if (parsed) { 1182 var allDay = localLeftovers.allDay; 1183 delete localLeftovers.allDay; // remove from leftovers 1184 if (allDay == null) { 1185 allDay = allDayDefault; 1186 if (allDay == null) { 1187 allDay = parsed.allDayGuess; 1188 if (allDay == null) { 1189 allDay = false; 1190 } 1191 } 1192 } 1193 __assign(leftovers, localLeftovers); 1194 return { 1195 allDay: allDay, 1196 duration: parsed.duration, 1197 typeData: parsed.typeData, 1198 typeId: i 1199 }; 1200 } 1201 } 1202 return null; 1203 } 1204 /* 1205 Event MUST have a recurringDef 1206 */ 1207 function expandRecurringRanges(eventDef, framingRange, dateEnv, recurringTypes) { 1208 var typeDef = recurringTypes[eventDef.recurringDef.typeId]; 1209 var markers = typeDef.expand(eventDef.recurringDef.typeData, framingRange, dateEnv); 1210 // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to 1211 if (eventDef.allDay) { 1212 markers = markers.map(startOfDay); 1213 } 1214 return markers; 1215 } 1216 1217 // Merges an array of objects into a single object. 1218 // The second argument allows for an array of property names who's object values will be merged together. 1219 function mergeProps(propObjs, complexProps) { 1220 var dest = {}; 1221 var i; 1222 var name; 1223 var complexObjs; 1224 var j; 1225 var val; 1226 var props; 1227 if (complexProps) { 1228 for (i = 0; i < complexProps.length; i++) { 1229 name = complexProps[i]; 1230 complexObjs = []; 1231 // collect the trailing object values, stopping when a non-object is discovered 1232 for (j = propObjs.length - 1; j >= 0; j--) { 1233 val = propObjs[j][name]; 1234 if (typeof val === 'object' && val) { // non-null object 1235 complexObjs.unshift(val); 1236 } 1237 else if (val !== undefined) { 1238 dest[name] = val; // if there were no objects, this value will be used 1239 break; 1240 } 1241 } 1242 // if the trailing values were objects, use the merged value 1243 if (complexObjs.length) { 1244 dest[name] = mergeProps(complexObjs); 1245 } 1246 } 1247 } 1248 // copy values into the destination, going from last to first 1249 for (i = propObjs.length - 1; i >= 0; i--) { 1250 props = propObjs[i]; 1251 for (name in props) { 1252 if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign 1253 dest[name] = props[name]; 1254 } 1255 } 1256 } 1257 return dest; 1258 } 1259 function filterHash(hash, func) { 1260 var filtered = {}; 1261 for (var key in hash) { 1262 if (func(hash[key], key)) { 1263 filtered[key] = hash[key]; 1264 } 1265 } 1266 return filtered; 1267 } 1268 function mapHash(hash, func) { 1269 var newHash = {}; 1270 for (var key in hash) { 1271 newHash[key] = func(hash[key], key); 1272 } 1273 return newHash; 1274 } 1275 function arrayToHash(a) { 1276 var hash = {}; 1277 for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { 1278 var item = a_1[_i]; 1279 hash[item] = true; 1280 } 1281 return hash; 1282 } 1283 function hashValuesToArray(obj) { 1284 var a = []; 1285 for (var key in obj) { 1286 a.push(obj[key]); 1287 } 1288 return a; 1289 } 1290 1291 function parseEvents(rawEvents, sourceId, calendar, allowOpenRange) { 1292 var eventStore = createEmptyEventStore(); 1293 for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { 1294 var rawEvent = rawEvents_1[_i]; 1295 var tuple = parseEvent(rawEvent, sourceId, calendar, allowOpenRange); 1296 if (tuple) { 1297 eventTupleToStore(tuple, eventStore); 1298 } 1299 } 1300 return eventStore; 1301 } 1302 function eventTupleToStore(tuple, eventStore) { 1303 if (eventStore === void 0) { eventStore = createEmptyEventStore(); } 1304 eventStore.defs[tuple.def.defId] = tuple.def; 1305 if (tuple.instance) { 1306 eventStore.instances[tuple.instance.instanceId] = tuple.instance; 1307 } 1308 return eventStore; 1309 } 1310 function expandRecurring(eventStore, framingRange, calendar) { 1311 var dateEnv = calendar.dateEnv; 1312 var defs = eventStore.defs, instances = eventStore.instances; 1313 // remove existing recurring instances 1314 instances = filterHash(instances, function (instance) { 1315 return !defs[instance.defId].recurringDef; 1316 }); 1317 for (var defId in defs) { 1318 var def = defs[defId]; 1319 if (def.recurringDef) { 1320 var starts = expandRecurringRanges(def, framingRange, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes); 1321 var duration = def.recurringDef.duration; 1322 if (!duration) { 1323 duration = def.allDay ? 1324 calendar.defaultAllDayEventDuration : 1325 calendar.defaultTimedEventDuration; 1326 } 1327 for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) { 1328 var start = starts_1[_i]; 1329 var instance = createEventInstance(defId, { 1330 start: start, 1331 end: dateEnv.add(start, duration) 1332 }); 1333 instances[instance.instanceId] = instance; 1334 } 1335 } 1336 } 1337 return { defs: defs, instances: instances }; 1338 } 1339 // retrieves events that have the same groupId as the instance specified by `instanceId` 1340 // or they are the same as the instance. 1341 // why might instanceId not be in the store? an event from another calendar? 1342 function getRelevantEvents(eventStore, instanceId) { 1343 var instance = eventStore.instances[instanceId]; 1344 if (instance) { 1345 var def_1 = eventStore.defs[instance.defId]; 1346 // get events/instances with same group 1347 var newStore = filterEventStoreDefs(eventStore, function (lookDef) { 1348 return isEventDefsGrouped(def_1, lookDef); 1349 }); 1350 // add the original 1351 // TODO: wish we could use eventTupleToStore or something like it 1352 newStore.defs[def_1.defId] = def_1; 1353 newStore.instances[instance.instanceId] = instance; 1354 return newStore; 1355 } 1356 return createEmptyEventStore(); 1357 } 1358 function isEventDefsGrouped(def0, def1) { 1359 return Boolean(def0.groupId && def0.groupId === def1.groupId); 1360 } 1361 function transformRawEvents(rawEvents, eventSource, calendar) { 1362 var calEachTransform = calendar.opt('eventDataTransform'); 1363 var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null; 1364 if (sourceEachTransform) { 1365 rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform); 1366 } 1367 if (calEachTransform) { 1368 rawEvents = transformEachRawEvent(rawEvents, calEachTransform); 1369 } 1370 return rawEvents; 1371 } 1372 function transformEachRawEvent(rawEvents, func) { 1373 var refinedEvents; 1374 if (!func) { 1375 refinedEvents = rawEvents; 1376 } 1377 else { 1378 refinedEvents = []; 1379 for (var _i = 0, rawEvents_2 = rawEvents; _i < rawEvents_2.length; _i++) { 1380 var rawEvent = rawEvents_2[_i]; 1381 var refinedEvent = func(rawEvent); 1382 if (refinedEvent) { 1383 refinedEvents.push(refinedEvent); 1384 } 1385 else if (refinedEvent == null) { 1386 refinedEvents.push(rawEvent); 1387 } // if a different falsy value, do nothing 1388 } 1389 } 1390 return refinedEvents; 1391 } 1392 function createEmptyEventStore() { 1393 return { defs: {}, instances: {} }; 1394 } 1395 function mergeEventStores(store0, store1) { 1396 return { 1397 defs: __assign({}, store0.defs, store1.defs), 1398 instances: __assign({}, store0.instances, store1.instances) 1399 }; 1400 } 1401 function filterEventStoreDefs(eventStore, filterFunc) { 1402 var defs = filterHash(eventStore.defs, filterFunc); 1403 var instances = filterHash(eventStore.instances, function (instance) { 1404 return defs[instance.defId]; // still exists? 1405 }); 1406 return { defs: defs, instances: instances }; 1407 } 1408 1409 function parseRange(input, dateEnv) { 1410 var start = null; 1411 var end = null; 1412 if (input.start) { 1413 start = dateEnv.createMarker(input.start); 1414 } 1415 if (input.end) { 1416 end = dateEnv.createMarker(input.end); 1417 } 1418 if (!start && !end) { 1419 return null; 1420 } 1421 if (start && end && end < start) { 1422 return null; 1423 } 1424 return { start: start, end: end }; 1425 } 1426 // SIDE-EFFECT: will mutate ranges. 1427 // Will return a new array result. 1428 function invertRanges(ranges, constraintRange) { 1429 var invertedRanges = []; 1430 var start = constraintRange.start; // the end of the previous range. the start of the new range 1431 var i; 1432 var dateRange; 1433 // ranges need to be in order. required for our date-walking algorithm 1434 ranges.sort(compareRanges); 1435 for (i = 0; i < ranges.length; i++) { 1436 dateRange = ranges[i]; 1437 // add the span of time before the event (if there is any) 1438 if (dateRange.start > start) { // compare millisecond time (skip any ambig logic) 1439 invertedRanges.push({ start: start, end: dateRange.start }); 1440 } 1441 if (dateRange.end > start) { 1442 start = dateRange.end; 1443 } 1444 } 1445 // add the span of time after the last event (if there is any) 1446 if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic) 1447 invertedRanges.push({ start: start, end: constraintRange.end }); 1448 } 1449 return invertedRanges; 1450 } 1451 function compareRanges(range0, range1) { 1452 return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first 1453 } 1454 function intersectRanges(range0, range1) { 1455 var start = range0.start; 1456 var end = range0.end; 1457 var newRange = null; 1458 if (range1.start !== null) { 1459 if (start === null) { 1460 start = range1.start; 1461 } 1462 else { 1463 start = new Date(Math.max(start.valueOf(), range1.start.valueOf())); 1464 } 1465 } 1466 if (range1.end != null) { 1467 if (end === null) { 1468 end = range1.end; 1469 } 1470 else { 1471 end = new Date(Math.min(end.valueOf(), range1.end.valueOf())); 1472 } 1473 } 1474 if (start === null || end === null || start < end) { 1475 newRange = { start: start, end: end }; 1476 } 1477 return newRange; 1478 } 1479 function rangesEqual(range0, range1) { 1480 return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) && 1481 (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf()); 1482 } 1483 function rangesIntersect(range0, range1) { 1484 return (range0.end === null || range1.start === null || range0.end > range1.start) && 1485 (range0.start === null || range1.end === null || range0.start < range1.end); 1486 } 1487 function rangeContainsRange(outerRange, innerRange) { 1488 return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) && 1489 (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end)); 1490 } 1491 function rangeContainsMarker(range, date) { 1492 return (range.start === null || date >= range.start) && 1493 (range.end === null || date < range.end); 1494 } 1495 // If the given date is not within the given range, move it inside. 1496 // (If it's past the end, make it one millisecond before the end). 1497 function constrainMarkerToRange(date, range) { 1498 if (range.start != null && date < range.start) { 1499 return range.start; 1500 } 1501 if (range.end != null && date >= range.end) { 1502 return new Date(range.end.valueOf() - 1); 1503 } 1504 return date; 1505 } 1506 1507 function removeExact(array, exactVal) { 1508 var removeCnt = 0; 1509 var i = 0; 1510 while (i < array.length) { 1511 if (array[i] === exactVal) { 1512 array.splice(i, 1); 1513 removeCnt++; 1514 } 1515 else { 1516 i++; 1517 } 1518 } 1519 return removeCnt; 1520 } 1521 function isArraysEqual(a0, a1) { 1522 var len = a0.length; 1523 var i; 1524 if (len !== a1.length) { // not array? or not same length? 1525 return false;
1526 } 1527 for (i = 0; i < len; i++) { 1528 if (a0[i] !== a1[i]) { 1529 return false; 1530 } 1531 } 1532 return true; 1533 } 1534 1535 function memoize(workerFunc) { 1536 var args; 1537 var res; 1538 return function () { 1539 if (!args || !isArraysEqual(args, arguments)) { 1540 args = arguments; 1541 res = workerFunc.apply(this, arguments); 1542 } 1543 return res; 1544 }; 1545 } 1546 /* 1547 always executes the workerFunc, but if the result is equal to the previous result, 1548 return the previous result instead. 1549 */ 1550 function memoizeOutput(workerFunc, equalityFunc) { 1551 var cachedRes = null; 1552 return function () { 1553 var newRes = workerFunc.apply(this, arguments); 1554 if (cachedRes === null || !(cachedRes === newRes || equalityFunc(cachedRes, newRes))) { 1555 cachedRes = newRes; 1556 } 1557 return cachedRes; 1558 }; 1559 } 1560 1561 var EXTENDED_SETTINGS_AND_SEVERITIES = { 1562 week: 3, 1563 separator: 0, 1564 omitZeroMinute: 0, 1565 meridiem: 0, 1566 omitCommas: 0 1567 }; 1568 var STANDARD_DATE_PROP_SEVERITIES = { 1569 timeZoneName: 7, 1570 era: 6, 1571 year: 5, 1572 month: 4, 1573 day: 2, 1574 weekday: 2, 1575 hour: 1, 1576 minute: 1, 1577 second: 1 1578 }; 1579 var MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too 1580 var COMMA_RE = /,/g; // we need re for globalness 1581 var MULTI_SPACE_RE = /\s+/g; 1582 var LTR_RE = /\u200e/g; // control character 1583 var UTC_RE = /UTC|GMT/; 1584 var NativeFormatter = /** @class */ (function () { 1585 function NativeFormatter(formatSettings) { 1586 var standardDateProps = {}; 1587 var extendedSettings = {}; 1588 var severity = 0; 1589 for (var name_1 in formatSettings) { 1590 if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) { 1591 extendedSettings[name_1] = formatSettings[name_1]; 1592 severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity); 1593 } 1594 else { 1595 standardDateProps[name_1] = formatSettings[name_1]; 1596 if (name_1 in STANDARD_DATE_PROP_SEVERITIES) { 1597 severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity); 1598 } 1599 } 1600 } 1601 this.standardDateProps = standardDateProps; 1602 this.extendedSettings = extendedSettings; 1603 this.severity = severity; 1604 this.buildFormattingFunc = memoize(buildFormattingFunc); 1605 } 1606 NativeFormatter.prototype.format = function (date, context) { 1607 return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date); 1608 }; 1609 NativeFormatter.prototype.formatRange = function (start, end, context) { 1610 var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings; 1611 var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem); 1612 if (!diffSeverity) { 1613 return this.format(start, context); 1614 } 1615 var biggestUnitForPartial = diffSeverity; 1616 if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time 1617 (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') && 1618 (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') && 1619 (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) { 1620 biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time 1621 } 1622 var full0 = this.format(start, context); 1623 var full1 = this.format(end, context); 1624 if (full0 === full1) { 1625 return full0; 1626 } 1627 var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForParti
1627al); 1628 var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context); 1629 var partial0 = partialFormattingFunc(start); 1630 var partial1 = partialFormattingFunc(end); 1631 var insertion = findCommonInsertion(full0, partial0, full1, partial1); 1632 var separator = extendedSettings.separator || ''; 1633 if (insertion) { 1634 return insertion.before + partial0 + separator + partial1 + insertion.after; 1635 } 1636 return full0 + separator + full1; 1637 }; 1638 NativeFormatter.prototype.getLargestUnit = function () { 1639 switch (this.severity) { 1640 case 7: 1641 case 6: 1642 case 5: 1643 return 'year'; 1644 case 4: 1645 return 'month'; 1646 case 3: 1647 return 'week'; 1648 default: 1649 return 'day'; 1650 } 1651 }; 1652 return NativeFormatter; 1653 }()); 1654 function buildFormattingFunc(standardDateProps, extendedSettings, context) { 1655 var standardDatePropCnt = Object.keys(standardDateProps).length; 1656 if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') { 1657 return function (date) { 1658 return formatTimeZoneOffset(date.timeZoneOffset); 1659 }; 1660 } 1661 if (standardDatePropCnt === 0 && extendedSettings.week) { 1662 return function (date) { 1663 return formatWeekNumber(context.computeWeekNumber(date.marker), context.weekLabel, context.locale, extendedSettings.week); 1664 }; 1665 } 1666 return buildNativeFormattingFunc(standardDateProps, extendedSettings, context); 1667 } 1668 function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) { 1669 standardDateProps = __assign({}, standardDateProps); // copy 1670 extendedSettings = __assign({}, extendedSettings); // copy 1671 sanitizeSettings(standardDateProps, extendedSettings); 1672 standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers 1673 var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps); 1674 var zeroFormat; // needed? 1675 if (extendedSettings.omitZeroMinute) { 1676 var zeroProps = __assign({}, standardDateProps); 1677 delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings 1678 zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps); 1679 } 1680 return function (date) { 1681 var marker = date.marker; 1682 var format; 1683 if (zeroFormat && !marker.getUTCMinutes()) { 1684 format = zeroFormat; 1685 } 1686 else { 1687 format = normalFormat; 1688 } 1689 var s = format.format(marker); 1690 return postProcess(s, date, standardDateProps, extendedSettings, context); 1691 }; 1692 } 1693 function sanitizeSettings(standardDateProps, extendedSettings) { 1694 // deal with a browser inconsistency where formatting the timezone 1695 // requires that the hour/minute be present. 1696 if (standardDateProps.timeZoneName) { 1697 if (!standardDateProps.hour) { 1698 standardDateProps.hour = '2-digit'; 1699 } 1700 if (!standardDateProps.minute) { 1701 standardDateProps.minute = '2-digit'; 1702 } 1703 } 1704 // only support short timezone names 1705 if (standardDateProps.timeZoneName === 'long') { 1706 standardDateProps.timeZoneName = 'short'; 1707 } 1708 // if requesting to display seconds, MUST display minutes 1709 if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) { 1710 delete extendedSettings.omitZeroMinute; 1711 } 1712 } 1713 function postProcess(s, date, standardDateProps, extendedSettings, context) { 1714 s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes 1715 if (standardDateProps.timeZoneName === 'short') { 1716 s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ? 1717 'UTC' : // important to normalize for IE, which does "GMT" 1718 formatTimeZoneOffset(date.timeZoneOffset)); 1719 } 1720 if (extendedSettings.omitCommas) { 1721 s = s.replace(COMMA_RE, '').trim(); 1722 } 1723 if (extendedSettings.omitZeroMinute) { 1724 s = s.replace(':00', ''); // zeroFormat doesn't always achieve this 1725 } 1726 // ^ do anything that might create adjacent spaces before this point,
1727 // because MERIDIEM_RE likes to eat up loading spaces 1728 if (extendedSettings.meridiem === false) { 1729 s = s.replace(MERIDIEM_RE, '').trim(); 1730 } 1731 else if (extendedSettings.meridiem === 'narrow') { // a/p 1732 s = s.replace(MERIDIEM_RE, function (m0, m1) { 1733 return m1.toLocaleLowerCase(); 1734 }); 1735 } 1736 else if (extendedSettings.meridiem === 'short') { // am/pm 1737 s = s.replace(MERIDIEM_RE, function (m0, m1) { 1738 return m1.toLocaleLowerCase() + 'm'; 1739 }); 1740 } 1741 else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase 1742 s = s.replace(MERIDIEM_RE, function (m0) { 1743 return m0.toLocaleLowerCase(); 1744 }); 1745 } 1746 s = s.replace(MULTI_SPACE_RE, ' '); 1747 s = s.trim(); 1748 return s; 1749 } 1750 function injectTzoStr(s, tzoStr) { 1751 var replaced = false; 1752 s = s.replace(UTC_RE, function () { 1753 replaced = true; 1754 return tzoStr; 1755 }); 1756 // IE11 doesn't include UTC/GMT in the original string, so append to end 1757 if (!replaced) { 1758 s += ' ' + tzoStr; 1759 } 1760 return s; 1761 } 1762 function formatWeekNumber(num, weekLabel, locale, display) { 1763 var parts = []; 1764 if (display === 'narrow') { 1765 parts.push(weekLabel); 1766 } 1767 else if (display === 'short') { 1768 parts.push(weekLabel, ' '); 1769 } 1770 // otherwise, considered 'numeric' 1771 parts.push(locale.simpleNumberFormat.format(num)); 1772 if (locale.options.isRtl) { // TODO: use control characters instead? 1773 parts.reverse(); 1774 } 1775 return parts.join(''); 1776 } 1777 // Range Formatting Utils 1778 // 0 = exactly the same 1779 // 1 = different by time 1780 // and bigger 1781 function computeMarkerDiffSeverity(d0, d1, ca) { 1782 if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) { 1783 return 5; 1784 } 1785 if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) { 1786 return 4; 1787 } 1788 if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) { 1789 return 2; 1790 } 1791 if (timeAsMs(d0) !== timeAsMs(d1)) { 1792 return 1; 1793 } 1794 return 0; 1795 } 1796 function computePartialFormattingOptions(options, biggestUnit) { 1797 var partialOptions = {}; 1798 for (var name_2 in options) { 1799 if (!(name_2 in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone) 1800 STANDARD_DATE_PROP_SEVERITIES[name_2] <= biggestUnit) { 1801 partialOptions[name_2] = options[name_2]; 1802 } 1803 } 1804 return partialOptions; 1805 } 1806 function findCommonInsertion(full0, partial0, full1, partial1) { 1807 var i0 = 0; 1808 while (i0 < full0.length) { 1809 var found0 = full0.indexOf(partial0, i0); 1810 if (found0 === -1) { 1811 break; 1812 } 1813 var before0 = full0.substr(0, found0); 1814 i0 = found0 + partial0.length; 1815 var after0 = full0.substr(i0); 1816 var i1 = 0; 1817 while (i1 < full1.length) { 1818 var found1 = full1.indexOf(partial1, i1); 1819 if (found1 === -1) { 1820 break; 1821 } 1822 var before1 = full1.substr(0, found1); 1823 i1 = found1 + partial1.length; 1824 var after1 = full1.substr(i1); 1825 if (before0 === before1 && after0 === after1) { 1826 return { 1827 before: before0, 1828 after: after0 1829 }; 1830 } 1831 } 1832 } 1833 return null; 1834 } 1835 1836 /* 1837 TODO: fix the terminology of "formatter" vs "formatting func" 1838 */ 1839 /* 1840 At the time of instantiation, this object does not know which cmd-formatting system it will use. 1841 It receives this at the time of formatting, as a setting. 1842 */ 1843 var CmdFormatter = /** @class */ (function () { 1844 function CmdFormatter(cmdStr, separator) { 1845 this.cmdStr = cmdStr; 1846 this.separator = separator; 1847 } 1848 CmdFormatter.prototype.format = function (date, context) { 1849 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, this.separator)); 1850 }; 1851 CmdFormatter.prototype.formatRange = function (start, end, context) { 1852 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, this.separator)); 1853 }; 1854 return CmdFormatter; 1855 }()); 1856 1857 var FuncFormatter = /** @class */ (function () { 1858 function FuncFormatter(func) { 1859 this.func = func; 1860 } 1861 FuncFormatter.prototype.format = function (date, context) { 1862 return this.func(createVerboseFormattingArg(date, null, context)); 1863 }; 1864 FuncFormatter.prototype.formatRange = function (start, end, context) { 1865 return this.func(createVerboseFormattingArg(start, end, context)); 1866 }; 1867 return FuncFormatter; 1868 }()); 1869 1870 // Formatter Object Creation 1871 function createFormatter(input, defaultSeparator) { 1872 if (typeof input === 'object' && input) { // non-null object 1873 if (typeof defaultSeparator === 'string') { 1874 input = __assign({ separator: defaultSeparator }, input); 1875 } 1876 return new NativeFormatter(input); 1877 } 1878 else if (typeof input === 'string') { 1879 return new CmdFormatter(input, defaultSeparator); 1880 } 1881 else if (typeof input === 'function') { 1882 return new FuncFormatter(input); 1883 } 1884 } 1885 // String Utils 1886 // timeZoneOffset is in minutes 1887 function buildIsoString(marker, timeZoneOffset, stripZeroTime) { 1888 if (stripZeroTime === void 0) { stripZeroTime = false; } 1889 var s = marker.toISOString(); 1890 s = s.replace('.000', ''); 1891 if (stripZeroTime) { 1892 s = s.replace('T00:00:00Z', ''); 1893 } 1894 if (s.length > 10) { // time part wasn't stripped, can add timezone info 1895 if (timeZoneOffset == null) { 1896 s = s.replace('Z', ''); 1897 } 1898 else if (timeZoneOffset !== 0) { 1899 s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true)); 1900 } 1901 // otherwise, its UTC-0 and we want to keep the Z 1902 } 1903 return s; 1904 } 1905 function formatIsoTimeString(marker) { 1906 return padStart(marker.getUTCHours(), 2) + ':' + 1907 padStart(marker.getUTCMinutes(), 2) + ':' + 1908 padStart(marker.getUTCSeconds(), 2); 1909 } 1910 function formatTimeZoneOffset(minutes, doIso) { 1911 if (doIso === void 0) { doIso = false; } 1912 var sign = minutes < 0 ? '-' : '+'; 1913 var abs = Math.abs(minutes); 1914 var hours = Math.floor(abs / 60); 1915 var mins = Math.round(abs % 60); 1916 if (doIso) { 1917 return sign + padStart(hours, 2) + ':' + padStart(mins, 2); 1918 } 1919 else { 1920 return 'GMT' + sign + hours + (mins ? ':' + padStart(mins, 2) : ''); 1921 } 1922 } 1923 // Arg Utils 1924 function createVerboseFormattingArg(start, end, context, separator) { 1925 var startInfo = expandZonedMarker(start, context.calendarSystem); 1926 var endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null; 1927 return { 1928 date: startInfo, 1929 start: startInfo, 1930 end: endInfo, 1931 timeZone: context.timeZone, 1932 localeCodes: context.locale.codes, 1933 separator: separator 1934 }; 1935 } 1936 function expandZonedMarker(dateInfo, calendarSystem) { 1937 var a = calendarSystem.markerToArray(dateInfo.marker); 1938 return { 1939 marker: dateInfo.marker, 1940 timeZoneOffset: dateInfo.timeZoneOffset, 1941 array: a, 1942 year: a[0], 1943 month: a[1], 1944 day: a[2], 1945 hour: a[3], 1946 minute: a[4], 1947 second: a[5], 1948 millisecond: a[6] 1949 }; 1950 } 1951 1952 var EventSourceApi = /** @class */ (function () { 1953 function EventSourceApi(calendar, internalEventSource) { 1954 this.calendar = calendar; 1955 this.internalEventSource = internalEventSource; 1956 } 1957 EventSourceApi.prototype.remove = function () { 1958 this.calendar.dispatch({
1959 type: 'REMOVE_EVENT_SOURCE', 1960 sourceId: this.internalEventSource.sourceId 1961 }); 1962 }; 1963 EventSourceApi.prototype.refetch = function () { 1964 this.calendar.dispatch({ 1965 type: 'FETCH_EVENT_SOURCES', 1966 sourceIds: [this.internalEventSource.sourceId] 1967 }); 1968 }; 1969 Object.defineProperty(EventSourceApi.prototype, "id", { 1970 get: function () { 1971 return this.internalEventSource.publicId; 1972 }, 1973 enumerable: true, 1974 configurable: true 1975 }); 1976 Object.defineProperty(EventSourceApi.prototype, "url", { 1977 // only relevant to json-feed event sources 1978 get: function () { 1979 return this.internalEventSource.meta.url; 1980 }, 1981 enumerable: true, 1982 configurable: true 1983 }); 1984 return EventSourceApi; 1985 }()); 1986 1987 var EventApi = /** @class */ (function () { 1988 function EventApi(calendar, def, instance) { 1989 this._calendar = calendar; 1990 this._def = def; 1991 this._instance = instance || null; 1992 } 1993 /* 1994 TODO: make event struct more responsible for this 1995 */ 1996 EventApi.prototype.setProp = function (name, val) { 1997 var _a, _b; 1998 if (name in DATE_PROPS) ; 1999 else if (name in NON_DATE_PROPS) { 2000 if (typeof NON_DATE_PROPS[name] === 'function') { 2001 val = NON_DATE_PROPS[name](val); 2002 } 2003 this.mutate({ 2004 standardProps: (_a = {}, _a[name] = val, _a) 2005 }); 2006 } 2007 else if (name in UNSCOPED_EVENT_UI_PROPS) { 2008 var ui = void 0; 2009 if (typeof UNSCOPED_EVENT_UI_PROPS[name] === 'function') { 2010 val = UNSCOPED_EVENT_UI_PROPS[name](val); 2011 } 2012 if (name === 'color') { 2013 ui = { backgroundColor: val, borderColor: val }; 2014 } 2015 else if (name === 'editable') { 2016 ui = { startEditable: val, durationEditable: val }; 2017 } 2018 else { 2019 ui = (_b = {}, _b[name] = val, _b); 2020 } 2021 this.mutate({ 2022 standardProps: { ui: ui } 2023 }); 2024 } 2025 }; 2026 EventApi.prototype.setExtendedProp = function (name, val) { 2027 var _a; 2028 this.mutate({ 2029 extendedProps: (_a = {}, _a[name] = val, _a) 2030 }); 2031 }; 2032 EventApi.prototype.setStart = function (startInput, options) { 2033 if (options === void 0) { options = {}; } 2034 var dateEnv = this._calendar.dateEnv; 2035 var start = dateEnv.createMarker(startInput); 2036 if (start && this._instance) { // TODO: warning if parsed bad 2037 var instanceRange = this._instance.range; 2038 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!? 2039 var endDelta = null; 2040 if (options.maintainDuration) { 2041 var origDuration = diffDates(instanceRange.start, instanceRange.end, dateEnv, options.granularity); 2042 var newDuration = diffDates(start, instanceRange.end, dateEnv, options.granularity); 2043 endDelta = subtractDurations(origDuration, newDuration); 2044 } 2045 this.mutate({ startDelta: startDelta, endDelta: endDelta }); 2046 } 2047 }; 2048 EventApi.prototype.setEnd = function (endInput, options) { 2049 if (options === void 0) { options = {}; } 2050 var dateEnv = this._calendar.dateEnv; 2051 var end; 2052 if (endInput != null) { 2053 end = dateEnv.createMarker(endInput); 2054 if (!end) { 2055 return; // TODO: warning if parsed bad 2056 } 2057 } 2058 if (this._instance) { 2059 if (end) { 2060 var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity); 2061 this.mutate({ endDelta: endDelta }); 2062 } 2063 else { 2064 this.mutate({ standardProps: { hasEnd: false } }); 2065 } 2066 } 2067 }; 2068 EventApi.prototype.setDates = function (startInput, endInput, options) { 2069 if (options === void 0) { options = {}; } 2070 var dateEnv = this._calendar.dateEnv; 2071 var standardProps = { allDay: options.allDay }; 2072 var start = dateEnv.createMarker(startInput); 2073 var end; 2074 if (!start) { 2075 return; // TODO: warning if parsed bad 2076 } 2077 if (endInput != null) { 2078 end = dateEnv.createMarker(endInput); 2079 if (!end) { // TODO: warning if parsed bad 2080 return; 2081 } 2082 } 2083 if (this._instance) { 2084 var instanceRange = this._instance.range; 2085 // when computing the diff for an event being converted to all-day, 2086 // compute diff off of the all-day values the way event-mutation does. 2087 if (options.allDay === true) { 2088 instanceRange = computeAlignedDayRange(instanceRange); 2089 } 2090 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); 2091 if (end) { 2092 var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity); 2093 this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps }); 2094 } 2095 else { 2096 standardProps.hasEnd = false;
2097 this.mutate({ startDelta: startDelta, standardProps: standardProps }); 2098 } 2099 } 2100 }; 2101 EventApi.prototype.moveStart = function (deltaInput) { 2102 var delta = createDuration(deltaInput); 2103 if (delta) { // TODO: warning if parsed bad 2104 this.mutate({ startDelta: delta }); 2105 } 2106 }; 2107 EventApi.prototype.moveEnd = function (deltaInput) { 2108 var delta = createDuration(deltaInput); 2109 if (delta) { // TODO: warning if parsed bad 2110 this.mutate({ endDelta: delta }); 2111 } 2112 }; 2113 EventApi.prototype.moveDates = function (deltaInput) { 2114 var delta = createDuration(deltaInput); 2115 if (delta) { // TODO: warning if parsed bad 2116 this.mutate({ startDelta: delta, endDelta: delta }); 2117 } 2118 }; 2119 EventApi.prototype.setAllDay = function (allDay, options) { 2120 if (options === void 0) { options = {}; } 2121 var standardProps = { allDay: allDay }; 2122 var maintainDuration = options.maintainDuration; 2123 if (maintainDuration == null) { 2124 maintainDuration = this._calendar.opt('allDayMaintainDuration'); 2125 } 2126 if (this._def.allDay !== allDay) { 2127 standardProps.hasEnd = maintainDuration; 2128 } 2129 this.mutate({ standardProps: standardProps }); 2130 }; 2131 EventApi.prototype.formatRange = function (formatInput) { 2132 var dateEnv = this._calendar.dateEnv; 2133 var instance = this._instance; 2134 var formatter = createFormatter(formatInput, this._calendar.opt('defaultRangeSeparator')); 2135 if (this._def.hasEnd) { 2136 return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, { 2137 forcedStartTzo: instance.forcedStartTzo, 2138 forcedEndTzo: instance.forcedEndTzo 2139 }); 2140 } 2141 else { 2142 return dateEnv.format(instance.range.start, formatter, { 2143 forcedTzo: instance.forcedStartTzo 2144 }); 2145 } 2146 }; 2147 EventApi.prototype.mutate = function (mutation) { 2148 var def = this._def; 2149 var instance = this._instance; 2150 if (instance) { 2151 this._calendar.dispatch({ 2152 type: 'MUTATE_EVENTS', 2153 instanceId: instance.instanceId, 2154 mutation: mutation, 2155 fromApi: true 2156 }); 2157 var eventStore = this._calendar.state.eventStore; 2158 this._def = eventStore.defs[def.defId]; 2159 this._instance = eventStore.instances[instance.instanceId]; 2160 } 2161 }; 2162 EventApi.prototype.remove = function () { 2163 this._calendar.dispatch({ 2164 type: 'REMOVE_EVENT_DEF', 2165 defId: this._def.defId 2166 }); 2167 }; 2168 Object.defineProperty(EventApi.prototype, "source", { 2169 get: function () { 2170 var sourceId = this._def.sourceId; 2171 if (sourceId) { 2172 return new EventSourceApi(this._calendar, this._calendar.state.eventSources[sourceId]); 2173 } 2174 return null; 2175 }, 2176 enumerable: true, 2177 configurable: true 2178 }); 2179 Object.defineProperty(EventApi.prototype, "start", { 2180 get: function () { 2181 return this._instance ? 2182 this._calendar.dateEnv.toDate(this._instance.range.start) : 2183 null; 2184 }, 2185 enumerable: true, 2186 configurable: true 2187 }); 2188 Object.defineProperty(EventApi.prototype, "end", { 2189 get: function () { 2190 return (this._instance && this._def.hasEnd) ? 2191 this._calendar.dateEnv.toDate(this._instance.range.end) : 2192 null; 2193 }, 2194 enumerable: true, 2195 configurable: true 2196 }); 2197 Object.defineProperty(EventApi.prototype, "id", { 2198 // computable props that all access the def
2199 // TODO: find a TypeScript-compatible way to do this at scale 2200 get: function () { return this._def.publicId; }, 2201 enumerable: true, 2202 configurable: true 2203 }); 2204 Object.defineProperty(EventApi.prototype, "groupId", { 2205 get: function () { return this._def.groupId; }, 2206 enumerable: true, 2207 configurable: true 2208 }); 2209 Object.defineProperty(EventApi.prototype, "allDay", { 2210 get: function () { return this._def.allDay; }, 2211 enumerable: true, 2212 configurable: true 2213 }); 2214 Object.defineProperty(EventApi.prototype, "title", { 2215 get: function () { return this._def.title; }, 2216 enumerable: true, 2217 configurable: true 2218 }); 2219 Object.defineProperty(EventApi.prototype, "url", { 2220 get: function () { return this._def.url; }, 2221 enumerable: true, 2222 configurable: true 2223 }); 2224 Object.defineProperty(EventApi.prototype, "rendering", { 2225 get: function () { return this._def.rendering; }, 2226 enumerable: true, 2227 configurable: true 2228 }); 2229 Object.defineProperty(EventApi.prototype, "startEditable", { 2230 get: function () { return this._def.ui.startEditable; }, 2231 enumerable: true, 2232 configurable: true 2233 }); 2234 Object.defineProperty(EventApi.prototype, "durationEditable", { 2235 get: function () { return this._def.ui.durationEditable; }, 2236 enumerable: true, 2237 configurable: true 2238 }); 2239 Object.defineProperty(EventApi.prototype, "constraint", { 2240 get: function () { return this._def.ui.constraints[0] || null; }, 2241 enumerable: true, 2242 configurable: true 2243 }); 2244 Object.defineProperty(EventApi.prototype, "overlap", { 2245 get: function () { return this._def.ui.overlap; }, 2246 enumerable: true, 2247 configurable: true 2248 }); 2249 Object.defineProperty(EventApi.prototype, "allow", { 2250 get: function () { return this._def.ui.allows[0] || null; }, 2251 enumerable: true, 2252 configurable: true 2253 }); 2254 Object.defineProperty(EventApi.prototype, "backgroundColor", { 2255 get: function () { return this._def.ui.backgroundColor; }, 2256 enumerable: true, 2257 configurable: true 2258 }); 2259 Object.defineProperty(EventApi.prototype, "borderColor", { 2260 get: function () { return this._def.ui.borderColor; }, 2261 enumerable: true, 2262 configurable: true 2263 }); 2264 Object.defineProperty(EventApi.prototype, "textColor", { 2265 get: function () { return this._def.ui.textColor; }, 2266 enumerable: true, 2267 configurable: true 2268 }); 2269 Object.defineProperty(EventApi.prototype, "classNames", { 2270 // NOTE: user can't modify these because Object.freeze was called in event-def parsing 2271 get: function () { return this._def.ui.classNames; }, 2272 enumerable: true, 2273 configurable: true 2274 }); 2275 Object.defineProperty(EventApi.prototype, "extendedProps", { 2276 get: function () { return this._def.extendedProps; }, 2277 enumerable: true, 2278 configurable: true 2279 }); 2280 return EventApi; 2281 }()); 2282 2283 /* 2284 Specifying nextDayThreshold signals that all-day ranges should be sliced. 2285 */ 2286 function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) { 2287 var inverseBgByGroupId = {}; 2288 var inverseBgByDefId = {}; 2289 var defByGroupId = {}; 2290 var bgRanges = []; 2291 var fgRanges = []; 2292 var eventUis = compileEventUis(eventStore.defs, eventUiBases); 2293 for (var defId in eventStore.defs) { 2294 var def = eventStore.defs[defId]; 2295 if (def.rendering === 'inverse-background') { 2296 if (def.groupId) { 2297 inverseBgByGroupId[def.groupId] = []; 2298 if (!defByGroupId[def.groupId]) { 2299 defByGroupId[def.groupId] = def; 2300 } 2301 } 2302 else { 2303 inverseBgByDefId[defId] = []; 2304 } 2305 } 2306 } 2307 for (var instanceId in eventStore.instances) { 2308 var instance = eventStore.instances[instanceId]; 2309 var def = eventStore.defs[instance.defId]; 2310 var ui = eventUis[def.defId]; 2311 var origRange = instance.range; 2312 var normalRange = (!def.allDay && nextDayThreshold) ? 2313 computeVisibleDayRange(origRange, nextDayThreshold) : 2314 origRange; 2315 var slicedRange = intersectRanges(normalRange, framingRange); 2316 if (slicedRange) { 2317 if (def.rendering === 'inverse-background') { 2318 if (def.groupId) { 2319 inverseBgByGroupId[def.groupId].push(slicedRange); 2320 } 2321 else { 2322 inverseBgByDefId[instance.defId].push(slicedRange); 2323 } 2324 } 2325 else { 2326 (def.rendering === 'background' ? bgRanges : fgRanges).push({ 2327 def: def, 2328 ui: ui, 2329 instance: instance, 2330 range: slicedRange, 2331 isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(), 2332 isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf() 2333 }); 2334 } 2335 } 2336 } 2337 for (var groupId in inverseBgByGroupId) { // BY GROUP 2338 var ranges = inverseBgByGroupId[groupId]; 2339 var invertedRanges = invertRanges(ranges, framingRange); 2340 for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) { 2341 var invertedRange = invertedRanges_1[_i]; 2342 var def = defByGroupId[groupId]; 2343 var ui = eventUis[def.defId]; 2344 bgRanges.push({ 2345 def: def, 2346 ui: ui, 2347 instance: null, 2348 range: invertedRange, 2349 isStart: false, 2350 isEnd: false 2351 }); 2352 } 2353 } 2354 for (var defId in inverseBgByDefId) { 2355 var ranges = inverseBgByDefId[defId]; 2356 var invertedRanges = invertRanges(ranges, framingRange); 2357 for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) { 2358 var invertedRange = invertedRanges_2[_a]; 2359 bgRanges.push({ 2360 def: eventStore.defs[defId], 2361 ui: eventUis[defId], 2362 instance: null, 2363 range: invertedRange, 2364 isStart: false, 2365 isEnd: false 2366 }); 2367 } 2368 } 2369 return { bg: bgRanges, fg: fgRanges }; 2370 } 2371 function hasBgRendering(def) { 2372 return def.rendering === 'background' || def.rendering === 'inverse-background'; 2373 } 2374 function filterSegsViaEls(view, segs, isMirror) { 2375 if (view.hasPublicHandlers('eventRender')) { 2376 segs = segs.filter(function (seg) { 2377 var custom = view.publiclyTrigger('eventRender', [ 2378 { 2379 event: new EventApi(view.calendar, seg.eventRange.def, seg.eventRange.instance), 2380 isMirror: isMirror, 2381 isStart: seg.isStart, 2382 isEnd: seg.isEnd, 2383 // TODO: include seg.range once all components consistently generate it 2384 el: seg.el, 2385 view: view 2386 } 2387 ]); 2388 if (custom === false) { // means don't render at all 2389 return false;
2390 } 2391 else if (custom && custom !== true) { 2392 seg.el = custom; 2393 } 2394 return true; 2395 }); 2396 } 2397 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 2398 var seg = segs_1[_i]; 2399 setElSeg(seg.el, seg); 2400 } 2401 return segs; 2402 } 2403 function setElSeg(el, seg) { 2404 el.fcSeg = seg; 2405 } 2406 function getElSeg(el) { 2407 return el.fcSeg || null; 2408 } 2409 // event ui computation 2410 function compileEventUis(eventDefs, eventUiBases) { 2411 return mapHash(eventDefs, function (eventDef) { 2412 return compileEventUi(eventDef, eventUiBases); 2413 }); 2414 } 2415 function compileEventUi(eventDef, eventUiBases) { 2416 var uis = []; 2417 if (eventUiBases['']) { 2418 uis.push(eventUiBases['']); 2419 } 2420 if (eventUiBases[eventDef.defId]) { 2421 uis.push(eventUiBases[eventDef.defId]); 2422 } 2423 uis.push(eventDef.ui); 2424 return combineEventUis(uis); 2425 } 2426 2427 // applies the mutation to ALL defs/instances within the event store 2428 function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) { 2429 var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase); 2430 var dest = createEmptyEventStore(); 2431 for (var defId in eventStore.defs) { 2432 var def = eventStore.defs[defId]; 2433 dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, calendar.pluginSystem.hooks.eventDefMutationAppliers, calendar); 2434 } 2435 for (var instanceId in eventStore.instances) { 2436 var instance = eventStore.instances[instanceId]; 2437 var def = dest.defs[instance.defId]; // important to grab the newly modified def 2438 dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, calendar); 2439 } 2440 return dest; 2441 } 2442 function applyMutationToEventDef(eventDef, eventConfig, mutation, appliers, calendar) { 2443 var standardProps = mutation.standardProps || {}; 2444 // if hasEnd has not been specified, guess a good value based on deltas. 2445 // if duration will change, there's no way the default duration will persist, 2446 // and thus, we need to mark the event as having a real end 2447 if (standardProps.hasEnd == null && 2448 eventConfig.durationEditable && 2449 willDeltasAffectDuration(eventConfig.startEditable ? mutation.startDelta : null, mutation.endDelta || null)) { 2450 standardProps.hasEnd = true; // TODO: is this mutation okay? 2451 } 2452 var copy = __assign({}, eventDef, standardProps, { ui: __assign({}, eventDef.ui, standardProps.ui) }); 2453 if (mutation.extendedProps) { 2454 copy.extendedProps = __assign({}, copy.extendedProps, mutation.extendedProps); 2455 } 2456 for (var _i = 0, appliers_1 = appliers; _i < appliers_1.length; _i++) { 2457 var applier = appliers_1[_i]; 2458 applier(copy, mutation, calendar); 2459 } 2460 if (!copy.hasEnd && calendar.opt('forceEventDuration')) { 2461 copy.hasEnd = true; 2462 } 2463 return copy; 2464 } 2465 function willDeltasAffectDuration(startDelta, endDelta) { 2466 if (startDelta && !asRoughMs(startDelta)) { 2467 startDelta = null; 2468 } 2469 if (endDelta && !asRoughMs(endDelta)) { 2470 endDelta = null; 2471 } 2472 if (!startDelta && !endDelta) { 2473 return false; 2474 } 2475 if (Boolean(startDelta) !== Boolean(endDelta)) { 2476 return true; 2477 } 2478 return !durationsEqual(startDelta, endDelta); 2479 } 2480 function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef 2481 eventConfig, mutation, calendar) { 2482 var dateEnv = calendar.dateEnv; 2483 var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true; 2484 var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false; 2485 var copy = __assign({}, eventInstance); 2486 if (forceAllDay) { 2487 copy.range = computeAlignedDayRange(copy.range); 2488 } 2489 if (mutation.startDelta && eventConfig.startEditable) { 2490 copy.range = { 2491 start: dateEnv.add(copy.range.start, mutation.startDelta), 2492 end: copy.range.end 2493 }; 2494 } 2495 if (clearEnd) { 2496 copy.range = { 2497 start: copy.range.start, 2498 end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start) 2499 }; 2500 } 2501 else if (mutation.endDelta && 2502 (eventConfig.durationEditable || 2503 !willDeltasAffectDuration(// TODO: nonDRY logic above 2504 eventConfig.startEditable ? mutation.startDelta : null, mutation.endDelta))) { 2505 copy.range = { 2506 start: copy.range.start, 2507 end: dateEnv.add(copy.range.end, mutation.endDelta) 2508 }; 2509 } 2510 // in case event was all-day but the supplied deltas were not 2511 // better util for this? 2512 if (eventDef.allDay) { 2513 copy.range = { 2514 start: startOfDay(copy.range.start), 2515 end: startOfDay(copy.range.end) 2516 }; 2517 } 2518 // handle invalid durations 2519 if (copy.range.end < copy.range.start) { 2520 copy.range.end = calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start); 2521 } 2522 return copy; 2523 } 2524 2525 function reduceEventStore (eventStore, action, eventSources, dateProfile, calendar) { 2526 switch (action.type) { 2527 case 'RECEIVE_EVENTS': // raw 2528 return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, calendar); 2529 case 'ADD_EVENTS': // already parsed, but not expanded 2530 return addEvent(eventStore, action.eventStore, // new ones 2531 dateProfile ? dateProfile.activeRange : null, calendar); 2532 case 'MERGE_EVENTS': // already parsed and expanded 2533 return mergeEventStores(eventStore, action.eventStore); 2534 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 2535 case 'NEXT': 2536 case 'SET_DATE': 2537 case 'SET_VIEW_TYPE': 2538 if (dateProfile) { 2539 return expandRecurring(eventStore, dateProfile.activeRange, calendar); 2540 } 2541 else { 2542 return eventStore; 2543 } 2544 case 'CHANGE_TIMEZONE': 2545 return rezoneDates(eventStore, action.oldDateEnv, calendar.dateEnv); 2546 case 'MUTATE_EVENTS': 2547 return applyMutationToRelated(eventStore, action.instanceId, action.mutation, action.fromApi, calendar);
2548 case 'REMOVE_EVENT_INSTANCES': 2549 return excludeInstances(eventStore, action.instances); 2550 case 'REMOVE_EVENT_DEF': 2551 return filterEventStoreDefs(eventStore, function (eventDef) { 2552 return eventDef.defId !== action.defId; 2553 }); 2554 case 'REMOVE_EVENT_SOURCE': 2555 return excludeEventsBySourceId(eventStore, action.sourceId); 2556 case 'REMOVE_ALL_EVENT_SOURCES': 2557 return filterEventStoreDefs(eventStore, function (eventDef) { 2558 return !eventDef.sourceId; // only keep events with no source id 2559 }); 2560 case 'REMOVE_ALL_EVENTS': 2561 return createEmptyEventStore(); 2562 case 'RESET_EVENTS': 2563 return { 2564 defs: eventStore.defs, 2565 instances: eventStore.instances 2566 }; 2567 default: 2568 return eventStore; 2569 } 2570 } 2571 function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, calendar) { 2572 if (eventSource && // not already removed 2573 fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources 2574 ) { 2575 var subset = parseEvents(transformRawEvents(rawEvents, eventSource, calendar), eventSource.sourceId, calendar); 2576 if (fetchRange) { 2577 subset = expandRecurring(subset, fetchRange, calendar); 2578 } 2579 return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset); 2580 } 2581 return eventStore; 2582 } 2583 function addEvent(eventStore, subset, expandRange, calendar) { 2584 if (expandRange) { 2585 subset = expandRecurring(subset, expandRange, calendar); 2586 } 2587 return mergeEventStores(eventStore, subset); 2588 } 2589 function rezoneDates(eventStore, oldDateEnv, newDateEnv) { 2590 var defs = eventStore.defs; 2591 var instances = mapHash(eventStore.instances, function (instance) { 2592 var def = defs[instance.defId]; 2593 if (def.allDay || def.recurringDef) { 2594 return instance; // isn't dependent on timezone 2595 } 2596 else { 2597 return __assign({}, instance, { range: { 2598 start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)), 2599 end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)) 2600 }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo }); 2601 } 2602 }); 2603 return { defs: defs, instances: instances }; 2604 } 2605 function applyMutationToRelated(eventStore, instanceId, mutation, fromApi, calendar) { 2606 var relevant = getRelevantEvents(eventStore, instanceId); 2607 var eventConfigBase = fromApi ? 2608 { '': { 2609 startEditable: true, 2610 durationEditable: true, 2611 constraints: [], 2612 overlap: null, 2613 allows: [], 2614 backgroundColor: '', 2615 borderColor: '', 2616 textColor: '', 2617 classNames: [] 2618 } } : 2619 calendar.eventUiBases; 2620 relevant = applyMutationToEventStore(relevant, eventConfigBase, mutation, calendar); 2621 return mergeEventStores(eventStore, relevant); 2622 } 2623 function excludeEventsBySourceId(eventStore, sourceId) { 2624 return filterEventStoreDefs(eventStore, function (eventDef) { 2625 return eventDef.sourceId !== sourceId; 2626 }); 2627 } 2628 // QUESTION: why not just return instances? do a general object-property-exclusion util 2629 function excludeInstances(eventStore, removals) { 2630 return { 2631 defs: eventStore.defs, 2632 instances: filterHash(eventStore.instances, function (instance) { 2633 return !removals[instance.instanceId]; 2634 }) 2635 }; 2636 } 2637 2638 // high-level segmenting-aware tester functions 2639 // ------------------------------------------------------------------------------------------------------------------------ 2640 function isInteractionValid(interaction, calendar) { 2641 return isNewPropsValid({ eventDrag: interaction }, calendar); // HACK: the eventDrag props is used for ALL interactions 2642 } 2643 function isDateSelectionValid(dateSelection, calendar) { 2644 return isNewPropsValid({ dateSelection: dateSelection }, calendar); 2645 } 2646 function isNewPropsValid(newProps, calendar) { 2647 var view = calendar.view; 2648 var props = __assign({ businessHours: view ? view.props.businessHours : createEmptyEventStore(), dateSelection: '', eventStore: calendar.state.eventStore, eventUiBases: calendar.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps); 2649 return (calendar.pluginSystem.hooks.isPropsValid || isPropsValid)(props, calendar); 2650 } 2651 function isPropsValid(state, calendar, dateSpanMeta, filterConfig) {
2652 if (dateSpanMeta === void 0) { dateSpanMeta = {}; } 2653 if (state.eventDrag && !isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { 2654 return false; 2655 } 2656 if (state.dateSelection && !isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { 2657 return false; 2658 } 2659 return true; 2660 } 2661 // Moving Event Validation 2662 // ------------------------------------------------------------------------------------------------------------------------ 2663 function isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig) { 2664 var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions 2665 var subjectEventStore = interaction.mutatedEvents; 2666 var subjectDefs = subjectEventStore.defs; 2667 var subjectInstances = subjectEventStore.instances; 2668 var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ? 2669 state.eventUiBases : 2670 { '': calendar.selectionConfig } // if not a real event, validate as a selection 2671 ); 2672 if (filterConfig) { 2673 subjectConfigs = mapHash(subjectConfigs, filterConfig); 2674 } 2675 var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); // exclude the subject events. TODO: exclude defs too? 2676 var otherDefs = otherEventStore.defs; 2677 var otherInstances = otherEventStore.instances; 2678 var otherConfigs = compileEventUis(otherDefs, state.eventUiBases); 2679 for (var subjectInstanceId in subjectInstances) { 2680 var subjectInstance = subjectInstances[subjectInstanceId]; 2681 var subjectRange = subjectInstance.range; 2682 var subjectConfig = subjectConfigs[subjectInstance.defId]; 2683 var subjectDef = subjectDefs[subjectInstance.defId]; 2684 // constraint 2685 if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, calendar)) { 2686 return false; 2687 } 2688 // overlap 2689 var overlapFunc = calendar.opt('eventOverlap'); 2690 if (typeof overlapFunc !== 'function') { 2691 overlapFunc = null; 2692 } 2693 for (var otherInstanceId in otherInstances) { 2694 var otherInstance = otherInstances[otherInstanceId]; 2695 // intersect! evaluate 2696 if (rangesIntersect(subjectRange, otherInstance.range)) { 2697 var otherOverlap = otherConfigs[otherInstance.defId].overlap; 2698 // consider the other event's overlap. only do this if the subject event is a "real" event 2699 if (otherOverlap === false && interaction.isEvent) { 2700 return false; 2701 } 2702 if (subjectConfig.overlap === false) { 2703 return false; 2704 } 2705 if (overlapFunc && !overlapFunc(new EventApi(calendar, otherDefs[otherInstance.defId], otherInstance), // still event 2706 new EventApi(calendar, subjectDef, subjectInstance) // moving event 2707 )) { 2708 return false; 2709 } 2710 } 2711 } 2712 // allow (a function) 2713 for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) { 2714 var subjectAllow = _a[_i]; 2715 var subjectDateSpan = __assign({}, dateSpanMeta, { range: subjectInstance.range, allDay: subjectDef.allDay }); 2716 var origDef = state.eventStore.defs[subjectDef.defId]; 2717 var origInstance = state.eventStore.instances[subjectInstanceId]; 2718 var eventApi = void 0; 2719 if (origDef) { // was previously in the calendar 2720 eventApi = new EventApi(calendar, origDef, origInstance); 2721 } 2722 else { // was an external event 2723 eventApi = new EventApi(calendar, subjectDef); // no instance, because had no dates 2724 } 2725 if (!subjectAllow(calendar.buildDateSpanApi(subjectDateSpan), eventApi)) { 2726 return false;
2727 } 2728 } 2729 } 2730 return true; 2731 } 2732 // Date Selection Validation 2733 // ------------------------------------------------------------------------------------------------------------------------ 2734 function isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig) { 2735 var relevantEventStore = state.eventStore; 2736 var relevantDefs = relevantEventStore.defs; 2737 var relevantInstances = relevantEventStore.instances; 2738 var selection = state.dateSelection; 2739 var selectionRange = selection.range; 2740 var selectionConfig = calendar.selectionConfig; 2741 if (filterConfig) { 2742 selectionConfig = filterConfig(selectionConfig); 2743 } 2744 // constraint 2745 if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, calendar)) { 2746 return false; 2747 } 2748 // overlap 2749 var overlapFunc = calendar.opt('selectOverlap'); 2750 if (typeof overlapFunc !== 'function') { 2751 overlapFunc = null; 2752 } 2753 for (var relevantInstanceId in relevantInstances) { 2754 var relevantInstance = relevantInstances[relevantInstanceId]; 2755 // intersect! evaluate 2756 if (rangesIntersect(selectionRange, relevantInstance.range)) { 2757 if (selectionConfig.overlap === false) { 2758 return false; 2759 } 2760 if (overlapFunc && !overlapFunc(new EventApi(calendar, relevantDefs[relevantInstance.defId], relevantInstance))) { 2761 return false; 2762 } 2763 } 2764 } 2765 // allow (a function) 2766 for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) { 2767 var selectionAllow = _a[_i]; 2768 var fullDateSpan = __assign({}, dateSpanMeta, selection); 2769 if (!selectionAllow(calendar.buildDateSpanApi(fullDateSpan), null)) { 2770 return false; 2771 } 2772 } 2773 return true; 2774 } 2775 // Constraint Utils 2776 // ------------------------------------------------------------------------------------------------------------------------ 2777 function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, calendar) { 2778 for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) { 2779 var constraint = constraints_1[_i]; 2780 if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, calendar), subjectRange)) { 2781 return false; 2782 } 2783 } 2784 return true; 2785 } 2786 function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours 2787 otherEventStore, // for if constraint is an even group ID 2788 businessHoursUnexpanded, // for if constraint is 'businessHours' 2789 calendar // for expanding businesshours 2790 ) { 2791 if (constraint === 'businessHours') { 2792 return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, calendar)); 2793 } 2794 else if (typeof constraint === 'string') { // an group ID 2795 return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) { 2796 return eventDef.groupId === constraint; 2797 })); 2798 } 2799 else if (typeof constraint === 'object' && constraint) { // non-null object 2800 return eventStoreToRanges(expandRecurring(constraint, subjectRange, calendar)); 2801 } 2802 return []; // if it's false 2803 } 2804 // TODO: move to event-store file? 2805 function eventStoreToRanges(eventStore) { 2806 var instances = eventStore.instances; 2807 var ranges = []; 2808 for (var instanceId in instances) { 2809 ranges.push(instances[instanceId].range); 2810 } 2811 return ranges; 2812 } 2813 // TODO: move to geom file? 2814 function anyRangesContainRange(outerRanges, innerRange) { 2815 for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) { 2816 var outerRange = outerRanges_1[_i]; 2817 if (rangeContainsRange(outerRange, innerRange)) { 2818 return true; 2819 } 2820 } 2821 return false;
2822 } 2823 // Parsing 2824 // ------------------------------------------------------------------------------------------------------------------------ 2825 function normalizeConstraint(input, calendar) { 2826 if (Array.isArray(input)) { 2827 return parseEvents(input, '', calendar, true); // allowOpenRange=true 2828 } 2829 else if (typeof input === 'object' && input) { // non-null object 2830 return parseEvents([input], '', calendar, true); // allowOpenRange=true 2831 } 2832 else if (input != null) { 2833 return String(input); 2834 } 2835 else { 2836 return null; 2837 } 2838 } 2839 2840 function htmlEscape(s) { 2841 return (s + '').replace(/&/g, '&') 2842 .replace(/</g, '<') 2843 .replace(/>/g, '>') 2844 .replace(/'/g, ''') 2845 .replace(/"/g, '"') 2846 .replace(/\n/g, '<br />'); 2847 } 2848 // Given a hash of CSS properties, returns a string of CSS. 2849 // Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values. 2850 function cssToStr(cssProps) { 2851 var statements = []; 2852 for (var name_1 in cssProps) { 2853 var val = cssProps[name_1]; 2854 if (val != null && val !== '') { 2855 statements.push(name_1 + ':' + val); 2856 } 2857 } 2858 return statements.join(';'); 2859 } 2860 // Given an object hash of HTML attribute names to values, 2861 // generates a string that can be injected between < > in HTML 2862 function attrsToStr(attrs) { 2863 var parts = []; 2864 for (var name_2 in attrs) { 2865 var val = attrs[name_2]; 2866 if (val != null) { 2867 parts.push(name_2 + '="' + htmlEscape(val) + '"'); 2868 } 2869 } 2870 return parts.join(' '); 2871 } 2872 function parseClassName(raw) { 2873 if (Array.isArray(raw)) { 2874 return raw; 2875 } 2876 else if (typeof raw === 'string') { 2877 return raw.split(/\s+/); 2878 } 2879 else { 2880 return []; 2881 } 2882 } 2883 2884 var UNSCOPED_EVENT_UI_PROPS = { 2885 editable: Boolean, 2886 startEditable: Boolean, 2887 durationEditable: Boolean, 2888 constraint: null, 2889 overlap: null, 2890 allow: null, 2891 className: parseClassName, 2892 classNames: parseClassName, 2893 color: String, 2894 backgroundColor: String, 2895 borderColor: String, 2896 textColor: String 2897 }; 2898 function processUnscopedUiProps(rawProps, calendar, leftovers) { 2899 var props = refineProps(rawProps, UNSCOPED_EVENT_UI_PROPS, {}, leftovers); 2900 var constraint = normalizeConstraint(props.constraint, calendar); 2901 return { 2902 startEditable: props.startEditable != null ? props.startEditable : props.editable, 2903 durationEditable: props.durationEditable != null ? props.durationEditable : props.editable, 2904 constraints: constraint != null ? [constraint] : [], 2905 overlap: props.overlap, 2906 allows: props.allow != null ? [props.allow] : [], 2907 backgroundColor: props.backgroundColor || props.color, 2908 borderColor: props.borderColor || props.color, 2909 textColor: props.textColor, 2910 classNames: props.classNames.concat(props.className) 2911 }; 2912 } 2913 function processScopedUiProps(prefix, rawScoped, calendar, leftovers) { 2914 var rawUnscoped = {}; 2915 var wasFound = {}; 2916 for (var key in UNSCOPED_EVENT_UI_PROPS) { 2917 var scopedKey = prefix + capitaliseFirstLetter(key); 2918 rawUnscoped[key] = rawScoped[scopedKey]; 2919 wasFound[scopedKey] = true; 2920 } 2921 if (prefix === 'event') { 2922 rawUnscoped.editable = rawScoped.editable; // special case. there is no 'eventEditable', just 'editable' 2923 } 2924 if (leftovers) { 2925 for (var key in rawScoped) { 2926 if (!wasFound[key]) { 2927 leftovers[key] = rawScoped[key]; 2928 } 2929 } 2930 } 2931 return processUnscopedUiProps(rawUnscoped, calendar); 2932 } 2933 var EMPTY_EVENT_UI = { 2934 startEditable: null, 2935 durationEditable: null, 2936 constraints: [], 2937 overlap: null, 2938 allows: [], 2939 backgroundColor: '', 2940 borderColor: '', 2941 textColor: '', 2942 classNames: [] 2943 }; 2944 // prevent against problems with <2 args! 2945 function combineEventUis(uis) { 2946 return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI); 2947 } 2948 function combineTwoEventUis(item0, item1) { 2949 return { 2950 startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable, 2951 durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable, 2952 constraints: item0.constraints.concat(item1.constraints), 2953 overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap, 2954 allows: item0.allows.concat(item1.allows), 2955 backgroundColor: item1.backgroundColor || item0.backgroundColor, 2956 borderColor: item1.borderColor || item0.borderColor, 2957 textColor: item1.textColor || item0.textColor,
2958 classNames: item0.classNames.concat(item1.classNames) 2959 }; 2960 } 2961 2962 var NON_DATE_PROPS = { 2963 id: String, 2964 groupId: String, 2965 title: String, 2966 url: String, 2967 rendering: String, 2968 extendedProps: null 2969 }; 2970 var DATE_PROPS = { 2971 start: null, 2972 date: null, 2973 end: null, 2974 allDay: null 2975 }; 2976 var uid = 0; 2977 function parseEvent(raw, sourceId, calendar, allowOpenRange) { 2978 var allDayDefault = computeIsAllDayDefault(sourceId, calendar); 2979 var leftovers0 = {}; 2980 var recurringRes = parseRecurring(raw, // raw, but with single-event stuff stripped out 2981 allDayDefault, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes, leftovers0 // will populate with non-recurring props 2982 ); 2983 if (recurringRes) { 2984 var def = parseEventDef(leftovers0, sourceId, recurringRes.allDay, Boolean(recurringRes.duration), calendar); 2985 def.recurringDef = { 2986 typeId: recurringRes.typeId, 2987 typeData: recurringRes.typeData, 2988 duration: recurringRes.duration 2989 }; 2990 return { def: def, instance: null }; 2991 } 2992 else { 2993 var leftovers1 = {}; 2994 var singleRes = parseSingle(raw, allDayDefault, calendar, leftovers1, allowOpenRange); 2995 if (singleRes) { 2996 var def = parseEventDef(leftovers1, sourceId, singleRes.allDay, singleRes.hasEnd, calendar); 2997 var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo); 2998 return { def: def, instance: instance }; 2999 } 3000 } 3001 return null; 3002 } 3003 /* 3004 Will NOT populate extendedProps with the leftover properties. 3005 Will NOT populate date-related props. 3006 The EventNonDateInput has been normalized (id => publicId, etc). 3007 */ 3008 function parseEventDef(raw, sourceId, allDay, hasEnd, calendar) { 3009 var leftovers = {}; 3010 var def = pluckNonDateProps(raw, calendar, leftovers); 3011 def.defId = String(uid++); 3012 def.sourceId = sourceId; 3013 def.allDay = allDay; 3014 def.hasEnd = hasEnd; 3015 for (var _i = 0, _a = calendar.pluginSystem.hooks.eventDefParsers; _i < _a.length; _i++) { 3016 var eventDefParser = _a[_i]; 3017 var newLeftovers = {}; 3018 eventDefParser(def, leftovers, newLeftovers); 3019 leftovers = newLeftovers; 3020 } 3021 def.extendedProps = __assign(leftovers, def.extendedProps || {}); 3022 // help out EventApi from having user modify props 3023 Object.freeze(def.ui.classNames); 3024 Object.freeze(def.extendedProps); 3025 return def; 3026 } 3027 function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) { 3028 return { 3029 instanceId: String(uid++), 3030 defId: defId, 3031 range: range, 3032 forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo, 3033 forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo 3034 }; 3035 } 3036 function parseSingle(raw, allDayDefault, calendar, leftovers, allowOpenRange) { 3037 var props = pluckDateProps(raw, leftovers); 3038 var allDay = props.allDay; 3039 var startMeta; 3040 var startMarker = null; 3041 var hasEnd = false; 3042 var endMeta; 3043 var endMarker = null; 3044 startMeta = calendar.dateEnv.createMarkerMeta(props.start); 3045 if (startMeta) { 3046 startMarker = startMeta.marker; 3047 } 3048 else if (!allowOpenRange) { 3049 return null; 3050 } 3051 if (props.end != null) { 3052 endMeta = calendar.dateEnv.createMarkerMeta(props.end); 3053 } 3054 if (allDay == null) { 3055 if (allDayDefault != null) { 3056 allDay = allDayDefault; 3057 } 3058 else { 3059 // fall back to the date props LAST 3060 allDay = (!startMeta || startMeta.isTimeUnspecified) && 3061 (!endMeta || endMeta.isTimeUnspecified); 3062 } 3063 } 3064 if (allDay && startMarker) { 3065 startMarker = startOfDay(startMarker); 3066 } 3067 if (endMeta) { 3068 endMarker = endMeta.marker; 3069 if (allDay) { 3070 endMarker = startOfDay(endMarker); 3071 } 3072 if (startMarker && endMarker <= startMarker) { 3073 endMarker = null; 3074 } 3075 } 3076 if (endMarker) { 3077 hasEnd = true; 3078 } 3079 else if (!allowOpenRange) { 3080 hasEnd = calendar.opt('forceEventDuration') || false; 3081 endMarker = calendar.dateEnv.add(startMarker, allDay ? 3082 calendar.defaultAllDayEventDuration : 3083 calendar.defaultTimedEventDuration); 3084 } 3085 return { 3086 allDay: allDay, 3087 hasEnd: hasEnd, 3088 range: { start: startMarker, end: endMarker }, 3089 forcedStartTzo: startMeta ? startMeta.forcedTzo : null, 3090 forcedEndTzo: endMeta ? endMeta.forcedTzo : null 3091 }; 3092 } 3093 function pluckDateProps(raw, leftovers) { 3094 var props = refineProps(raw, DATE_PROPS, {}, leftovers); 3095 props.start = (props.start !== null) ? props.start : props.date; 3096 delete props.date; 3097 return props; 3098 } 3099 function pluckNonDateProps(raw, calendar, leftovers) { 3100 var preLeftovers = {}; 3101 var props = refineProps(raw, NON_DATE_PROPS, {}, preLeftovers); 3102 var ui = processUnscopedUiProps(preLeftovers, calendar, leftovers); 3103 props.publicId = props.id; 3104 delete props.id; 3105 props.ui = ui; 3106 return props; 3107 } 3108 function computeIsAllDayDefault(sourceId, calendar) { 3109 var res = null; 3110 if (sourceId) { 3111 var source = calendar.state.eventSources[sourceId]; 3112 res = source.allDayDefault; 3113 } 3114 if (res == null) { 3115 res = calendar.opt('allDayDefault'); 3116 } 3117 return res; 3118 } 3119 3120 var DEF_DEFAULTS = { 3121 startTime: '09:00', 3122 endTime: '17:00', 3123 daysOfWeek: [1, 2, 3, 4, 5], 3124 rendering: 'inverse-background', 3125 classNames: 'fc-nonbusiness', 3126 groupId: '_businessHours' // so multiple defs get grouped 3127 }; 3128 /* 3129 TODO: pass around as EventDefHash!!! 3130 */ 3131 function parseBusinessHours(input, calendar) { 3132 return parseEvents(refineInputs(input), '', calendar); 3133 } 3134 function refineInputs(input) { 3135 var rawDefs; 3136 if (input === true) { 3137 rawDefs = [{}]; // will get DEF_DEFAULTS verbatim 3138 } 3139 else if (Array.isArray(input)) { 3140 // if specifying an array, every sub-definition NEEDS a day-of-week 3141 rawDefs = input.filter(function (rawDef) { 3142 return rawDef.daysOfWeek; 3143 }); 3144 } 3145 else if (typeof input === 'object' && input) { // non-null object 3146 rawDefs = [input]; 3147 } 3148 else { // is probably false 3149 rawDefs = []; 3150 } 3151 rawDefs = rawDefs.map(function (rawDef) { 3152 return __assign({}, DEF_DEFAULTS, rawDef); 3153 }); 3154 return rawDefs; 3155 } 3156 3157 function memoizeRendering(renderFunc, unrenderFunc, dependencies) { 3158 if (dependencies === void 0) { dependencies = []; } 3159 var dependents = []; 3160 var thisContext; 3161 var prevArgs; 3162 function unrender() { 3163 if (prevArgs) {
3164 for (var _i = 0, dependents_1 = dependents; _i < dependents_1.length; _i++) { 3165 var dependent = dependents_1[_i]; 3166 dependent.unrender(); 3167 } 3168 if (unrenderFunc) { 3169 unrenderFunc.apply(thisContext, prevArgs); 3170 } 3171 prevArgs = null; 3172 } 3173 } 3174 function res() { 3175 if (!prevArgs || !isArraysEqual(prevArgs, arguments)) { 3176 unrender(); 3177 thisContext = this; 3178 prevArgs = arguments; 3179 renderFunc.apply(this, arguments); 3180 } 3181 } 3182 res.dependents = dependents; 3183 res.unrender = unrender; 3184 for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) { 3185 var dependency = dependencies_1[_i]; 3186 dependency.dependents.push(res); 3187 } 3188 return res; 3189 } 3190 3191 function isValuesSimilar(val0, val1, depth) { 3192 if (depth === void 0) { depth = 1; } 3193 if (val0 === val1) { 3194 return true; 3195 } 3196 else if (Array.isArray(val0) && Array.isArray(val1)) { 3197 return isArraysSimilar(val0, val1, depth); 3198 } 3199 else if (typeof val0 === 'object' && val0 && typeof val1 === 'object' && val1) { // non-null objects 3200 return isObjectsSimilar(val0, val1, depth); 3201 } 3202 else { 3203 return false; 3204 } 3205 } 3206 function isArraysSimilar(a0, a1, depth) { 3207 if (depth === void 0) { depth = 1; } 3208 if (a0 === a1) { 3209 return true; 3210 } 3211 else if (depth > 0) { 3212 if (a0.length !== a1.length) { 3213 return false; 3214 } 3215 else { 3216 for (var i = 0; i < a0.length; i++) { 3217 if (!isValuesSimilar(a0[i], a1[i], depth - 1)) { 3218 return false; 3219 } 3220 } 3221 return true; 3222 } 3223 } 3224 else { 3225 return false; 3226 } 3227 } 3228 function isObjectsSimilar(obj0, obj1, depth) { 3229 if (depth === void 0) { depth = 1; } 3230 if (obj0 === obj1) { 3231 return true; 3232 } 3233 else if (depth > 0) { 3234 for (var prop in obj0) { 3235 if (!(prop in obj1)) { 3236 return false; 3237 } 3238 } 3239 for (var prop in obj1) { 3240 if (!(prop in obj0)) { 3241 return false; 3242 } 3243 else { 3244 if (!isValuesSimilar(obj0[prop], obj1[prop], depth - 1)) { 3245 return false; 3246 } 3247 } 3248 } 3249 return true; 3250 } 3251 else { 3252 return false; 3253 } 3254 } 3255 function computeChangedProps(obj0, obj1, depth) { 3256 if (depth === void 0) { depth = 1; } 3257 var res = {}; 3258 for (var prop in obj1) { 3259 if (!(prop in obj0) || 3260 !isValuesSimilar(obj0[prop], obj1[prop], depth - 1)) { 3261 res[prop] = obj1[prop]; 3262 } 3263 } 3264 return res; 3265 } 3266 function anyKeysRemoved(obj0, obj1) { 3267 for (var prop in obj0) { 3268 if (!(prop in obj1)) { 3269 return true; 3270 } 3271 } 3272 return false; 3273 } 3274 3275 var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere 3276 var Splitter = /** @class */ (function () { 3277 function Splitter() { 3278 this.getKeysForEventDefs = memoize(this._getKeysForEventDefs); 3279 this.splitDateSelection = memoize(this._splitDateSpan); 3280 this.splitEventStore = memoize(this._splitEventStore); 3281 this.splitIndividualUi = memoize(this._splitIndividualUi); 3282 this.splitEventDrag = memoize(this._splitInteraction); 3283 this.splitEventResize = memoize(this._splitInteraction); 3284 this.eventUiBuilders = {}; // TODO: typescript protection 3285 } 3286 Splitter.prototype.splitProps = function (props) { 3287 var _this = this; 3288 var keyInfos = this.getKeyInfo(props);
3289 var defKeys = this.getKeysForEventDefs(props.eventStore); 3290 var dateSelections = this.splitDateSelection(props.dateSelection); 3291 var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases* 3292 var eventStores = this.splitEventStore(props.eventStore, defKeys); 3293 var eventDrags = this.splitEventDrag(props.eventDrag); 3294 var eventResizes = this.splitEventResize(props.eventResize); 3295 var splitProps = {}; 3296 this.eventUiBuilders = mapHash(keyInfos, function (info, key) { 3297 return _this.eventUiBuilders[key] || memoize(buildEventUiForKey); 3298 }); 3299 for (var key in keyInfos) { 3300 var keyInfo = keyInfos[key]; 3301 var eventStore = eventStores[key] || EMPTY_EVENT_STORE; 3302 var buildEventUi = this.eventUiBuilders[key]; 3303 splitProps[key] = { 3304 businessHours: keyInfo.businessHours || props.businessHours, 3305 dateSelection: dateSelections[key] || null, 3306 eventStore: eventStore, 3307 eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]), 3308 eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '', 3309 eventDrag: eventDrags[key] || null, 3310 eventResize: eventResizes[key] || null 3311 }; 3312 } 3313 return splitProps; 3314 }; 3315 Splitter.prototype._splitDateSpan = function (dateSpan) { 3316 var dateSpans = {}; 3317 if (dateSpan) { 3318 var keys = this.getKeysForDateSpan(dateSpan); 3319 for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { 3320 var key = keys_1[_i]; 3321 dateSpans[key] = dateSpan; 3322 } 3323 } 3324 return dateSpans; 3325 }; 3326 Splitter.prototype._getKeysForEventDefs = function (eventStore) { 3327 var _this = this; 3328 return mapHash(eventStore.defs, function (eventDef) { 3329 return _this.getKeysForEventDef(eventDef); 3330 }); 3331 }; 3332 Splitter.prototype._splitEventStore = function (eventStore, defKeys) { 3333 var defs = eventStore.defs, instances = eventStore.instances; 3334 var splitStores = {}; 3335 for (var defId in defs) { 3336 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 3337 var key = _a[_i]; 3338 if (!splitStores[key]) { 3339 splitStores[key] = createEmptyEventStore(); 3340 } 3341 splitStores[key].defs[defId] = defs[defId]; 3342 } 3343 } 3344 for (var instanceId in instances) { 3345 var instance = instances[instanceId]; 3346 for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) { 3347 var key = _c[_b]; 3348 if (splitStores[key]) { // must have already been created 3349 splitStores[key].instances[instanceId] = instance; 3350 } 3351 } 3352 } 3353 return splitStores; 3354 }; 3355 Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) { 3356 var splitHashes = {}; 3357 for (var defId in eventUiBases) { 3358 if (defId) { // not the '' key 3359 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 3360 var key = _a[_i]; 3361 if (!splitHashes[key]) { 3362 splitHashes[key] = {}; 3363 } 3364 splitHashes[key][defId] = eventUiBases[defId]; 3365 } 3366 } 3367 } 3368 return splitHashes; 3369 }; 3370 Splitter.prototype._splitInteraction = function (interaction) { 3371 var splitStates = {}; 3372 if (interaction) { 3373 var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeys
3373ForEventDefs(interaction.affectedEvents) // can't use cached. might be events from other calendar 3374 ); 3375 // can't rely on defKeys because event data is mutated 3376 var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents); 3377 var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId); 3378 var populate = function (key) { 3379 if (!splitStates[key]) { 3380 splitStates[key] = { 3381 affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE, 3382 mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE, 3383 isEvent: interaction.isEvent, 3384 origSeg: interaction.origSeg 3385 }; 3386 } 3387 }; 3388 for (var key in affectedStores_1) { 3389 populate(key); 3390 } 3391 for (var key in mutatedStores_1) { 3392 populate(key); 3393 } 3394 } 3395 return splitStates; 3396 }; 3397 return Splitter; 3398 }()); 3399 function buildEventUiForKey(allUi, eventUiForKey, individualUi) { 3400 var baseParts = []; 3401 if (allUi) { 3402 baseParts.push(allUi); 3403 } 3404 if (eventUiForKey) { 3405 baseParts.push(eventUiForKey); 3406 } 3407 var stuff = { 3408 '': combineEventUis(baseParts) 3409 }; 3410 if (individualUi) { 3411 __assign(stuff, individualUi); 3412 } 3413 return stuff; 3414 } 3415 3416 // Generates HTML for an anchor to another view into the calendar. 3417 // Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings. 3418 // `gotoOptions` can either be a DateMarker, or an object with the form: 3419 // { date, type, forceOff } 3420 // `type` is a view-type like "day" or "week". default value is "day". 3421 // `attrs` and `innerHtml` are use to generate the rest of the HTML tag. 3422 function buildGotoAnchorHtml(component, gotoOptions, attrs, innerHtml) { 3423 var dateEnv = component.dateEnv; 3424 var date; 3425 var type; 3426 var forceOff; 3427 var finalOptions; 3428 if (gotoOptions instanceof Date) { 3429 date = gotoOptions; // a single date-like input 3430 } 3431 else { 3432 date = gotoOptions.date; 3433 type = gotoOptions.type; 3434 forceOff = gotoOptions.forceOff; 3435 } 3436 finalOptions = { 3437 date: dateEnv.formatIso(date, { omitTime: true }), 3438 type: type || 'day' 3439 }; 3440 if (typeof attrs === 'string') { 3441 innerHtml = attrs; 3442 attrs = null; 3443 } 3444 attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space 3445 innerHtml = innerHtml || ''; 3446 if (!forceOff && component.opt('navLinks')) { 3447 return '<a' + attrs + 3448 ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' + 3449 innerHtml + 3450 '</a>'; 3451 } 3452 else { 3453 return '<span' + attrs + '>' + 3454 innerHtml + 3455 '</span>'; 3456 } 3457 } 3458 function getAllDayHtml(component) { 3459 return component.opt('allDayHtml') || htmlEscape(component.opt('allDayText')); 3460 } 3461 // Computes HTML classNames for a single-day element 3462 function getDayClasses(date, dateProfile, context, noThemeHighlight) { 3463 var calendar = context.calendar, view = context.view, theme = context.theme, dateEnv = context.dateEnv; 3464 var classes = []; 3465 var todayStart; 3466 var todayEnd; 3467 if (!rangeContainsMarker(dateProfile.activeRange, date)) { 3468 classes.push('fc-disabled-day'); 3469 } 3470 else { 3471 classes.push('fc-' + DAY_IDS[date.getUTCDay()]); 3472 if (view.opt('monthMode') && 3473 dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) { 3474 classes.push('fc-other-month'); 3475 } 3476 todayStart = startOfDay(calendar.getNow()); 3477 todayEnd = addDays(todayStart, 1); 3478 if (date < todayStart) { 3479 classes.push('fc-past'); 3480 } 3481 else if (date >= todayEnd) { 3482 classes.push('fc-future'); 3483 } 3484 else { 3485 classes.push('fc-today'); 3486 if (noThemeHighlight !== true) { 3487 classes.push(theme.getClass('today')); 3488 } 3489 } 3490 } 3491 return classes; 3492 } 3493 3494 // given a function that resolves a result asynchronously. 3495 // the function can either call passed-in success and failure callbacks, 3496 // or it can return a promise. 3497 // if you need to pass additional params to func, bind them first. 3498 function unpromisify(func, success, failure) { 3499 // guard against success/failure callbacks being called more than once 3500 // and guard against a promise AND callback being used together. 3501 var isResolved = false;
3502 var wrappedSuccess = function () { 3503 if (!isResolved) { 3504 isResolved = true; 3505 success.apply(this, arguments); 3506 } 3507 }; 3508 var wrappedFailure = function () { 3509 if (!isResolved) { 3510 isResolved = true; 3511 if (failure) { 3512 failure.apply(this, arguments); 3513 } 3514 } 3515 }; 3516 var res = func(wrappedSuccess, wrappedFailure); 3517 if (res && typeof res.then === 'function') { 3518 res.then(wrappedSuccess, wrappedFailure); 3519 } 3520 } 3521 3522 var Mixin = /** @class */ (function () { 3523 function Mixin() { 3524 } 3525 // mix into a CLASS 3526 Mixin.mixInto = function (destClass) { 3527 this.mixIntoObj(destClass.prototype); 3528 }; 3529 // mix into ANY object 3530 Mixin.mixIntoObj = function (destObj) { 3531 var _this = this; 3532 Object.getOwnPropertyNames(this.prototype).forEach(function (name) { 3533 if (!destObj[name]) { // if destination doesn't already define it 3534 destObj[name] = _this.prototype[name]; 3535 } 3536 }); 3537 }; 3538 /* 3539 will override existing methods 3540 TODO: remove! not used anymore 3541 */ 3542 Mixin.mixOver = function (destClass) { 3543 var _this = this; 3544 Object.getOwnPropertyNames(this.prototype).forEach(function (name) { 3545 destClass.prototype[name] = _this.prototype[name]; 3546 }); 3547 }; 3548 return Mixin; 3549 }()); 3550 3551 /* 3552 USAGE: 3553 import { default as EmitterMixin, EmitterInterface } from './EmitterMixin' 3554 in class: 3555 on: EmitterInterface['on'] 3556 one: EmitterInterface['one'] 3557 off: EmitterInterface['off'] 3558 trigger: EmitterInterface['trigger'] 3559 triggerWith: EmitterInterface['triggerWith'] 3560 hasHandlers: EmitterInterface['hasHandlers'] 3561 after class: 3562 EmitterMixin.mixInto(TheClass) 3563 */ 3564 var EmitterMixin = /** @class */ (function (_super) { 3565 __extends(EmitterMixin, _super); 3566 function EmitterMixin() { 3567 return _super !== null && _super.apply(this, arguments) || this; 3568 } 3569 EmitterMixin.prototype.on = function (type, handler) { 3570 addToHash(this._handlers || (this._handlers = {}), type, handler); 3571 return this; // for chaining 3572 }; 3573 // todo: add comments 3574 EmitterMixin.prototype.one = function (type, handler) { 3575 addToHash(this._oneHandlers || (this._oneHandlers = {}), type, handler); 3576 return this; // for chaining 3577 }; 3578 EmitterMixin.prototype.off = function (type, handler) { 3579 if (this._handlers) { 3580 removeFromHash(this._handlers, type, handler); 3581 } 3582 if (this._oneHandlers) { 3583 removeFromHash(this._oneHandlers, type, handler); 3584 } 3585 return this; // for chaining 3586 }; 3587 EmitterMixin.prototype.trigger = function (type) { 3588 var args = []; 3589 for (var _i = 1; _i < arguments.length; _i++) { 3590 args[_i - 1] = arguments[_i]; 3591 } 3592 this.triggerWith(type, this, args); 3593 return this; // for chaining 3594 }; 3595 EmitterMixin.prototype.triggerWith = function (type, context, args) { 3596 if (this._handlers) { 3597 applyAll(this._handlers[type], context, args); 3598 } 3599 if (this._oneHandlers) { 3600 applyAll(this._oneHandlers[type], context, args); 3601 delete this._oneHandlers[type]; // will never fire again 3602 } 3603 return this; // for chaining 3604 }; 3605 EmitterMixin.prototype.hasHandlers = function (type) { 3606 return (this._handlers && this._handlers[type] && this._handlers[type].length) || 3607 (this._oneHandlers && this._oneHandlers[type] && this._oneHandlers[type].length); 3608 }; 3609 return EmitterMixin; 3610 }(Mixin)); 3611 function addToHash(hash, type, handler) { 3612 (hash[type] || (hash[type] = [])) 3613 .push(handler); 3614 } 3615 function removeFromHash(hash, type, handler) { 3616 if (handler) { 3617 if (hash[type]) { 3618 hash[type] = hash[type].filter(function (func) { 3619 return func !== handler; 3620 }); 3621 } 3622 } 3623 else { 3624 delete hash[type]; // remove all handler funcs for this type 3625 } 3626 } 3627 3628 /* 3629 Records offset information for a set of elements, relative to an origin element. 3630 Can record the left/right OR the top/bottom OR both. 3631 Provides methods for querying the cache by position. 3632 */ 3633 var PositionCache = /** @class */ (function () { 3634 function PositionCache(originEl, els, isHorizontal, isVertical) { 3635 this.originEl = originEl; 3636 this.els = els; 3637 this.isHorizontal = isHorizontal; 3638 this.isVertical = isVertical; 3639 } 3640 // Queries the els for coordinates and stores them. 3641 // Call this method before using and of the get* methods below. 3642 PositionCache.prototype.build = function () { 3643 var originEl = this.originEl; 3644 var originClientRect = this.originClientRect = 3645 originEl.getBoundingClientRect(); // relative to viewport top-left 3646 if (this.isHorizontal) { 3647 this.buildElHorizontals(originClientRect.left); 3648 } 3649 if (this.isVertical) { 3650 this.buildElVerticals(originClientRect.top); 3651 } 3652 };
3653 // Populates the left/right internal coordinate arrays 3654 PositionCache.prototype.buildElHorizontals = function (originClientLeft) { 3655 var lefts = []; 3656 var rights = []; 3657 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 3658 var el = _a[_i]; 3659 var rect = el.getBoundingClientRect(); 3660 lefts.push(rect.left - originClientLeft); 3661 rights.push(rect.right - originClientLeft); 3662 } 3663 this.lefts = lefts; 3664 this.rights = rights; 3665 }; 3666 // Populates the top/bottom internal coordinate arrays 3667 PositionCache.prototype.buildElVerticals = function (originClientTop) { 3668 var tops = []; 3669 var bottoms = []; 3670 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 3671 var el = _a[_i]; 3672 var rect = el.getBoundingClientRect(); 3673 tops.push(rect.top - originClientTop); 3674 bottoms.push(rect.bottom - originClientTop); 3675 } 3676 this.tops = tops; 3677 this.bottoms = bottoms; 3678 }; 3679 // Given a left offset (from document left), returns the index of the el that it horizontally intersects. 3680 // If no intersection is made, returns undefined. 3681 PositionCache.prototype.leftToIndex = function (leftPosition) { 3682 var lefts = this.lefts; 3683 var rights = this.rights; 3684 var len = lefts.length; 3685 var i; 3686 for (i = 0; i < len; i++) { 3687 if (leftPosition >= lefts[i] && leftPosition < rights[i]) { 3688 return i; 3689 } 3690 } 3691 }; 3692 // Given a top offset (from document top), returns the index of the el that it vertically intersects. 3693 // If no intersection is made, returns undefined. 3694 PositionCache.prototype.topToIndex = function (topPosition) { 3695 var tops = this.tops; 3696 var bottoms = this.bottoms; 3697 var len = tops.length; 3698 var i; 3699 for (i = 0; i < len; i++) { 3700 if (topPosition >= tops[i] && topPosition < bottoms[i]) { 3701 return i; 3702 } 3703 } 3704 }; 3705 // Gets the width of the element at the given index 3706 PositionCache.prototype.getWidth = function (leftIndex) { 3707 return this.rights[leftIndex] - this.lefts[leftIndex]; 3708 }; 3709 // Gets the height of the element at the given index 3710 PositionCache.prototype.getHeight = function (topIndex) { 3711 return this.bottoms[topIndex] - this.tops[topIndex]; 3712 }; 3713 return PositionCache; 3714 }()); 3715 3716 /* 3717 An object for getting/setting scroll-related information for an element. 3718 Internally, this is done very differently for window versus DOM element, 3719 so this object serves as a common interface. 3720 */ 3721 var ScrollController = /** @class */ (function () { 3722 function ScrollController() { 3723 } 3724 ScrollController.prototype.getMaxScrollTop = function () { 3725 return this.getScrollHeight() - this.getClientHeight(); 3726 }; 3727 ScrollController.prototype.getMaxScrollLeft = function () { 3728 return this.getScrollWidth() - this.getClientWidth(); 3729 }; 3730 ScrollController.prototype.canScrollVertically = function () { 3731 return this.getMaxScrollTop() > 0; 3732 }; 3733 ScrollController.prototype.canScrollHorizontally = function () { 3734 return this.getMaxScrollLeft() > 0; 3735 }; 3736 ScrollController.prototype.canScrollUp = function () { 3737 return this.getScrollTop() > 0; 3738 }; 3739 ScrollController.prototype.canScrollDown = function () { 3740 return this.getScrollTop() < this.getMaxScrollTop(); 3741 }; 3742 ScrollController.prototype.canScrollLeft = function () { 3743 return this.getScrollLeft() > 0; 3744 }; 3745 ScrollController.prototype.canScrollRight = function () { 3746 return this.getScrollLeft() < this.getMaxScrollLeft(); 3747 };
3748 return ScrollController; 3749 }()); 3750 var ElementScrollController = /** @class */ (function (_super) { 3751 __extends(ElementScrollController, _super); 3752 function ElementScrollController(el) { 3753 var _this = _super.call(this) || this; 3754 _this.el = el; 3755 return _this; 3756 } 3757 ElementScrollController.prototype.getScrollTop = function () { 3758 return this.el.scrollTop; 3759 }; 3760 ElementScrollController.prototype.getScrollLeft = function () { 3761 return this.el.scrollLeft; 3762 }; 3763 ElementScrollController.prototype.setScrollTop = function (top) { 3764 this.el.scrollTop = top; 3765 }; 3766 ElementScrollController.prototype.setScrollLeft = function (left) { 3767 this.el.scrollLeft = left; 3768 }; 3769 ElementScrollController.prototype.getScrollWidth = function () { 3770 return this.el.scrollWidth; 3771 }; 3772 ElementScrollController.prototype.getScrollHeight = function () { 3773 return this.el.scrollHeight; 3774 }; 3775 ElementScrollController.prototype.getClientHeight = function () { 3776 return this.el.clientHeight; 3777 }; 3778 ElementScrollController.prototype.getClientWidth = function () { 3779 return this.el.clientWidth; 3780 }; 3781 return ElementScrollController; 3782 }(ScrollController)); 3783 var WindowScrollController = /** @class */ (function (_super) { 3784 __extends(WindowScrollController, _super); 3785 function WindowScrollController() { 3786 return _super !== null && _super.apply(this, arguments) || this; 3787 } 3788 WindowScrollController.prototype.getScrollTop = function () { 3789 return window.pageYOffset; 3790 }; 3791 WindowScrollController.prototype.getScrollLeft = function () { 3792 return window.pageXOffset; 3793 }; 3794 WindowScrollController.prototype.setScrollTop = function (n) { 3795 window.scroll(window.pageXOffset, n); 3796 }; 3797 WindowScrollController.prototype.setScrollLeft = function (n) { 3798 window.scroll(n, window.pageYOffset); 3799 }; 3800 WindowScrollController.prototype.getScrollWidth = function () { 3801 return document.documentElement.scrollWidth; 3802 }; 3803 WindowScrollController.prototype.getScrollHeight = function () { 3804 return document.documentElement.scrollHeight; 3805 }; 3806 WindowScrollController.prototype.getClientHeight = function () { 3807 return document.documentElement.clientHeight; 3808 }; 3809 WindowScrollController.prototype.getClientWidth = function () { 3810 return document.documentElement.clientWidth; 3811 }; 3812 return WindowScrollController; 3813 }(ScrollController)); 3814 3815 /* 3816 Embodies a div that has potential scrollbars 3817 */ 3818 var ScrollComponent = /** @class */ (function (_super) { 3819 __extends(ScrollComponent, _super); 3820 function ScrollComponent(overflowX, overflowY) { 3821 var _this = _super.call(this, createElement('div', { 3822 className: 'fc-scroller' 3823 })) || this; 3824 _this.overflowX = overflowX; 3825 _this.overflowY = overflowY; 3826 _this.applyOverflow(); 3827 return _this; 3828 } 3829 // sets to natural height, unlocks overflow 3830 ScrollComponent.prototype.clear = function () { 3831 this.setHeight('auto'); 3832 this.applyOverflow(); 3833 }; 3834 ScrollComponent.prototype.destroy = function () { 3835 removeElement(this.el); 3836 }; 3837 // Overflow 3838 // ----------------------------------------------------------------------------------------------------------------- 3839 ScrollComponent.prototype.applyOverflow = function () { 3840 applyStyle(this.el, { 3841 overflowX: this.overflowX, 3842 overflowY: this.overflowY 3843 }); 3844 }; 3845 // Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'. 3846 // Useful for preserving scrollbar widths regardless of future resizes. 3847 // Can pass in scrollbarWidths for optimization. 3848 ScrollComponent.prototype.lockOverflow = function (scrollbarWidths) { 3849 var overflowX = this.overflowX; 3850 var overflowY = this.overflowY;
3851 scrollbarWidths = scrollbarWidths || this.getScrollbarWidths(); 3852 if (overflowX === 'auto') { 3853 overflowX = (scrollbarWidths.bottom || // horizontal scrollbars? 3854 this.canScrollHorizontally() // OR scrolling pane with massless scrollbars? 3855 ) ? 'scroll' : 'hidden'; 3856 } 3857 if (overflowY === 'auto') { 3858 overflowY = (scrollbarWidths.left || scrollbarWidths.right || // horizontal scrollbars? 3859 this.canScrollVertically() // OR scrolling pane with massless scrollbars? 3860 ) ? 'scroll' : 'hidden'; 3861 } 3862 applyStyle(this.el, { overflowX: overflowX, overflowY: overflowY }); 3863 }; 3864 ScrollComponent.prototype.setHeight = function (height) { 3865 applyStyleProp(this.el, 'height', height); 3866 }; 3867 ScrollComponent.prototype.getScrollbarWidths = function () { 3868 var edges = computeEdges(this.el); 3869 return { 3870 left: edges.scrollbarLeft, 3871 right: edges.scrollbarRight, 3872 bottom: edges.scrollbarBottom 3873 }; 3874 }; 3875 return ScrollComponent; 3876 }(ElementScrollController)); 3877 3878 var Theme = /** @class */ (function () { 3879 function Theme(calendarOptions) { 3880 this.calendarOptions = calendarOptions; 3881 this.processIconOverride(); 3882 } 3883 Theme.prototype.processIconOverride = function () { 3884 if (this.iconOverrideOption) { 3885 this.setIconOverride(this.calendarOptions[this.iconOverrideOption]); 3886 } 3887 }; 3888 Theme.prototype.setIconOverride = function (iconOverrideHash) { 3889 var iconClassesCopy; 3890 var buttonName; 3891 if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object 3892 iconClassesCopy = __assign({}, this.iconClasses); 3893 for (buttonName in iconOverrideHash) { 3894 iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]); 3895 } 3896 this.iconClasses = iconClassesCopy; 3897 } 3898 else if (iconOverrideHash === false) { 3899 this.iconClasses = {}; 3900 } 3901 }; 3902 Theme.prototype.applyIconOverridePrefix = function (className) { 3903 var prefix = this.iconOverridePrefix; 3904 if (prefix && className.indexOf(prefix) !== 0) { // if not already present 3905 className = prefix + className; 3906 } 3907 return className; 3908 }; 3909 Theme.prototype.getClass = function (key) { 3910 return this.classes[key] || ''; 3911 }; 3912 Theme.prototype.getIconClass = function (buttonName) { 3913 var className = this.iconClasses[buttonName]; 3914 if (className) { 3915 return this.baseIconClass + ' ' + className; 3916 } 3917 return ''; 3918 }; 3919 Theme.prototype.getCustomButtonIconClass = function (customButtonProps) { 3920 var className; 3921 if (this.iconOverrideCustomButtonOption) { 3922 className = customButtonProps[this.iconOverrideCustomButtonOption]; 3923 if (className) { 3924 return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className); 3925 } 3926 } 3927 return ''; 3928 }; 3929 return Theme; 3930 }()); 3931 Theme.prototype.classes = {}; 3932 Theme.prototype.iconClasses = {}; 3933 Theme.prototype.baseIconClass = ''; 3934 Theme.prototype.iconOverridePrefix = ''; 3935 3936 var guid = 0; 3937 var Component = /** @class */ (function () { 3938 function Component(context, isView) { 3939 // HACK to populate view at top of component instantiation call chain 3940 if (isView) { 3941 context.view = this; 3942 } 3943 this.uid = String(guid++); 3944 this.context = context; 3945 this.dateEnv = context.dateEnv; 3946 this.theme = context.theme; 3947 this.view = context.view; 3948 this.calendar = context.calendar; 3949 this.isRtl = this.opt('dir') === 'rtl'; 3950 } 3951 Component.addEqualityFuncs = function (newFuncs) { 3952 this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs); 3953 }; 3954 Component.prototype.opt = function (name) { 3955 return this.context.options[name]; 3956 }; 3957 Component.prototype.receiveProps = function (props) { 3958 var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps; 3959 this.props = comboProps;
3960 if (anyChanges) { 3961 this.render(comboProps); 3962 } 3963 }; 3964 Component.prototype.render = function (props) { 3965 }; 3966 // after destroy is called, this component won't ever be used again 3967 Component.prototype.destroy = function () { 3968 }; 3969 return Component; 3970 }()); 3971 Component.prototype.equalityFuncs = {}; 3972 /* 3973 Reuses old values when equal. If anything is unequal, returns newProps as-is. 3974 Great for PureComponent, but won't be feasible with React, so just eliminate and use React's DOM diffing. 3975 */ 3976 function recycleProps(oldProps, newProps, equalityFuncs) { 3977 var comboProps = {}; // some old, some new 3978 var anyChanges = false; 3979 for (var key in newProps) { 3980 if (key in oldProps && (oldProps[key] === newProps[key] || 3981 (equalityFuncs[key] && equalityFuncs[key](oldProps[key], newProps[key])))) { 3982 // equal to old? use old prop 3983 comboProps[key] = oldProps[key]; 3984 } 3985 else { 3986 comboProps[key] = newProps[key]; 3987 anyChanges = true; 3988 } 3989 } 3990 for (var key in oldProps) { 3991 if (!(key in newProps)) { 3992 anyChanges = true; 3993 break; 3994 } 3995 } 3996 return { anyChanges: anyChanges, comboProps: comboProps }; 3997 } 3998 3999 /* 4000 PURPOSES: 4001 - hook up to fg, fill, and mirror renderers 4002 - interface for dragging and hits 4003 */ 4004 var DateComponent = /** @class */ (function (_super) { 4005 __extends(DateComponent, _super); 4006 function DateComponent(context, el, isView) { 4007 var _this = _super.call(this, context, isView) || this; 4008 _this.el = el; 4009 return _this; 4010 } 4011 DateComponent.prototype.destroy = function () { 4012 _super.prototype.destroy.call(this); 4013 removeElement(this.el); 4014 }; 4015 // TODO: WHAT ABOUT (sourceSeg && sourceSeg.component.doesDragMirror) 4016 // 4017 // Event Drag-n-Drop Rendering (for both events and external elements) 4018 // --------------------------------------------------------------------------------------------------------------- 4019 /* 4020 renderEventDragSegs(state: EventSegUiInteractionState) { 4021 if (state) { 4022 let { isEvent, segs, sourceSeg } = state 4023 4024 if (this.eventRenderer) { 4025 this.eventRenderer.hideByHash(state.affectedInstances) 4026 } 4027 4028 // if the user is dragging something that is considered an event with real event data, 4029 // and this component likes to do drag mirrors OR the component where the seg came from 4030 // likes to do drag mirrors, then render a drag mirror. 4031 if (isEvent && (this.doesDragMirror || sourceSeg && sourceSeg.component.doesDragMirror)) { 4032 if (this.mirrorRenderer) { 4033 this.mirrorRenderer.renderSegs(segs, { isDragging: true, sourceSeg }) 4034 } 4035 } 4036 4037 // if it would be impossible to render a drag mirror OR this component likes to render 4038 // highlights, then render a highlight. 4039 if (!isEvent || this.doesDragHighlight) { 4040 if (this.fillRenderer) { 4041 this.fillRenderer.renderSegs('highlight', segs) 4042 } 4043 } 4044 } 4045 } 4046 */ 4047 // Hit System 4048 // ----------------------------------------------------------------------------------------------------------------- 4049 DateComponent.prototype.buildPositionCaches = function () { 4050 }; 4051 DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { 4052 return null; // this should be abstract 4053 }; 4054 // Validation 4055 // ----------------------------------------------------------------------------------------------------------------- 4056 DateComponent.prototype.isInteractionValid = function (interaction) { 4057 var calendar = this.calendar; 4058 var dateProfile = this.props.dateProfile; // HACK 4059 var instances = interaction.mutatedEvents.instances; 4060 if (dateProfile) { // HACK for DayTile 4061 for (var instanceId in instances) { 4062 if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) { 4063 return false;
4064 } 4065 } 4066 } 4067 return isInteractionValid(interaction, calendar); 4068 }; 4069 DateComponent.prototype.isDateSelectionValid = function (selection) { 4070 var dateProfile = this.props.dateProfile; // HACK 4071 if (dateProfile && // HACK for DayTile 4072 !rangeContainsRange(dateProfile.validRange, selection.range)) { 4073 return false; 4074 } 4075 return isDateSelectionValid(selection, this.calendar); 4076 }; 4077 // Triggering 4078 // ----------------------------------------------------------------------------------------------------------------- 4079 // TODO: move to Calendar 4080 DateComponent.prototype.publiclyTrigger = function (name, args) { 4081 var calendar = this.calendar; 4082 return calendar.publiclyTrigger(name, args); 4083 }; 4084 DateComponent.prototype.publiclyTriggerAfterSizing = function (name, args) { 4085 var calendar = this.calendar; 4086 return calendar.publiclyTriggerAfterSizing(name, args); 4087 }; 4088 DateComponent.prototype.hasPublicHandlers = function (name) { 4089 var calendar = this.calendar; 4090 return calendar.hasPublicHandlers(name); 4091 }; 4092 DateComponent.prototype.triggerRenderedSegs = function (segs, isMirrors) { 4093 var calendar = this.calendar; 4094 if (this.hasPublicHandlers('eventPositioned')) { 4095 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 4096 var seg = segs_1[_i]; 4097 this.publiclyTriggerAfterSizing('eventPositioned', [ 4098 { 4099 event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), 4100 isMirror: isMirrors, 4101 isStart: seg.isStart, 4102 isEnd: seg.isEnd, 4103 el: seg.el, 4104 view: this // ? 4105 } 4106 ]); 4107 } 4108 } 4109 if (!calendar.state.loadingLevel) { // avoid initial empty state while pending 4110 calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once 4111 } 4112 }; 4113 DateComponent.prototype.triggerWillRemoveSegs = function (segs, isMirrors) { 4114 var calendar = this.calendar; 4115 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 4116 var seg = segs_2[_i]; 4117 calendar.trigger('eventElRemove', seg.el); 4118 } 4119 if (this.hasPublicHandlers('eventDestroy')) { 4120 for (var _a = 0, segs_3 = segs; _a < segs_3.length; _a++) { 4121 var seg = segs_3[_a]; 4122 this.publiclyTrigger('eventDestroy', [ 4123 { 4124 event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), 4125 isMirror: isMirrors, 4126 el: seg.el, 4127 view: this // ? 4128 } 4129 ]); 4130 } 4131 } 4132 }; 4133 // Pointer Interaction Utils 4134 // ----------------------------------------------------------------------------------------------------------------- 4135 DateComponent.prototype.isValidSegDownEl = function (el) { 4136 return !this.props.eventDrag && // HACK 4137 !this.props.eventResize && // HACK 4138 !elementClosest(el, '.fc-mirror') && 4139 (this.isPopover() || !this.isInPopover(el)); 4140 // ^above line ensures we don't detect a seg interaction within a nested component. 4141 // it's a HACK because it only supports a popover as the nested component. 4142 }; 4143 DateComponent.prototype.isValidDateDownEl = function (el) { 4144 var segEl = elementClosest(el, this.fgSegSelector); 4145 return (!segEl || segEl.classList.contains('fc-mirror')) && 4146 !elementClosest(el, '.fc-more') && // a "more.." link 4147 !elementClosest(el, 'a[data-goto]') && // a clickable nav link 4148 !this.isInPopover(el); 4149 }; 4150 DateComponent.prototype.isPopover = function () { 4151 return this.el.classList.contains('fc-popover'); 4152 }; 4153 DateComponent.prototype.isInPopover = function (el) { 4154 return Boolean(elementClosest(el, '.fc-popover')); 4155 }; 4156 return DateComponent; 4157 }(Component)); 4158 DateComponent.prototype.fgSegSelector = '.fc-event-container > *'; 4159 DateComponent.prototype.bgSegSelector = '.fc-bgevent:not(.fc-nonbusiness)'; 4160 4161 var uid$1 = 0; 4162 function createPlugin(input) { 4163 return { 4164 id: String(uid$1++), 4165 deps: input.deps || [], 4166 reducers: input.reducers || [], 4167 eventDefParsers: input.eventDefParsers || [], 4168 eventDragMutationMassagers: input.eventDragMutationMassagers || [], 4169 eventDefMutationAppliers: input.eventDefMutationAppliers || [], 4170 dateSelectionTransformers: input.dateSelectionTransformers || [], 4171 datePointTransforms: input.datePointTransforms || [], 4172 dateSpanTransforms: input.dateSpanTransforms || [], 4173 views: input.views || {}, 4174 viewPropsTransformers: input.viewPropsTransformers || [], 4175 isPropsValid: input.isPropsValid || null, 4176 externalDefTransforms: input.externalDefTransforms || [], 4177 eventResizeJoinTransforms: input.eventResizeJoinTransforms || [], 4178 viewContainerModifiers: input.viewContainerModifiers || [], 4179 eventDropTransformers: input.eventDropTransformers || [], 4180 componentInteractions: input.componentInteractions || [], 4181 calendarInteractions: input.calendarInteractions || [],
4182 themeClasses: input.themeClasses || {}, 4183 eventSourceDefs: input.eventSourceDefs || [], 4184 cmdFormatter: input.cmdFormatter, 4185 recurringTypes: input.recurringTypes || [], 4186 namedTimeZonedImpl: input.namedTimeZonedImpl, 4187 defaultView: input.defaultView || '', 4188 elementDraggingImpl: input.elementDraggingImpl, 4189 optionChangeHandlers: input.optionChangeHandlers || {} 4190 }; 4191 } 4192 var PluginSystem = /** @class */ (function () { 4193 function PluginSystem() { 4194 this.hooks = { 4195 reducers: [], 4196 eventDefParsers: [], 4197 eventDragMutationMassagers: [], 4198 eventDefMutationAppliers: [], 4199 dateSelectionTransformers: [], 4200 datePointTransforms: [], 4201 dateSpanTransforms: [], 4202 views: {}, 4203 viewPropsTransformers: [], 4204 isPropsValid: null, 4205 externalDefTransforms: [], 4206 eventResizeJoinTransforms: [], 4207 viewContainerModifiers: [], 4208 eventDropTransformers: [], 4209 componentInteractions: [], 4210 calendarInteractions: [], 4211 themeClasses: {}, 4212 eventSourceDefs: [], 4213 cmdFormatter: null, 4214 recurringTypes: [], 4215 namedTimeZonedImpl: null, 4216 defaultView: '', 4217 elementDraggingImpl: null, 4218 optionChangeHandlers: {} 4219 }; 4220 this.addedHash = {}; 4221 } 4222 PluginSystem.prototype.add = function (plugin) { 4223 if (!this.addedHash[plugin.id]) { 4224 this.addedHash[plugin.id] = true; 4225 for (var _i = 0, _a = plugin.deps; _i < _a.length; _i++) { 4226 var dep = _a[_i]; 4227 this.add(dep); 4228 } 4229 this.hooks = combineHooks(this.hooks, plugin); 4230 } 4231 }; 4232 return PluginSystem; 4233 }()); 4234 function combineHooks(hooks0, hooks1) { 4235 return { 4236 reducers: hooks0.reducers.concat(hooks1.reducers), 4237 eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers), 4238 eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers), 4239 eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers), 4240 dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers), 4241 datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms), 4242 dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms), 4243 views: __assign({}, hooks0.views, hooks1.views), 4244 viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers), 4245 isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid, 4246 externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms), 4247 eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms), 4248 viewContainerModifiers: hooks0.viewContainerModifiers.concat(hooks1.viewContainerModifiers), 4249 eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers), 4250 calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions), 4251 componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions), 4252 themeClasses: __assign({}, hooks0.themeClasses, hooks1.themeClasses), 4253 eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs), 4254 cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter, 4255 recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes), 4256 namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl, 4257 defaultView: hooks0.defaultView || hooks1.defaultView, 4258 elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, 4259 optionChangeHandlers: __assign({}, hooks0.optionChangeHandlers, hooks1.optionChangeHandlers) 4260 }; 4261 } 4262 4263 var eventSourceDef = { 4264 ignoreRange: true, 4265 parseMeta: function (raw) { 4266 if (Array.isArray(raw)) { // short form 4267 return raw; 4268 } 4269 else if (Array.isArray(raw.events)) { 4270 return raw.events; 4271 } 4272 return null; 4273 }, 4274 fetch: function (arg, success) { 4275 success({ 4276 rawEvents: arg.eventSource.meta 4277 }); 4278 } 4279 }; 4280 var ArrayEventSourcePlugin = createPlugin({ 4281 eventSourceDefs: [eventSourceDef] 4282 }); 4283 4284 var eventSourceDef$1 = { 4285 parseMeta: function (raw) { 4286 if (typeof raw === 'function') { // short form 4287 return raw; 4288 } 4289 else if (typeof raw.events === 'function') { 4290 return raw.events; 4291 } 4292 return null; 4293 }, 4294 fetch: function (arg, success, failure) { 4295 var dateEnv = arg.calendar.dateEnv; 4296 var func = arg.eventSource.meta; 4297 unpromisify(func.bind(null, { 4298 start: dateEnv.toDate(arg.range.start), 4299 end: dateEnv.toDate(arg.range.end), 4300 startStr: dateEnv.formatIso(arg.range.start), 4301 endStr: dateEnv.formatIso(arg.range.end), 4302 timeZone: dateEnv.timeZone 4303 }), function (rawEvents) { 4304 success({ rawEvents: rawEvents }); // needs an object response 4305 }, failure // send errorObj directly to failure callback 4306 ); 4307 } 4308 }; 4309 var FuncEventSourcePlugin = createPlugin({ 4310 eventSourceDefs: [eventSourceDef$1] 4311 }); 4312 4313 function requestJson(method, url, params, successCallback, failureCallback) { 4314 method = method.toUpperCase(); 4315 var body = null; 4316 if (method === 'GET') { 4317 url = injectQueryStringParams(url, params); 4318 } 4319 else { 4320 body = encodeParams(params); 4321 } 4322 var xhr = new XMLHttpRequest(); 4323 xhr.open(method, url, true); 4324 if (method !== 'GET') { 4325 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 4326 } 4327 xhr.onload = function () { 4328 if (xhr.status >= 200 && xhr.status < 400) { 4329 try { 4330 var res = JSON.parse(xhr.responseText); 4331 successCallback(res, xhr); 4332 } 4333 catch (err) { 4334 failureCallback('Failure parsing JSON', xhr); 4335 } 4336 } 4337 else { 4338 failureCallback('Request failed', xhr); 4339 } 4340 }; 4341 xhr.onerror = function () { 4342 failureCallback('Request failed', xhr); 4343 }; 4344 xhr.send(body); 4345 } 4346 function injectQueryStringParams(url, params) { 4347 return url + 4348 (url.indexOf('?') === -1 ? '?' : '&') + 4349 encodeParams(params); 4350 } 4351 function encodeParams(params) { 4352 var parts = []; 4353 for (var key in params) { 4354 parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key])); 4355 } 4356 return parts.join('&'); 4357 } 4358 4359 var eventSourceDef$2 = { 4360 parseMeta: function (raw) { 4361 if (typeof raw === 'string') { // short form 4362 raw = { url: raw }; 4363 } 4364 else if (!raw || typeof raw !== 'object' || !raw.url) { 4365 return null; 4366 } 4367 return { 4368 url: raw.url, 4369 method: (raw.method || 'GET').toUpperCase(), 4370 extraParams: raw.extraParams, 4371 startParam: raw.startParam, 4372 endParam: raw.endParam, 4373 timeZoneParam: raw.timeZoneParam 4374 }; 4375 }, 4376 fetch: function (arg, success, failure) { 4377 var meta = arg.eventSource.meta;
4378 var requestParams = buildRequestParams(meta, arg.range, arg.calendar); 4379 requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) { 4380 success({ rawEvents: rawEvents, xhr: xhr }); 4381 }, function (errorMessage, xhr) { 4382 failure({ message: errorMessage, xhr: xhr }); 4383 }); 4384 } 4385 }; 4386 var JsonFeedEventSourcePlugin = createPlugin({ 4387 eventSourceDefs: [eventSourceDef$2] 4388 }); 4389 function buildRequestParams(meta, range, calendar) { 4390 var dateEnv = calendar.dateEnv; 4391 var startParam; 4392 var endParam; 4393 var timeZoneParam; 4394 var customRequestParams; 4395 var params = {}; 4396 startParam = meta.startParam; 4397 if (startParam == null) { 4398 startParam = calendar.opt('startParam'); 4399 } 4400 endParam = meta.endParam; 4401 if (endParam == null) { 4402 endParam = calendar.opt('endParam'); 4403 } 4404 timeZoneParam = meta.timeZoneParam; 4405 if (timeZoneParam == null) { 4406 timeZoneParam = calendar.opt('timeZoneParam'); 4407 } 4408 // retrieve any outbound GET/POST data from the options 4409 if (typeof meta.extraParams === 'function') { 4410 // supplied as a function that returns a key/value object
4411 customRequestParams = meta.extraParams(); 4412 } 4413 else { 4414 // probably supplied as a straight key/value object 4415 customRequestParams = meta.extraParams || {}; 4416 } 4417 __assign(params, customRequestParams); 4418 params[startParam] = dateEnv.formatIso(range.start); 4419 params[endParam] = dateEnv.formatIso(range.end); 4420 if (dateEnv.timeZone !== 'local') { 4421 params[timeZoneParam] = dateEnv.timeZone; 4422 } 4423 return params; 4424 } 4425 4426 var recurring = { 4427 parse: function (rawEvent, leftoverProps, dateEnv) { 4428 var createMarker = dateEnv.createMarker.bind(dateEnv); 4429 var processors = { 4430 daysOfWeek: null, 4431 startTime: createDuration, 4432 endTime: createDuration, 4433 startRecur: createMarker, 4434 endRecur: createMarker 4435 }; 4436 var props = refineProps(rawEvent, processors, {}, leftoverProps); 4437 var anyValid = false; 4438 for (var propName in props) { 4439 if (props[propName] != null) { 4440 anyValid = true; 4441 break; 4442 } 4443 } 4444 if (anyValid) { 4445 return { 4446 allDayGuess: Boolean(!props.startTime && !props.endTime), 4447 duration: (props.startTime && props.endTime) ? 4448 subtractDurations(props.endTime, props.startTime) : 4449 null, 4450 typeData: props // doesn't need endTime anymore but oh well 4451 }; 4452 } 4453 return null; 4454 }, 4455 expand: function (typeData, framingRange, dateEnv) { 4456 var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur }); 4457 if (clippedFramingRange) { 4458 return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv); 4459 } 4460 else { 4461 return []; 4462 } 4463 } 4464 }; 4465 var SimpleRecurrencePlugin = createPlugin({ 4466 recurringTypes: [recurring] 4467 }); 4468 function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) { 4469 var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null; 4470 var dayMarker = startOfDay(framingRange.start); 4471 var endMarker = framingRange.end; 4472 var instanceStarts = []; 4473 while (dayMarker < endMarker) { 4474 var instanceStart 4475 // if everyday, or this particular day-of-week 4476 = void 0; 4477 // if everyday, or this particular day-of-week 4478 if (!dowHash || dowHash[dayMarker.getUTCDay()]) { 4479 if (startTime) { 4480 instanceStart = dateEnv.add(dayMarker, startTime); 4481 } 4482 else { 4483 instanceStart = dayMarker; 4484 } 4485 instanceStarts.push(instanceStart); 4486 } 4487 dayMarker = addDays(dayMarker, 1); 4488 } 4489 return instanceStarts; 4490 } 4491 4492 var DefaultOptionChangeHandlers = createPlugin({ 4493 optionChangeHandlers: { 4494 events: function (events, calendar) { 4495 handleEventSources([events], calendar); 4496 }, 4497 eventSources: handleEventSources, 4498 plugins: handlePlugins 4499 } 4500 }); 4501 function handleEventSources(inputs, calendar) { 4502 var unfoundSources = hashValuesToArray(calendar.state.eventSources);
4503 var newInputs = []; 4504 for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { 4505 var input = inputs_1[_i]; 4506 var inputFound = false; 4507 for (var i = 0; i < unfoundSources.length; i++) { 4508 if (isValuesSimilar(unfoundSources[i]._raw, input, 2)) { 4509 unfoundSources.splice(i, 1); // delete 4510 inputFound = true; 4511 break; 4512 } 4513 } 4514 if (!inputFound) { 4515 newInputs.push(input); 4516 } 4517 } 4518 for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) { 4519 var unfoundSource = unfoundSources_1[_a]; 4520 calendar.dispatch({ 4521 type: 'REMOVE_EVENT_SOURCE', 4522 sourceId: unfoundSource.sourceId 4523 }); 4524 } 4525 for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) { 4526 var newInput = newInputs_1[_b]; 4527 calendar.addEventSource(newInput); 4528 } 4529 } 4530 // shortcoming: won't remove plugins 4531 function handlePlugins(inputs, calendar) { 4532 calendar.addPluginInputs(inputs); // will gracefully handle duplicates 4533 } 4534 4535 var config = {}; // TODO: make these options 4536 var globalDefaults = { 4537 defaultRangeSeparator: ' - ', 4538 titleRangeSeparator: ' \u2013 ', 4539 defaultTimedEventDuration: '01:00:00', 4540 defaultAllDayEventDuration: { day: 1 }, 4541 forceEventDuration: false, 4542 nextDayThreshold: '00:00:00', 4543 // display 4544 columnHeader: true, 4545 defaultView: '', 4546 aspectRatio: 1.35, 4547 header: { 4548 left: 'title', 4549 center: '', 4550 right: 'today prev,next' 4551 }, 4552 weekends: true, 4553 weekNumbers: false, 4554 weekNumberCalculation: 'local', 4555 editable: false, 4556 // nowIndicator: false, 4557 scrollTime: '06:00:00', 4558 minTime: '00:00:00', 4559 maxTime: '24:00:00', 4560 showNonCurrentDates: true, 4561 // event ajax 4562 lazyFetching: true, 4563 startParam: 'start', 4564 endParam: 'end', 4565 timeZoneParam: 'timeZone', 4566 timeZone: 'local', 4567 // allDayDefault: undefined, 4568 // locale 4569 locales: [], 4570 locale: '', 4571 // dir: will get this from the default locale 4572 // buttonIcons: null, 4573 // allows setting a min-height to the event segment to prevent short events overlapping each other 4574 timeGridEventMinHeight: 0, 4575 themeSystem: 'standard', 4576 // eventResizableFromStart: false, 4577 dragRevertDuration: 500, 4578 dragScroll: true, 4579 allDayMaintainDuration: false, 4580 // selectable: false, 4581 unselectAuto: true, 4582 // selectMinDistance: 0, 4583 dropAccept: '*', 4584 eventOrder: 'start,-duration,allDay,title', 4585 // ^ if start tie, longer events go before shorter. final tie-breaker is title text 4586 // rerenderDelay: null, 4587 eventLimit: false, 4588 eventLimitClick: 'popover', 4589 dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' }, 4590 handleWindowResize: true, 4591 windowResizeDelay: 100, 4592 longPressDelay: 1000, 4593 eventDragMinDistance: 5 // only applies to mouse 4594 }; 4595 var rtlDefaults = { 4596 header: { 4597 left: 'next,prev today', 4598 center: '', 4599 right: 'title' 4600 }, 4601 buttonIcons: { 4602 // TODO: make RTL support the responibility of the theme 4603 prev: 'fc-icon-chevron-right', 4604 next: 'fc-icon-chevron-left', 4605 prevYear: 'fc-icon-chevrons-right', 4606 nextYear: 'fc-icon-chevrons-left' 4607 } 4608 }; 4609 var complexOptions = [ 4610 'header', 4611 'footer', 4612 'buttonText', 4613 'buttonIcons' 4614 ]; 4615 // Merges an array of option objects into a single object 4616 function mergeOptions(optionObjs) { 4617 return mergeProps(optionObjs, complexOptions); 4618 } 4619 // TODO: move this stuff to a "plugin"-related file... 4620 var INTERNAL_PLUGINS = [ 4621 ArrayEventSourcePlugin, 4622 FuncEventSourcePlugin, 4623 JsonFeedEventSourcePlugin, 4624 SimpleRecurrencePlugin, 4625 DefaultOptionChangeHandlers 4626 ]; 4627 function refinePluginDefs(pluginInputs) { 4628 var plugins = []; 4629 for (var _i = 0, pluginInputs_1 = pluginInputs; _i < pluginInputs_1.length; _i++) { 4630 var pluginInput = pluginInputs_1[_i]; 4631 if (typeof pluginInput === 'string') { 4632 var globalName = 'FullCalendar' + capitaliseFirstLetter(pluginInput); 4633 if (!window[globalName]) { 4634 console.warn('Plugin file not loaded for ' + pluginInput); 4635 } 4636 else { 4637 plugins.push(window[globalName].default); // is an ES6 module 4638 } 4639 } 4640 else { 4641 plugins.push(pluginInput); 4642 } 4643 } 4644 return INTERNAL_PLUGINS.concat(plugins); 4645 } 4646 4647 var RAW_EN_LOCALE = { 4648 code: 'en', 4649 week: { 4650 dow: 0, 4651 doy: 4 // 4 days need to be within the year to be considered the first week 4652 }, 4653 dir: 'ltr', 4654 buttonText: { 4655 prev: 'prev', 4656 next: 'next', 4657 prevYear: 'prev year', 4658 nextYear: 'next year', 4659 year: 'year', 4660 today: 'today', 4661 month: 'month', 4662 week: 'week', 4663 day: 'day', 4664 list: 'list' 4665 }, 4666 weekLabel: 'W', 4667 allDayText: 'all-day', 4668 eventLimitText: 'more', 4669 noEventsMessage: 'No events to display' 4670 }; 4671 function parseRawLocales(explicitRawLocales) { 4672 var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en'; 4673 var globalArray = window['FullCalendarLocalesAll'] || []; // from locales-all.js 4674 var globalObject = window['FullCalendarLocales'] || {}; // from locales/*.js. keys are meaningless 4675 var allRawLocales = globalArray.concat(// globalArray is low prio 4676 hashValuesToArray(globalObject), // medium prio 4677 explicitRawLocales // highest prio 4678 ); 4679 var rawLocaleMap = { 4680 en: RAW_EN_LOCALE // necessary? 4681 }; 4682 for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) { 4683 var rawLocale = allRawLocales_1[_i]; 4684 rawLocaleMap[rawLocale.code] = rawLocale; 4685 } 4686 return { 4687 map: rawLocaleMap, 4688 defaultCode: defaultCode 4689 }; 4690 } 4691 function buildLocale(inputSingular, available) { 4692 if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) { 4693 return parseLocale(inputSingular.code, [inputSingular.code], inputSingular); 4694 } 4695 else { 4696 return queryLocale(inputSingular, available); 4697 } 4698 } 4699 function queryLocale(codeArg, available) { 4700 var codes = [].concat(codeArg || []); // will convert to array 4701 var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE; 4702 return parseLocale(codeArg, codes, raw); 4703 } 4704 function queryRawLocale(codes, available) { 4705 for (var i = 0; i < codes.length; i++) { 4706 var parts = codes[i].toLocaleLowerCase().split('-'); 4707 for (var j = parts.length; j > 0; j--) { 4708 var simpleId = parts.slice(0, j).join('-'); 4709 if (available[simpleId]) { 4710 return available[simpleId]; 4711 } 4712 } 4713 } 4714 return null; 4715 } 4716 function parseLocale(codeArg, codes, raw) { 4717 var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']); 4718 delete merged.code; // don't want this part of the options 4719 var week = merged.week; 4720 delete merged.week; 4721 return { 4722 codeArg: codeArg, 4723 codes: codes, 4724 week: week, 4725 simpleNumberFormat: new Intl.NumberFormat(codeArg), 4726 options: merged 4727 }; 4728 } 4729 4730 var OptionsManager = /** @class */ (function () { 4731 function OptionsManager(overrides) { 4732 this.overrides = __assign({}, overrides); // make a copy 4733 this.dynamicOverrides = {}; 4734 this.compute(); 4735 } 4736 OptionsManager.prototype.add = function (props) { 4737 __assign(this.overrides, props); 4738 this.compute(); 4739 }; 4740 OptionsManager.prototype.addDynamic = function (props) { 4741 __assign(this.dynamicOverrides, props); 4742 this.compute(); 4743 }; 4744 OptionsManager.prototype.reset = function (props) { 4745 this.overrides = props; 4746 this.compute(); 4747 }; 4748 // Computes the flattened options hash for the calendar and assigns to `this.options`. 4749 // Assumes this.overrides and this.dynamicOverrides have already been initialized. 4750 OptionsManager.prototype.compute = function () {
4751 // TODO: not a very efficient system 4752 var locales = firstDefined(// explicit locale option given? 4753 this.dynamicOverrides.locales, this.overrides.locales, globalDefaults.locales); 4754 var locale = firstDefined(// explicit locales option given? 4755 this.dynamicOverrides.locale, this.overrides.locale, globalDefaults.locale); 4756 var available = parseRawLocales(locales); 4757 var localeDefaults = buildLocale(locale || available.defaultCode, available.map).options; 4758 var dir = firstDefined(// based on options computed so far, is direction RTL? 4759 this.dynamicOverrides.dir, this.overrides.dir, localeDefaults.dir); 4760 var dirDefaults = dir === 'rtl' ? rtlDefaults : {}; 4761 this.dirDefaults = dirDefaults; 4762 this.localeDefaults = localeDefaults; 4763 this.computed = mergeOptions([ 4764 globalDefaults, 4765 dirDefaults, 4766 localeDefaults, 4767 this.overrides, 4768 this.dynamicOverrides 4769 ]); 4770 }; 4771 return OptionsManager; 4772 }()); 4773 4774 var calendarSystemClassMap = {}; 4775 function registerCalendarSystem(name, theClass) { 4776 calendarSystemClassMap[name] = theClass; 4777 } 4778 function createCalendarSystem(name) { 4779 return new calendarSystemClassMap[name](); 4780 } 4781 var GregorianCalendarSystem = /** @class */ (function () { 4782 function GregorianCalendarSystem() { 4783 } 4784 GregorianCalendarSystem.prototype.getMarkerYear = function (d) { 4785 return d.getUTCFullYear(); 4786 }; 4787 GregorianCalendarSystem.prototype.getMarkerMonth = function (d) { 4788 return d.getUTCMonth(); 4789 }; 4790 GregorianCalendarSystem.prototype.getMarkerDay = function (d) { 4791 return d.getUTCDate(); 4792 }; 4793 GregorianCalendarSystem.prototype.arrayToMarker = function (arr) { 4794 return arrayToUtcDate(arr); 4795 }; 4796 GregorianCalendarSystem.prototype.markerToArray = function (marker) { 4797 return dateToUtcArray(marker); 4798 }; 4799 return GregorianCalendarSystem; 4800 }()); 4801 registerCalendarSystem('gregory', GregorianCalendarSystem); 4802 4803 var ISO_RE = /^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/; 4804 function parse(str) { 4805 var m = ISO_RE.exec(str); 4806 if (m) { 4807 var marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number('0.' + m[12]) * 1000 : 0)); 4808 if (isValidDate(marker)) { 4809 var timeZoneOffset = null; 4810 if (m[13]) { 4811 timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 + 4812 Number(m[18] || 0)); 4813 } 4814 return { 4815 marker: marker, 4816 isTimeUnspecified: !m[6], 4817 timeZoneOffset: timeZoneOffset 4818 }; 4819 } 4820 } 4821 return null; 4822 } 4823 4824 var DateEnv = /** @class */ (function () { 4825 function DateEnv(settings) { 4826 var timeZone = this.timeZone = settings.timeZone; 4827 var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC'; 4828 if (settings.namedTimeZoneImpl && isNamedTimeZone) { 4829 this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone); 4830 } 4831 this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl); 4832 this.calendarSystem = createCalendarSystem(settings.calendarSystem); 4833 this.locale = settings.locale; 4834 this.weekDow = settings.locale.week.dow; 4835 this.weekDoy = settings.locale.week.doy; 4836 if (settings.weekNumberCalculation === 'ISO') { 4837 this.weekDow = 1; 4838 this.weekDoy = 4; 4839 } 4840 else if (typeof settings.firstDay === 'number') { 4841 this.weekDow = settings.firstDay; 4842 } 4843 if (typeof settings.weekNumberCalculation === 'function') {
4844 this.weekNumberFunc = settings.weekNumberCalculation; 4845 } 4846 this.weekLabel = settings.weekLabel != null ? settings.weekLabel : settings.locale.options.weekLabel; 4847 this.cmdFormatter = settings.cmdFormatter; 4848 } 4849 // Creating / Parsing 4850 DateEnv.prototype.createMarker = function (input) { 4851 var meta = this.createMarkerMeta(input); 4852 if (meta === null) { 4853 return null; 4854 } 4855 return meta.marker; 4856 }; 4857 DateEnv.prototype.createNowMarker = function () { 4858 if (this.canComputeOffset) { 4859 return this.timestampToMarker(new Date().valueOf()); 4860 } 4861 else { 4862 // if we can't compute the current date val for a timezone, 4863 // better to give the current local date vals than UTC 4864 return arrayToUtcDate(dateToLocalArray(new Date())); 4865 } 4866 }; 4867 DateEnv.prototype.createMarkerMeta = function (input) { 4868 if (typeof input === 'string') { 4869 return this.parse(input); 4870 } 4871 var marker = null; 4872 if (typeof input === 'number') { 4873 marker = this.timestampToMarker(input); 4874 } 4875 else if (input instanceof Date) { 4876 input = input.valueOf(); 4877 if (!isNaN(input)) { 4878 marker = this.timestampToMarker(input); 4879 } 4880 } 4881 else if (Array.isArray(input)) { 4882 marker = arrayToUtcDate(input); 4883 } 4884 if (marker === null || !isValidDate(marker)) { 4885 return null; 4886 } 4887 return { marker: marker, isTimeUnspecified: false, forcedTzo: null }; 4888 }; 4889 DateEnv.prototype.parse = function (s) { 4890 var parts = parse(s); 4891 if (parts === null) { 4892 return null; 4893 } 4894 var marker = parts.marker; 4895 var forcedTzo = null; 4896 if (parts.timeZoneOffset !== null) { 4897 if (this.canComputeOffset) { 4898 marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000); 4899 } 4900 else { 4901 forcedTzo = parts.timeZoneOffset; 4902 } 4903 } 4904 return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo }; 4905 }; 4906 // Accessors 4907 DateEnv.prototype.getYear = function (marker) { 4908 return this.calendarSystem.getMarkerYear(marker); 4909 }; 4910 DateEnv.prototype.getMonth = function (marker) { 4911 return this.calendarSystem.getMarkerMonth(marker); 4912 }; 4913 // Adding / Subtracting 4914 DateEnv.prototype.add = function (marker, dur) { 4915 var a = this.calendarSystem.markerToArray(marker); 4916 a[0] += dur.years; 4917 a[1] += dur.months; 4918 a[2] += dur.days; 4919 a[6] += dur.milliseconds; 4920 return this.calendarSystem.arrayToMarker(a); 4921 }; 4922 DateEnv.prototype.subtract = function (marker, dur) { 4923 var a = this.calendarSystem.markerToArray(marker); 4924 a[0] -= dur.years; 4925 a[1] -= dur.months; 4926 a[2] -= dur.days; 4927 a[6] -= dur.milliseconds; 4928 return this.calendarSystem.arrayToMarker(a); 4929 }; 4930 DateEnv.prototype.addYears = function (marker, n) { 4931 var a = this.calendarSystem.markerToArray(marker); 4932 a[0] += n; 4933 return this.calendarSystem.arrayToMarker(a); 4934 }; 4935 DateEnv.prototype.addMonths = function (marker, n) { 4936 var a = this.calendarSystem.markerToArray(marker); 4937 a[1] += n; 4938 return this.calendarSystem.arrayToMarker(a); 4939 }; 4940 // Diffing Whole Units 4941 DateEnv.prototype.diffWholeYears = function (m0, m1) { 4942 var calendarSystem = this.calendarSystem; 4943 if (timeAsMs(m0) === timeAsMs(m1) && 4944 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) && 4945 calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) { 4946 return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0); 4947 } 4948 return null; 4949 }; 4950 DateEnv.prototype.diffWholeMonths = function (m0, m1) { 4951 var calendarSystem = this.calendarSystem; 4952 if (timeAsMs(m0) === timeAsMs(m1) && 4953 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) { 4954 return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) + 4955 (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12; 4956 } 4957 return null; 4958 }; 4959 // Range / Duration 4960 DateEnv.prototype.greatestWholeUnit = function (m0, m1) { 4961 var n = this.diffWholeYears(m0, m1); 4962 if (n !== null) { 4963 return { unit: 'year', value: n }; 4964 } 4965 n = this.diffWholeMonths(m0, m1); 4966 if (n !== null) { 4967 return { unit: 'month', value: n }; 4968 } 4969 n = diffWholeWeeks(m0, m1); 4970 if (n !== null) { 4971 return { unit: 'week', value: n }; 4972 } 4973 n = diffWholeDays(m0, m1); 4974 if (n !== null) { 4975 return { unit: 'day', value: n }; 4976 } 4977 n = diffHours(m0, m1); 4978 if (isInt(n)) { 4979 return { unit: 'hour', value: n }; 4980 } 4981 n = diffMinutes(m0, m1); 4982 if (isInt(n)) { 4983 return { unit: 'minute', value: n }; 4984 } 4985 n = diffSeconds(m0, m1); 4986 if (isInt(n)) { 4987 return { unit: 'second', value: n }; 4988 } 4989 return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() }; 4990 }; 4991 DateEnv.prototype.countDurationsBetween = function (m0, m1, d) { 4992 // TODO: can use greatestWholeUnit 4993 var diff; 4994 if (d.years) { 4995 diff = this.diffWholeYears(m0, m1); 4996 if (diff !== null) { 4997 return diff / asRoughYears(d); 4998 } 4999 } 5000 if (d.months) { 5001 diff = this.diffWholeMonths(m0, m1); 5002 if (diff !== null) { 5003 return diff / asRoughMonths(d); 5004 } 5005 } 5006 if (d.days) { 5007 diff = diffWholeDays(m0, m1); 5008 if (diff !== null) { 5009 return diff / asRoughDays(d); 5010 } 5011 } 5012 return (m1.valueOf() - m0.valueOf()) / asRoughMs(d); 5013 }; 5014 // Start-Of 5015 DateEnv.prototype.startOf = function (m, unit) { 5016 if (unit === 'year') { 5017 return this.startOfYear(m); 5018 } 5019 else if (unit === 'month') { 5020 return this.startOfMonth(m); 5021 } 5022 else if (unit === 'week') { 5023 return this.startOfWeek(m); 5024 } 5025 else if (unit === 'day') { 5026 return startOfDay(m); 5027 } 5028 else if (unit === 'hour') { 5029 return startOfHour(m); 5030 } 5031 else if (unit === 'minute') { 5032 return startOfMinute(m); 5033 } 5034 else if (unit === 'second') { 5035 return startOfSecond(m); 5036 } 5037 }; 5038 DateEnv.prototype.startOfYear = function (m) { 5039 return this.calendarSystem.arrayToMarker([ 5040 this.calendarSystem.getMarkerYear(m) 5041 ]); 5042 }; 5043 DateEnv.prototype.startOfMonth = function (m) { 5044 return this.calendarSystem.arrayToMarker([ 5045 this.calendarSystem.getMarkerYear(m), 5046 this.calendarSystem.getMarkerMonth(m) 5047 ]); 5048 }; 5049 DateEnv.prototype.startOfWeek = function (m) { 5050 return this.calendarSystem.arrayToMarker([ 5051 this.calendarSystem.getMarkerYear(m), 5052 this.calendarSystem.getMarkerMonth(m), 5053 m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7) 5054 ]); 5055 }; 5056 // Week Number 5057 DateEnv.prototype.computeWeekNumber = function (marker) { 5058 if (this.weekNumberFunc) { 5059 return this.weekNumberFunc(this.toDate(marker)); 5060 } 5061 else { 5062 return weekOfYear(marker, this.weekDow, this.weekDoy); 5063 } 5064 }; 5065 // TODO: choke on timeZoneName: long 5066 DateEnv.prototype.format = function (marker, formatter, dateOptions) { 5067 if (dateOptions === void 0) { dateOptions = {}; } 5068 return formatter.format({ 5069 marker: marker, 5070 timeZoneOffset: dateOptions.forcedTzo != null ? 5071 dateOptions.forcedTzo : 5072 this.offsetForMarker(marker) 5073 }, this); 5074 }; 5075 DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) { 5076 if (dateOptions === void 0) { dateOptions = {}; } 5077 if (dateOptions.isEndExclusive) { 5078 end = addMs(end, -1); 5079 } 5080 return formatter.formatRange({ 5081 marker: start, 5082 timeZoneOffset: dateOptions.forcedStartTzo != null ? 5083 dateOptions.forcedStartTzo : 5084 this.offsetForMarker(start) 5085 }, { 5086 marker: end, 5087 timeZoneOffset: dateOptions.forcedEndTzo != null ? 5088 dateOptions.forcedEndTzo : 5089 this.offsetForMarker(end) 5090 }, this); 5091 }; 5092 DateEnv.prototype.formatIso = function (marker, extraOptions) { 5093 if (extraOptions === void 0) { extraOptions = {}; } 5094 var timeZoneOffset = null; 5095 if (!extraOptions.omitTimeZoneOffset) { 5096 if (extraOptions.forcedTzo != null) { 5097 timeZoneOffset = extraOptions.forcedTzo; 5098 } 5099 else { 5100 timeZoneOffset = this.offsetForMarker(marker); 5101 } 5102 } 5103 return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime); 5104 }; 5105 // TimeZone 5106 DateEnv.prototype.timestampToMarker = function (ms) { 5107 if (this.timeZone === 'local') { 5108 return arrayToUtcDate(dateToLocalArray(new Date(ms))); 5109 } 5110 else if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) { 5111 return new Date(ms); 5112 } 5113 else { 5114 return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms)); 5115 } 5116 }; 5117 DateEnv.prototype.offsetForMarker = function (m) { 5118 if (this.timeZone === 'local') { 5119 return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset 5120 } 5121 else if (this.timeZone === 'UTC') { 5122 return 0; 5123 } 5124 else if (this.namedTimeZoneImpl) { 5125 return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)); 5126 } 5127 return null; 5128 }; 5129 // Conversion 5130 DateEnv.prototype.toDate = function (m, forcedTzo) { 5131 if (this.timeZone === 'local') { 5132 return arrayToLocalDate(dateToUtcArray(m)); 5133 } 5134 else if (this.timeZone === 'UTC') { 5135 return new Date(m.valueOf()); // make sure it's a copy 5136 } 5137 else if (!this.namedTimeZoneImpl) { 5138 return new Date(m.valueOf() - (forcedTzo || 0)); 5139 } 5140 else { 5141 return new Date(m.valueOf() - 5142 this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60 // convert minutes -> ms 5143 ); 5144 } 5145 }; 5146 return DateEnv; 5147 }()); 5148 5149 var SIMPLE_SOURCE_PROPS = { 5150 id: String, 5151 allDayDefault: Boolean, 5152 eventDataTransform: Function, 5153 success: Function, 5154 failure: Function 5155 }; 5156 var uid$2 = 0; 5157 function doesSourceNeedRange(eventSource, calendar) { 5158 var defs = calendar.pluginSystem.hooks.eventSourceDefs; 5159 return !defs[eventSource.sourceDefId].ignoreRange; 5160 } 5161 function parseEventSource(raw, calendar) { 5162 var defs = calendar.pluginSystem.hooks.eventSourceDefs;
5163 for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence 5164 var def = defs[i]; 5165 var meta = def.parseMeta(raw); 5166 if (meta) { 5167 var res = parseEventSourceProps(typeof raw === 'object' ? raw : {}, meta, i, calendar); 5168 res._raw = freezeRaw(raw); 5169 return res; 5170 } 5171 } 5172 return null; 5173 } 5174 function parseEventSourceProps(raw, meta, sourceDefId, calendar) { 5175 var leftovers0 = {}; 5176 var props = refineProps(raw, SIMPLE_SOURCE_PROPS, {}, leftovers0); 5177 var leftovers1 = {}; 5178 var ui = processUnscopedUiProps(leftovers0, calendar, leftovers1); 5179 props.isFetching = false; 5180 props.latestFetchId = ''; 5181 props.fetchRange = null; 5182 props.publicId = String(raw.id || ''); 5183 props.sourceId = String(uid$2++); 5184 props.sourceDefId = sourceDefId; 5185 props.meta = meta; 5186 props.ui = ui; 5187 props.extendedProps = leftovers1; 5188 return props; 5189 } 5190 5191 function reduceEventSources (eventSources, action, dateProfile, calendar) { 5192 switch (action.type) { 5193 case 'ADD_EVENT_SOURCES': // already parsed 5194 return addSources(eventSources, action.sources, dateProfile ? dateProfile.activeRange : null, calendar);
5195 case 'REMOVE_EVENT_SOURCE': 5196 return removeSource(eventSources, action.sourceId); 5197 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 5198 case 'NEXT': 5199 case 'SET_DATE': 5200 case 'SET_VIEW_TYPE': 5201 if (dateProfile) { 5202 return fetchDirtySources(eventSources, dateProfile.activeRange, calendar); 5203 } 5204 else { 5205 return eventSources; 5206 } 5207 case 'FETCH_EVENT_SOURCES': 5208 case 'CHANGE_TIMEZONE': 5209 return fetchSourcesByIds(eventSources, action.sourceIds ? 5210 arrayToHash(action.sourceIds) : 5211 excludeStaticSources(eventSources, calendar), dateProfile ? dateProfile.activeRange : null, calendar); 5212 case 'RECEIVE_EVENTS': 5213 case 'RECEIVE_EVENT_ERROR': 5214 return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange); 5215 case 'REMOVE_ALL_EVENT_SOURCES': 5216 return {}; 5217 default: 5218 return eventSources; 5219 } 5220 } 5221 var uid$3 = 0; 5222 function addSources(eventSourceHash, sources, fetchRange, calendar) { 5223 var hash = {}; 5224 for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) { 5225 var source = sources_1[_i]; 5226 hash[source.sourceId] = source; 5227 } 5228 if (fetchRange) { 5229 hash = fetchDirtySources(hash, fetchRange, calendar); 5230 } 5231 return __assign({}, eventSourceHash, hash); 5232 } 5233 function removeSource(eventSourceHash, sourceId) { 5234 return filterHash(eventSourceHash, function (eventSource) { 5235 return eventSource.sourceId !== sourceId; 5236 }); 5237 } 5238 function fetchDirtySources(sourceHash, fetchRange, calendar) { 5239 return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) { 5240 return isSourceDirty(eventSource, fetchRange, calendar); 5241 }), fetchRange, calendar); 5242 } 5243 function isSourceDirty(eventSource, fetchRange, calendar) { 5244 if (!doesSourceNeedRange(eventSource, calendar)) { 5245 return !eventSource.latestFetchId; 5246 } 5247 else { 5248 return !calendar.opt('lazyFetching') || 5249 !eventSource.fetchRange || 5250 fetchRange.start < eventSource.fetchRange.start || 5251 fetchRange.end > eventSource.fetchRange.end; 5252 } 5253 } 5254 function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, calendar) { 5255 var nextSources = {}; 5256 for (var sourceId in prevSources) { 5257 var source = prevSources[sourceId]; 5258 if (sourceIdHash[sourceId]) { 5259 nextSources[sourceId] = fetchSource(source, fetchRange, calendar); 5260 } 5261 else { 5262 nextSources[sourceId] = source; 5263 } 5264 } 5265 return nextSources; 5266 } 5267 function fetchSource(eventSource, fetchRange, calendar) { 5268 var sourceDef = calendar.pluginSystem.hooks.eventSourceDefs[eventSource.sourceDefId]; 5269 var fetchId = String(uid$3++); 5270 sourceDef.fetch({ 5271 eventSource: eventSource, 5272 calendar: calendar, 5273 range: fetchRange 5274 }, function (res) { 5275 var rawEvents = res.rawEvents; 5276 var calSuccess = calendar.opt('eventSourceSuccess'); 5277 var calSuccessRes; 5278 var sourceSuccessRes; 5279 if (eventSource.success) { 5280 sourceSuccessRes = eventSource.success(rawEvents, res.xhr); 5281 } 5282 if (calSuccess) { 5283 calSuccessRes = calSuccess(rawEvents, res.xhr); 5284 } 5285 rawEvents = sourceSuccessRes || calSuccessRes || rawEvents; 5286 calendar.dispatch({ 5287 type: 'RECEIVE_EVENTS', 5288 sourceId: eventSource.sourceId, 5289 fetchId: fetchId, 5290 fetchRange: fetchRange, 5291 rawEvents: rawEvents 5292 }); 5293 }, function (error) { 5294 var callFailure = calendar.opt('eventSourceFailure'); 5295 console.warn(error.message, error); 5296 if (eventSource.failure) { 5297 eventSource.failure(error); 5298 } 5299 if (callFailure) { 5300 callFailure(error); 5301 } 5302 calendar.dispatch({ 5303 type: 'RECEIVE_EVENT_ERROR', 5304 sourceId: eventSource.sourceId, 5305 fetchId: fetchId, 5306 fetchRange: fetchRange, 5307 error: error 5308 }); 5309 }); 5310 return __assign({}, eventSource, { isFetching: true, latestFetchId: fetchId }); 5311 } 5312 function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) { 5313 var _a; 5314 var eventSource = sourceHash[sourceId]; 5315 if (eventSource && // not already removed 5316 fetchId === eventSource.latestFetchId) { 5317 return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange }), _a)); 5318 } 5319 return sourceHash; 5320 } 5321 function excludeStaticSources(eventSources, calendar) { 5322 return filterHash(eventSources, function (eventSource) { 5323 return doesSourceNeedRange(eventSource, calendar); 5324 }); 5325 } 5326 5327 var DateProfileGenerator = /** @class */ (function () { 5328 function DateProfileGenerator(viewSpec, calendar) { 5329 this.viewSpec = viewSpec; 5330 this.options = viewSpec.options; 5331 this.dateEnv = calendar.dateEnv; 5332 this.calendar = calendar; 5333 this.initHiddenDays(); 5334 } 5335 /* Date Range Computation 5336 ------------------------------------------------------------------------------------------------------------------*/ 5337 // Builds a structure with info about what the dates/ranges will be for the "prev" view. 5338 DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate) { 5339 var dateEnv = this.dateEnv; 5340 var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5341 currentDateProfile.dateIncrement); 5342 return this.build(prevDate, -1); 5343 }; 5344 // Builds a structure with info about what the dates/ranges will be for the "next" view. 5345 DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate) { 5346 var dateEnv = this.dateEnv; 5347 var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5348 currentDateProfile.dateIncrement); 5349 return this.build(nextDate, 1); 5350 }; 5351 // Builds a structure holding dates/ranges for rendering around the given date. 5352 // Optional direction param indicates whether the date is being incremented/decremented 5353 // from its previous value. decremented = -1, incremented = 1 (default). 5354 DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) { 5355 if (forceToValid === void 0) { forceToValid = false; }
5356 var validRange; 5357 var minTime = null; 5358 var maxTime = null; 5359 var currentInfo; 5360 var isRangeAllDay; 5361 var renderRange; 5362 var activeRange; 5363 var isValid; 5364 validRange = this.buildValidRange(); 5365 validRange = this.trimHiddenDays(validRange); 5366 if (forceToValid) { 5367 currentDate = constrainMarkerToRange(currentDate, validRange); 5368 } 5369 currentInfo = this.buildCurrentRangeInfo(currentDate, direction); 5370 isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit); 5371 renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay); 5372 renderRange = this.trimHiddenDays(renderRange); 5373 activeRange = renderRange; 5374 if (!this.options.showNonCurrentDates) { 5375 activeRange = intersectRanges(activeRange, currentInfo.range); 5376 } 5377 minTime = createDuration(this.options.minTime); 5378 maxTime = createDuration(this.options.maxTime); 5379 activeRange = this.adjustActiveRange(activeRange, minTime, maxTime); 5380 activeRange = intersectRanges(activeRange, validRange); // might return null 5381 // it's invalid if the originally requested date is not contained, 5382 // or if the range is completely outside of the valid range. 5383 isValid = rangesIntersect(currentInfo.range, validRange); 5384 return { 5385 // constraint for where prev/next operations can go and where events can be dragged/resized to. 5386 // an object with optional start and end properties. 5387 validRange: validRange, 5388 // range the view is formally responsible for. 5389 // for example, a month view might have 1st-31st, excluding padded dates 5390 currentRange: currentInfo.range, 5391 // name of largest unit being displayed, like "month" or "week" 5392 currentRangeUnit: currentInfo.unit, 5393 isRangeAllDay: isRangeAllDay, 5394 // dates that display events and accept drag-n-drop 5395 // will be `null` if no dates accept events 5396 activeRange: activeRange, 5397 // date range with a rendered skeleton 5398 // includes not-active days that need some sort of DOM 5399 renderRange: renderRange, 5400 // Duration object that denotes the first visible time of any given day 5401 minTime: minTime, 5402 // Duration object that denotes the exclusive visible end time of any given day 5403 maxTime: maxTime, 5404 isValid: isValid, 5405 // how far the current date will move for a prev/next operation 5406 dateIncrement: this.buildDateIncrement(currentInfo.duration) 5407 // pass a fallback (might be null) ^ 5408 }; 5409 }; 5410 // Builds an object with optional start/end properties. 5411 // Indicates the minimum/maximum dates to display. 5412 // not responsible for trimming hidden days. 5413 DateProfileGenerator.prototype.buildValidRange = function () { 5414 return this.getRangeOption('validRange', this.calendar.getNow()) || 5415 { start: null, end: null }; // completely open-ended 5416 }; 5417 // Builds a structure with info about the "current" range, the range that is 5418 // highlighted as being the current month for example. 5419 // See build() for a description of `direction`. 5420 // Guaranteed to have `range` and `unit` properties. `duration` is optional. 5421 DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) { 5422 var _a = this, viewSpec = _a.viewSpec, dateEnv = _a.dateEnv; 5423 var duration = null; 5424 var unit = null; 5425 var range = null; 5426 var dayCount; 5427 if (viewSpec.duration) { 5428 duration = viewSpec.duration; 5429 unit = viewSpec.durationUnit; 5430 range = this.buildRangeFromDuration(date, direction, duration, unit); 5431 } 5432 else if ((dayCount = this.options.dayCount)) { 5433 unit = 'day'; 5434 range = this.buildRangeFromDayCount(date, direction, dayCount); 5435 } 5436 else if ((range = this.buildCustomVisibleRange(date))) { 5437 unit = dateEnv.greatestWholeUnit(range.start, range.end).unit; 5438 } 5439 else { 5440 duration = this.getFallbackDuration(); 5441 unit = greatestDurationDenominator(duration).unit; 5442 range = this.buildRangeFromDuration(date, direction, duration, unit); 5443 } 5444 return { duration: duration, unit: unit, range: range }; 5445 }; 5446 DateProfileGenerator.prototype.getFallbackDuration = function () { 5447 return createDuration({ day: 1 }); 5448 }; 5449 // Returns a new activeRange to have time values (un-ambiguate) 5450 // minTime or maxTime causes the range to expand. 5451 DateProfileGenerator.prototype.adjustActiveRange = function (range, minTime, maxTime) { 5452 var dateEnv = this.dateEnv; 5453 var start = range.start; 5454 var end = range.end; 5455 if (this.viewSpec.class.prototype.usesMinMaxTime) { 5456 // expand active range if minTime is negative (why not when positive?) 5457 if (asRoughDays(minTime) < 0) { 5458 start = startOfDay(start); // necessary? 5459 start = dateEnv.add(start, minTime); 5460 } 5461 // expand active range if maxTime is beyond one day (why not when positive?) 5462 if (asRoughDays(maxTime) > 1) { 5463 end = startOfDay(end); // necessary? 5464 end = addDays(end, -1); 5465 end = dateEnv.add(end, maxTime); 5466 } 5467 } 5468 return { start: start, end: end }; 5469 }; 5470 // Builds the "current" range when it is specified as an explicit duration. 5471 // `unit` is the already-computed greatestDurationDenominator unit of duration. 5472 DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) { 5473 var dateEnv = this.dateEnv; 5474 var alignment = this.options.dateAlignment; 5475 var dateIncrementInput; 5476 var dateIncrementDuration; 5477 var start; 5478 var end; 5479 var res; 5480 // compute what the alignment should be 5481 if (!alignment) { 5482 dateIncrementInput = this.options.dateIncrement; 5483 if (dateIncrementInput) { 5484 dateIncrementDuration = createDuration(dateIncrementInput); 5485 // use the smaller of the two units 5486 if (asRoughMs(dateIncrementDuration) < asRoughMs(duration)) { 5487 alignment = greatestDurationDenominator(dateIncrementDuration, !getWeeksFromInput(dateIncrementInput)).unit; 5488 } 5489 else { 5490 alignment = unit; 5491 } 5492 } 5493 else { 5494 alignment = unit; 5495 } 5496 }
5497 // if the view displays a single day or smaller 5498 if (asRoughDays(duration) <= 1) { 5499 if (this.isHiddenDay(start)) { 5500 start = this.skipHiddenDays(start, direction); 5501 start = startOfDay(start); 5502 } 5503 } 5504 function computeRes() { 5505 start = dateEnv.startOf(date, alignment); 5506 end = dateEnv.add(start, duration); 5507 res = { start: start, end: end }; 5508 } 5509 computeRes(); 5510 // if range is completely enveloped by hidden days, go past the hidden days 5511 if (!this.trimHiddenDays(res)) { 5512 date = this.skipHiddenDays(date, direction); 5513 computeRes(); 5514 } 5515 return res; 5516 }; 5517 // Builds the "current" range when a dayCount is specified. 5518 DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) { 5519 var dateEnv = this.dateEnv; 5520 var customAlignment = this.options.dateAlignment; 5521 var runningCount = 0; 5522 var start = date; 5523 var end; 5524 if (customAlignment) { 5525 start = dateEnv.startOf(start, customAlignment); 5526 } 5527 start = startOfDay(start); 5528 start = this.skipHiddenDays(start, direction); 5529 end = start; 5530 do { 5531 end = addDays(end, 1); 5532 if (!this.isHiddenDay(end)) { 5533 runningCount++; 5534 } 5535 } while (runningCount < dayCount); 5536 return { start: start, end: end }; 5537 }; 5538 // Builds a normalized range object for the "visible" range, 5539 // which is a way to define the currentRange and activeRange at the same time. 5540 DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) { 5541 var dateEnv = this.dateEnv; 5542 var visibleRange = this.getRangeOption('visibleRange', dateEnv.toDate(date)); 5543 if (visibleRange && (visibleRange.start == null || visibleRange.end == null)) { 5544 return null; 5545 } 5546 return visibleRange; 5547 }; 5548 // Computes the range that will represent the element/cells for *rendering*, 5549 // but which may have voided days/times. 5550 // not responsible for trimming hidden days. 5551 DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { 5552 return currentRange; 5553 }; 5554 // Compute the duration value that should be added/substracted to the current date 5555 // when a prev/next operation happens. 5556 DateProfileGenerator.prototype.buildDateIncrement = function (fallback) { 5557 var dateIncrementInput = this.options.dateIncrement; 5558 var customAlignment; 5559 if (dateIncrementInput) { 5560 return createDuration(dateIncrementInput); 5561 } 5562 else if ((customAlignment = this.options.dateAlignment)) { 5563 return createDuration(1, customAlignment); 5564 } 5565 else if (fallback) { 5566 return fallback; 5567 } 5568 else { 5569 return createDuration({ days: 1 }); 5570 } 5571 }; 5572 // Arguments after name will be forwarded to a hypothetical function value 5573 // WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects. 5574 // Always clone your objects if you fear mutation. 5575 DateProfileGenerator.prototype.getRangeOption = function (name) { 5576 var otherArgs = []; 5577 for (var _i = 1; _i < arguments.length; _i++) { 5578 otherArgs[_i - 1] = arguments[_i]; 5579 } 5580 var val = this.options[name]; 5581 if (typeof val === 'function') { 5582 val = val.apply(null, otherArgs); 5583 } 5584 if (val) { 5585 val = parseRange(val, this.dateEnv); 5586 } 5587 if (val) { 5588 val = computeVisibleDayRange(val); 5589 } 5590 return val; 5591 }; 5592 /* Hidden Days 5593 ------------------------------------------------------------------------------------------------------------------*/ 5594 // Initializes internal variables related to calculating hidden days-of-week 5595 DateProfileGenerator.prototype.initHiddenDays = function () { 5596 var hiddenDays = this.options.hiddenDays || []; // array of day-of-week indices that are hidden
5597 var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool) 5598 var dayCnt = 0; 5599 var i; 5600 if (this.options.weekends === false) { 5601 hiddenDays.push(0, 6); // 0=sunday, 6=saturday 5602 } 5603 for (i = 0; i < 7; i++) { 5604 if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) { 5605 dayCnt++; 5606 } 5607 } 5608 if (!dayCnt) { 5609 throw new Error('invalid hiddenDays'); // all days were hidden? bad. 5610 } 5611 this.isHiddenDayHash = isHiddenDayHash; 5612 }; 5613 // Remove days from the beginning and end of the range that are computed as hidden. 5614 // If the whole range is trimmed off, returns null 5615 DateProfileGenerator.prototype.trimHiddenDays = function (range) { 5616 var start = range.start; 5617 var end = range.end; 5618 if (start) { 5619 start = this.skipHiddenDays(start); 5620 } 5621 if (end) { 5622 end = this.skipHiddenDays(end, -1, true); 5623 } 5624 if (start == null || end == null || start < end) { 5625 return { start: start, end: end }; 5626 } 5627 return null; 5628 }; 5629 // Is the current day hidden? 5630 // `day` is a day-of-week index (0-6), or a Date (used for UTC) 5631 DateProfileGenerator.prototype.isHiddenDay = function (day) { 5632 if (day instanceof Date) { 5633 day = day.getUTCDay(); 5634 } 5635 return this.isHiddenDayHash[day]; 5636 }; 5637 // Incrementing the current day until it is no longer a hidden day, returning a copy. 5638 // DOES NOT CONSIDER validRange! 5639 // If the initial value of `date` is not a hidden day, don't do anything. 5640 // Pass `isExclusive` as `true` if you are dealing with an end date. 5641 // `inc` defaults to `1` (increment one day forward each time) 5642 DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) { 5643 if (inc === void 0) { inc = 1; } 5644 if (isExclusive === void 0) { isExclusive = false; } 5645 while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) { 5646 date = addDays(date, inc); 5647 } 5648 return date; 5649 }; 5650 return DateProfileGenerator; 5651 }());
5652 // TODO: find a way to avoid comparing DateProfiles. it's tedious 5653 function isDateProfilesEqual(p0, p1) { 5654 return rangesEqual(p0.activeRange, p1.activeRange) && 5655 rangesEqual(p0.validRange, p1.validRange) && 5656 durationsEqual(p0.minTime, p1.minTime) && 5657 durationsEqual(p0.maxTime, p1.maxTime); 5658 } 5659 5660 function reduce (state, action, calendar) { 5661 var viewType = reduceViewType(state.viewType, action); 5662 var dateProfile = reduceDateProfile(state.dateProfile, action, state.currentDate, viewType, calendar); 5663 var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendar); 5664 var nextState = __assign({}, state, { viewType: viewType, 5665 dateProfile: dateProfile, currentDate: reduceCurrentDate(state.currentDate, action, dateProfile), eventSources: eventSources, eventStore: reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendar), dateSelection: reduceDateSelection(state.dateSelection, action, calendar), eventSelection: reduceSelectedEvent(state.eventSelection, action), eventDrag: reduceEventDrag(state.eventDrag, action, eventSources, calendar), eventResize: reduceEventResize(state.eventResize, action, eventSources, calendar), eventSourceLoadingLevel: computeLoadingLevel(eventSources), loadingLevel: computeLoadingLevel(eventSources) }); 5666 for (var _i = 0, _a = calendar.pluginSystem.hooks.reducers; _i < _a.length; _i++) { 5667 var reducerFunc = _a[_i]; 5668 nextState = reducerFunc(nextState, action, calendar); 5669 } 5670 // console.log(action.type, nextState) 5671 return nextState; 5672 } 5673 function reduceViewType(currentViewType, action) { 5674 switch (action.type) { 5675 case 'SET_VIEW_TYPE': 5676 return action.viewType; 5677 default: 5678 return currentViewType; 5679 } 5680 } 5681 function reduceDateProfile(currentDateProfile, action, currentDate, viewType, calendar) { 5682 var newDateProfile; 5683 switch (action.type) { 5684 case 'PREV': 5685 newDateProfile = calendar.dateProfileGenerators[viewType].buildPrev(currentDateProfile, currentDate); 5686 break; 5687 case 'NEXT': 5688 newDateProfile = calendar.dateProfileGenerators[viewType].buildNext(currentDateProfile, currentDate); 5689 break; 5690 case 'SET_DATE': 5691 if (!currentDateProfile.activeRange || 5692 !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker)) { 5693 newDateProfile = calendar.dateProfileGenerators[viewType].build(action.dateMarker, undefined, true // forceToValid 5694 ); 5695 } 5696 break; 5697 case 'SET_VIEW_TYPE': 5698 var generator = calendar.dateProfileGenerators[viewType]; 5699 if (!generator) { 5700 throw new Error(viewType ? 5701 'The FullCalendar view "' + viewType + '" does not exist. Make sure your plugins are loaded correctly.' : 5702 'No available FullCalendar view plugins.'); 5703 } 5704 newDateProfile = generator.build(action.dateMarker || currentDate, undefined, true // forceToValid 5705 ); 5706 break; 5707 } 5708 if (newDateProfile && 5709 newDateProfile.isValid && 5710 !(currentDateProfile && isDateProfilesEqual(currentDateProfile, newDateProfile))) { 5711 return newDateProfile; 5712 } 5713 else { 5714 return currentDateProfile; 5715 } 5716 } 5717 function reduceCurrentDate(currentDate, action, dateProfile) { 5718 switch (action.type) { 5719 case 'PREV': 5720 case 'NEXT': 5721 if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) { 5722 return dateProfile.currentRange.start; 5723 } 5724 else { 5725 return currentDate; 5726 } 5727 case 'SET_DATE': 5728 case 'SET_VIEW_TYPE': 5729 var newDate = action.dateMarker || currentDate; 5730 if (dateProfile.activeRange && !rangeContainsMarker(dateProfile.activeRange, newD
5730ate)) { 5731 return dateProfile.currentRange.start; 5732 } 5733 else { 5734 return newDate; 5735 } 5736 default: 5737 return currentDate; 5738 } 5739 } 5740 function reduceDateSelection(currentSelection, action, calendar) { 5741 switch (action.type) { 5742 case 'SELECT_DATES': 5743 return action.selection; 5744 case 'UNSELECT_DATES': 5745 return null; 5746 default: 5747 return currentSelection; 5748 } 5749 } 5750 function reduceSelectedEvent(currentInstanceId, action) { 5751 switch (action.type) { 5752 case 'SELECT_EVENT': 5753 return action.eventInstanceId; 5754 case 'UNSELECT_EVENT': 5755 return ''; 5756 default: 5757 return currentInstanceId; 5758 } 5759 } 5760 function reduceEventDrag(currentDrag, action, sources, calendar) { 5761 switch (action.type) { 5762 case 'SET_EVENT_DRAG': 5763 var newDrag = action.state; 5764 return { 5765 affectedEvents: newDrag.affectedEvents, 5766 mutatedEvents: newDrag.mutatedEvents, 5767 isEvent: newDrag.isEvent, 5768 origSeg: newDrag.origSeg 5769 }; 5770 case 'UNSET_EVENT_DRAG': 5771 return null; 5772 default: 5773 return currentDrag; 5774 } 5775 } 5776 function reduceEventResize(currentResize, action, sources, calendar) { 5777 switch (action.type) { 5778 case 'SET_EVENT_RESIZE': 5779 var newResize = action.state; 5780 return { 5781 affectedEvents: newResize.affectedEvents, 5782 mutatedEvents: newResize.mutatedEvents, 5783 isEvent: newResize.isEvent, 5784 origSeg: newResize.origSeg 5785 }; 5786 case 'UNSET_EVENT_RESIZE': 5787 return null; 5788 default: 5789 return currentResize; 5790 } 5791 } 5792 function computeLoadingLevel(eventSources) { 5793 var cnt = 0; 5794 for (var sourceId in eventSources) { 5795 if (eventSources[sourceId].isFetching) { 5796 cnt++; 5797 } 5798 } 5799 return cnt; 5800 } 5801 5802 var STANDARD_PROPS = { 5803 start: null, 5804 end: null, 5805 allDay: Boolean 5806 }; 5807 function parseDateSpan(raw, dateEnv, defaultDuration) { 5808 var span = parseOpenDateSpan(raw, dateEnv); 5809 var range = span.range; 5810 if (!range.start) { 5811 return null; 5812 } 5813 if (!range.end) { 5814 if (defaultDuration == null) { 5815 return null; 5816 } 5817 else { 5818 range.end = dateEnv.add(range.start, defaultDuration); 5819 } 5820 } 5821 return span; 5822 } 5823 /* 5824 TODO: somehow combine with parseRange? 5825 Will return null if the start/end props were present but parsed invalidly. 5826 */ 5827 function parseOpenDateSpan(raw, dateEnv) { 5828 var leftovers = {}; 5829 var standardProps = refineProps(raw, STANDARD_PROPS, {}, leftovers); 5830 var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null; 5831 var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null; 5832 var allDay = standardProps.allDay; 5833 if (allDay == null) { 5834 allDay = (startMeta && startMeta.isTimeUnspecified) && 5835 (!endMeta || endMeta.isTimeUnspecified); 5836 } 5837 // use this leftover object as the selection object 5838 leftovers.range = { 5839 start: startMeta ? startMeta.marker : null, 5840 end: endMeta ? endMeta.marker : null 5841 }; 5842 leftovers.allDay = allDay; 5843 return leftovers; 5844 } 5845 function isDateSpansEqual(span0, span1) { 5846 return rangesEqual(span0.range, span1.range) && 5847 span0.allDay === span1.allDay && 5848 isSpanPropsEqual(span0, span1); 5849 } 5850 // the NON-DATE-RELATED props 5851 function isSpanPropsEqual(span0, span1) { 5852 for (var propName in span1) { 5853 if (propName !== 'range' && propName !== 'allDay') { 5854 if (span0[propName] !== span1[propName]) { 5855 return false;
5856 } 5857 } 5858 } 5859 // are there any props that span0 has that span1 DOESN'T have? 5860 // both have range/allDay, so no need to special-case. 5861 for (var propName in span0) { 5862 if (!(propName in span1)) { 5863 return false; 5864 } 5865 } 5866 return true; 5867 } 5868 function buildDateSpanApi(span, dateEnv) { 5869 return { 5870 start: dateEnv.toDate(span.range.start), 5871 end: dateEnv.toDate(span.range.end), 5872 startStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), 5873 endStr: dateEnv.formatIso(span.range.end, { omitTime: span.allDay }), 5874 allDay: span.allDay 5875 }; 5876 } 5877 function buildDatePointApi(span, dateEnv) { 5878 return { 5879 date: dateEnv.toDate(span.range.start), 5880 dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), 5881 allDay: span.allDay 5882 }; 5883 } 5884 function fabricateEventRange(dateSpan, eventUiBases, calendar) { 5885 var def = parseEventDef({ editable: false }, '', // sourceId 5886 dateSpan.allDay, true, // hasEnd 5887 calendar); 5888 return { 5889 def: def, 5890 ui: compileEventUi(def, eventUiBases), 5891 instance: createEventInstance(def.defId, dateSpan.range), 5892 range: dateSpan.range, 5893 isStart: true, 5894 isEnd: true 5895 }; 5896 } 5897 5898 function compileViewDefs(defaultConfigs, overrideConfigs) { 5899 var hash = {}; 5900 var viewType; 5901 for (viewType in defaultConfigs) { 5902 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5903 } 5904 for (viewType in overrideConfigs) { 5905 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5906 } 5907 return hash; 5908 } 5909 function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5910 if (hash[viewType]) { 5911 return hash[viewType]; 5912 } 5913 var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5914 if (viewDef) { 5915 hash[viewType] = viewDef; 5916 } 5917 return viewDef; 5918 } 5919 function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5920 var defaultConfig = defaultConfigs[viewType]; 5921 var overrideConfig = overrideConfigs[viewType]; 5922 var queryProp = function (name) { 5923 return (defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] : 5924 ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null); 5925 }; 5926 var theClass = queryProp('class'); 5927 var superType = queryProp('superType'); 5928 if (!superType && theClass) { 5929 superType = 5930 findViewNameBySubclass(theClass, overrideConfigs) || 5931 findViewNameBySubclass(theClass, defaultConfigs); 5932 } 5933 var superDef = superType ? ensureViewDef(superType, hash, defaultConfigs, overrideConfigs) : null; 5934 if (!theClass && superDef) { 5935 theClass = superDef.class; 5936 } 5937 if (!theClass) { 5938 return null; // don't throw a warning, might be settings for a single-unit view 5939 } 5940 return { 5941 type: viewType, 5942 class: theClass, 5943 defaults: __assign({}, (superDef ? superDef.defaults : {}), (defaultConfig ? defaultConfig.options : {})), 5944 overrides: __assign({}, (superDef ? superDef.overrides : {}), (overrideConfig ? overrideConfig.options : {})) 5945 }; 5946 } 5947 function findViewNameBySubclass(viewSubclass, configs) { 5948 var superProto = Object.getPrototypeOf(viewSubclass.prototype); 5949 for (var viewType in configs) { 5950 var parsed = configs[viewType]; 5951 // need DIRECT subclass, so instanceof won't do it 5952 if (parsed.class && parsed.class.prototype === superProto) { 5953 return viewType; 5954 } 5955 } 5956 return ''; 5957 } 5958 5959 function parseViewConfigs(inputs) { 5960 return mapHash(inputs, parseViewConfig); 5961 } 5962 var VIEW_DEF_PROPS = { 5963 type: String, 5964 class: null 5965 }; 5966 function parseViewConfig(input) { 5967 if (typeof input === 'function') { 5968 input = { class: input }; 5969 } 5970 var options = {}; 5971 var props = refineProps(input, VIEW_DEF_PROPS, {}, options); 5972 return { 5973 superType: props.type, 5974 class: props.class, 5975 options: options 5976 }; 5977 } 5978 5979 function buildViewSpecs(defaultInputs, optionsManager) { 5980 var defaultConfigs = parseViewConfigs(defaultInputs); 5981 var overrideConfigs = parseViewConfigs(optionsManager.overrides.views); 5982 var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs); 5983 return mapHash(viewDefs, function (viewDef) { 5984 return buildViewSpec(viewDef, overrideConfigs, optionsManager); 5985 }); 5986 } 5987 function buildViewSpec(viewDef, overrideConfigs, optionsManager) { 5988 var durationInput = viewDef.overrides.duration || 5989 viewDef.defaults.duration || 5990 optionsManager.dynamicOverrides.duration || 5991 optionsManager.overrides.duration; 5992 var duration = null; 5993 var durationUnit = ''; 5994 var singleUnit = ''; 5995 var singleUnitOverrides = {}; 5996 if (durationInput) { 5997 duration = createDuration(durationInput); 5998 if (duration) { // valid? 5999 var denom = greatestDurationDenominator(duration, !getWeeksFromInput(durationInput)); 6000 durationUnit = denom.unit; 6001 if (denom.value === 1) { 6002 singleUnit = durationUnit; 6003 singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].options : {}; 6004 } 6005 } 6006 } 6007 var queryButtonText = function (options) { 6008 var buttonTextMap = options.buttonText || {}; 6009 var buttonTextKey = viewDef.defaults.buttonTextKey; 6010 if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) { 6011 return buttonTextMap[buttonTextKey]; 6012 } 6013 if (buttonTextMap[viewDef.type] != null) { 6014 return buttonTextMap[viewDef.type]; 6015 } 6016 if (buttonTextMap[singleUnit] != null) { 6017 return buttonTextMap[singleUnit]; 6018 } 6019 }; 6020 return { 6021 type: viewDef.type, 6022 class: viewDef.class, 6023 duration: duration, 6024 durationUnit: durationUnit, 6025 singleUnit: singleUnit, 6026 options: __assign({}, globalDefaults, viewDef.defaults, optionsManager.dirDefaults, optionsManager.localeDefaults, optionsManager.overrides, singleUnitOverrides, viewDef.overrides, optionsManager.dynamicOverrides), 6027 buttonTextOverride: queryButtonText(optionsManager.dynamicOverrides) || 6028 queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence 6029 viewDef.overrides.buttonText, 6030 buttonTextDefault: queryButtonText(optionsManager.localeDefaults) || 6031 queryButtonText(optionsManager.dirDefaults) || 6032 viewDef.defaults.buttonText || 6033 queryButtonText(globalDefaults) || 6034 viewDef.type // fall back to given view name 6035 }; 6036 } 6037 6038 var Toolbar = /** @class */ (function (_super) { 6039 __extends(Toolbar, _super); 6040 function Toolbar(context, extraClassName) { 6041 var _this = _super.call(this, context) || this; 6042 _this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout); 6043 _this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]); 6044 _this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]); 6045 _this._updateToday = memoizeRendering(_this.updateToday, null, [_this._renderLayout]); 6046 _this._updatePrev = memoizeRendering(_this.updatePrev, null, [_this._renderLayout]); 6047 _this._updateNext = memoizeRendering(_this.updateNext, null, [_this._renderLayout]); 6048 _this.el = createElement('div', { className: 'fc-toolbar ' + extraClassName }); 6049 return _this; 6050 } 6051 Toolbar.prototype.destroy = function () { 6052 _super.prototype.destroy.call(this); 6053 this._renderLayout.unrender(); // should unrender everything else 6054 removeElement(this.el); 6055 }; 6056 Toolbar.prototype.render = function (props) { 6057 this._renderLayout(props.layout); 6058 this._updateTitle(props.title); 6059 this._updateActiveButton(props.activeButton); 6060 this._updateToday(props.isTodayEnabled); 6061 this._updatePrev(props.isPrevEnabled); 6062 this._updateNext(props.isNextEnabled); 6063 }; 6064 Toolbar.prototype.renderLayout = function (layout) { 6065 var el = this.el; 6066 this.viewsWithButtons = []; 6067 appendToElement(el, this.renderSection('left', layout.left)); 6068 appendToElement(el, this.renderSection('center', layout.center)); 6069 appendToElement(el, this.renderSection('right', layout.right)); 6070 }; 6071 Toolbar.prototype.unrenderLayout = function () { 6072 this.el.innerHTML = ''; 6073 }; 6074 Toolbar.prototype.renderSection = function (position, buttonStr) { 6075 var _this = this; 6076 var _a = this, theme = _a.theme, calendar = _a.calendar; 6077 var optionsManager = calendar.optionsManager; 6078 var viewSpecs = calendar.viewSpecs; 6079 var sectionEl = createElement('div', { className: 'fc-' + position }); 6080 var calendarCustomButtons = optionsManager.computed.customButtons || {}; 6081 var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {}; 6082 var calendarButtonText = optionsManager.computed.buttonText || {}; 6083 if (buttonStr) { 6084 buttonStr.split(' ').forEach(function (buttonGroupStr, i) { 6085 var groupChildren = []; 6086 var isOnlyButtons = true; 6087 var groupEl; 6088 buttonGroupStr.split(',').forEach(function (buttonName, j) { 6089 var customButtonProps; 6090 var viewSpec; 6091 var buttonClick; 6092 var buttonIcon; // only one of these will be set 6093 var buttonText; // " 6094 var buttonInnerHtml;
6095 var buttonClasses; 6096 var buttonEl; 6097 var buttonAriaAttr; 6098 if (buttonName === 'title') { 6099 groupChildren.push(htmlToElement('<h2> </h2>')); // we always want it to take up height 6100 isOnlyButtons = false; 6101 } 6102 else { 6103 if ((customButtonProps = calendarCustomButtons[buttonName])) { 6104 buttonClick = function (ev) { 6105 if (customButtonProps.click) { 6106 customButtonProps.click.call(buttonEl, ev); 6107 } 6108 }; 6109 (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) || 6110 (buttonIcon = theme.getIconClass(buttonName)) || 6111 (buttonText = customButtonProps.text); 6112 } 6113 else if ((viewSpec = viewSpecs[buttonName])) { 6114 _this.viewsWithButtons.push(buttonName); 6115 buttonClick = function () { 6116 calendar.changeView(buttonName); 6117 }; 6118 (buttonText = viewSpec.buttonTextOverride) || 6119 (buttonIcon = theme.getIconClass(buttonName)) || 6120 (buttonText = viewSpec.buttonTextDefault); 6121 } 6122 else if (calendar[buttonName]) { // a calendar method 6123 buttonClick = function () { 6124 calendar[buttonName](); 6125 }; 6126 (buttonText = calendarButtonTextOverrides[buttonName]) || 6127 (buttonIcon = theme.getIconClass(buttonName)) || 6128 (buttonText = calendarButtonText[buttonName]); 6129 // ^ everything else is considered default 6130 } 6131 if (buttonClick) { 6132 buttonClasses = [ 6133 'fc-' + buttonName + '-button', 6134 theme.getClass('button') 6135 ]; 6136 if (buttonText) { 6137 buttonInnerHtml = htmlEscape(buttonText); 6138 buttonAriaAttr = ''; 6139 } 6140 else if (buttonIcon) { 6141 buttonInnerHtml = "<span class='" + buttonIcon + "'></span>"; 6142 buttonAriaAttr = ' aria-label="' + buttonName + '"'; 6143 } 6144 buttonEl = htmlToElement(// type="button" so that it doesn't submit a form 6145 '<button type="button" class="' + buttonClasses.join(' ') + '"' + 6146 buttonAriaAttr + 6147 '>' + buttonInnerHtml + '</button>'); 6148 buttonEl.addEventListener('click', buttonClick); 6149 groupChildren.push(buttonEl); 6150 } 6151 } 6152 }); 6153 if (groupChildren.length > 1) { 6154 groupEl = document.createElement('div'); 6155 var buttonGroupClassName = theme.getClass('buttonGroup'); 6156 if (isOnlyButtons && buttonGroupClassName) { 6157 groupEl.classList.add(buttonGroupClassName); 6158 } 6159 appendToElement(groupEl, groupChildren); 6160 sectionEl.appendChild(groupEl); 6161 } 6162 else { 6163 appendToElement(sectionEl, groupChildren); // 1 or 0 children 6164 } 6165 }); 6166 } 6167 return sectionEl; 6168 }; 6169 Toolbar.prototype.updateToday = function (isTodayEnabled) { 6170 this.toggleButtonEnabled('today', isTodayEnabled); 6171 }; 6172 Toolbar.prototype.updatePrev = function (isPrevEnabled) { 6173 this.toggleButtonEnabled('prev', isPrevEnabled); 6174 }; 6175 Toolbar.prototype.updateNext = function (isNextEnabled) { 6176 this.toggleButtonEnabled('next', isNextEnabled); 6177 }; 6178 Toolbar.prototype.updateTitle = function (text) { 6179 findElements(this.el, 'h2').forEach(function (titleEl) { 6180 titleEl.innerText = text; 6181 }); 6182 }; 6183 Toolbar.prototype.updateActiveButton = function (buttonName) { 6184 var className = this.theme.getClass('buttonActive'); 6185 findElements(this.el, 'button').forEach(function (buttonEl) { 6186 if (buttonName && buttonEl.classList.contains('fc-'
6186+ buttonName + '-button')) { 6187 buttonEl.classList.add(className); 6188 } 6189 else { 6190 buttonEl.classList.remove(className); 6191 } 6192 }); 6193 }; 6194 Toolbar.prototype.toggleButtonEnabled = function (buttonName, bool) { 6195 findElements(this.el, '.fc-' + buttonName + '-button').forEach(function (buttonEl) { 6196 buttonEl.disabled = !bool; 6197 }); 6198 }; 6199 return Toolbar; 6200 }(Component)); 6201 6202 var CalendarComponent = /** @class */ (function (_super) { 6203 __extends(CalendarComponent, _super); 6204 function CalendarComponent(context, el) { 6205 var _this = _super.call(this, context) || this; 6206 _this._renderToolbars = memoizeRendering(_this.renderToolbars); 6207 _this.buildViewPropTransformers = memoize(buildViewPropTransformers); 6208 _this.el = el; 6209 prependToElement(el, _this.contentEl = createElement('div', { className: 'fc-view-container' })); 6210 var calendar = _this.calendar; 6211 for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) { 6212 var modifyViewContainer = _a[_i]; 6213 modifyViewContainer(_this.contentEl, calendar); 6214 } 6215 _this.toggleElClassNames(true); 6216 _this.computeTitle = memoize(computeTitle); 6217 _this.parseBusinessHours = memoize(function (input) { 6218 return parseBusinessHours(input, _this.calendar); 6219 }); 6220 return _this; 6221 } 6222 CalendarComponent.prototype.destroy = function () { 6223 if (this.header) { 6224 this.header.destroy(); 6225 } 6226 if (this.footer) { 6227 this.footer.destroy(); 6228 } 6229 if (this.view) { 6230 this.view.destroy(); 6231 } 6232 removeElement(this.contentEl); 6233 this.toggleElClassNames(false); 6234 _super.prototype.destroy.call(this); 6235 }; 6236 CalendarComponent.prototype.toggleElClassNames = function (bool) { 6237 var classList = this.el.classList; 6238 var dirClassName = 'fc-' + this.opt('dir'); 6239 var themeClassName = this.theme.getClass('widget'); 6240 if (bool) { 6241 classList.add('fc'); 6242 classList.add(dirClassName); 6243 classList.add(themeClassName); 6244 } 6245 else { 6246 classList.remove('fc'); 6247 classList.remove(dirClassName); 6248 classList.remove(themeClassName); 6249 } 6250 }; 6251 CalendarComponent.prototype.render = function (props) { 6252 this.freezeHeight(); 6253 var title = this.computeTitle(props.dateProfile, props.viewSpec.options); 6254 this._renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, props.dateProfileGenerator, title); 6255 this.renderView(props, title); 6256 this.updateSize(); 6257 this.thawHeight(); 6258 }; 6259 CalendarComponent.prototype.renderToolbars = function (viewSpec, dateProfile, currentDate, dateProfileGenerator, title) { 6260 var headerLayout = this.opt('header'); 6261 var footerLayout = this.opt('footer'); 6262 var now = this.calendar.getNow(); 6263 var todayInfo = dateProfileGenerator.build(now); 6264 var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate); 6265 var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate); 6266 var toolbarProps = { 6267 title: title, 6268 activeButton: viewSpec.type, 6269 isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now), 6270 isPrevEnabled: prevInfo.isValid, 6271 isNextEnabled: nextInfo.isValid 6272 }; 6273 if (headerLayout) { 6274 if (!this.header) { 6275 this.header = new Toolbar(this.context, 'fc-header-toolbar'); 6276 prependToElement(this.el, this.header.el); 6277 } 6278 this.header.receiveProps(__assign({ layout: headerLayout }, toolbarProps)); 6279 } 6280 else if (this.header) { 6281 this.header.destroy(); 6282 this.header = null; 6283 }
6284 if (footerLayout) { 6285 if (!this.footer) { 6286 this.footer = new Toolbar(this.context, 'fc-footer-toolbar'); 6287 appendToElement(this.el, this.footer.el); 6288 } 6289 this.footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps)); 6290 } 6291 else if (this.footer) { 6292 this.footer.destroy(); 6293 this.footer = null; 6294 } 6295 }; 6296 CalendarComponent.prototype.renderView = function (props, title) { 6297 var view = this.view; 6298 var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator; 6299 if (!view || view.viewSpec !== viewSpec) { 6300 if (view) { 6301 view.destroy(); 6302 } 6303 view = this.view = new viewSpec['class']({ 6304 calendar: this.calendar, 6305 view: null, 6306 dateEnv: this.dateEnv, 6307 theme: this.theme, 6308 options: viewSpec.options 6309 }, viewSpec, dateProfileGenerator, this.contentEl); 6310 } 6311 else { 6312 view.addScroll(view.queryScroll()); 6313 } 6314 view.title = title; // for the API 6315 var viewProps = { 6316 dateProfile: props.dateProfile, 6317 businessHours: this.parseBusinessHours(viewSpec.options.businessHours), 6318 eventStore: props.eventStore, 6319 eventUiBases: props.eventUiBases, 6320 dateSelection: props.dateSelection, 6321 eventSelection: props.eventSelection, 6322 eventDrag: props.eventDrag, 6323 eventResize: props.eventResize 6324 }; 6325 var transformers = this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers); 6326 for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { 6327 var transformer = transformers_1[_i]; 6328 __assign(viewProps, transformer.transform(viewProps, viewSpec, props, view)); 6329 } 6330 view.receiveProps(viewProps); 6331 }; 6332 // Sizing 6333 // ----------------------------------------------------------------------------------------------------------------- 6334 CalendarComponent.prototype.updateSize = function (isResize) { 6335 if (isResize === void 0) { isResize = false; } 6336 var view = this.view; 6337 if (isResize) { 6338 view.addScroll(view.queryScroll()); 6339 } 6340 if (isResize || this.isHeightAuto == null) { 6341 this.computeHeightVars(); 6342 } 6343 view.updateSize(isResize, this.viewHeight, this.isHeightAuto); 6344 view.updateNowIndicator(); // we need to guarantee this will run after updateSize 6345 view.popScroll(isResize); 6346 }; 6347 CalendarComponent.prototype.computeHeightVars = function () { 6348 var calendar = this.calendar; // yuck. need to handle dynamic options 6349 var heightInput = calendar.opt('height'); 6350 var contentHeightInput = calendar.opt('contentHeight'); 6351 this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto'; 6352 if (typeof contentHeightInput === 'number') { // exists and not 'auto' 6353 this.viewHeight = contentHeightInput; 6354 } 6355 else if (typeof contentHeightInput === 'function') { // exists and is a function 6356 this.viewHeight = contentHeightInput(); 6357 } 6358 else if (typeof heightInput === 'number') { // exists and not 'auto' 6359 this.viewHeight = heightInput - this.queryToolbarsHeight(); 6360 } 6361 else if (typeof heightInput === 'function') { // exists and is a function 6362 this.viewHeight = heightInput() - this.queryToolbarsHeight(); 6363 } 6364 else if (heightInput === 'parent') { // set to height of parent element 6365 this.viewHeight = this.el.parentNode.offsetHeight - this.queryToolbarsHeight(); 6366 } 6367 else { 6368 this.viewHeight = Math.round(this.contentEl.offsetWidth / 6369 Math.max(calendar.opt('aspectRatio'), .5)); 6370 } 6371 }; 6372 CalendarComponent.prototype.queryToolbarsHeight = function () { 6373 var height = 0; 6374 if (this.header) { 6375 height += computeHeightAndMargins(this.header.el); 6376 } 6377 if (this.footer) { 6378 height += computeHeightAndMargins(this.footer.el); 6379 } 6380 return height; 6381 }; 6382 // Height "Freezing" 6383 // ----------------------------------------------------------------------------------------------------------------- 6384 CalendarComponent.prototype.freezeHeight = function () { 6385 applyStyle(this.el, { 6386 height: this.el.offsetHeight, 6387 overflow: 'hidden' 6388 }); 6389 }; 6390 CalendarComponent.prototype.thawHeight = function () { 6391 applyStyle(this.el, { 6392 height: '', 6393 overflow: '' 6394 }); 6395 }; 6396 return CalendarComponent; 6397 }(Component)); 6398 // Title and Date Formatting 6399 // ----------------------------------------------------------------------------------------------------------------- 6400 // Computes what the title at the top of the calendar should be for this view 6401 function computeTitle(dateProfile, viewOptions) { 6402 var range; 6403 // for views that span a large unit of time, show the proper interval, ignoring stray days before and after 6404 if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) { 6405 range = dateProfile.currentRange; 6406 } 6407 else { // for day units or smaller, use the actual day range 6408 range = dateProfile.activeRange; 6409 } 6410 return this.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay }); 6411 }
6412 // Generates the format string that should be used to generate the title for the current date range. 6413 // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`. 6414 function computeTitleFormat(dateProfile) { 6415 var currentRangeUnit = dateProfile.currentRangeUnit; 6416 if (currentRangeUnit === 'year') { 6417 return { year: 'numeric' }; 6418 } 6419 else if (currentRangeUnit === 'month') { 6420 return { year: 'numeric', month: 'long' }; // like "September 2014" 6421 } 6422 else { 6423 var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end); 6424 if (days !== null && days > 1) { 6425 // multi-day range. shorter, like "Sep 9 - 10 2014" 6426 return { year: 'numeric', month: 'short', day: 'numeric' }; 6427 } 6428 else { 6429 // one day. longer, like "September 9 2014" 6430 return { year: 'numeric', month: 'long', day: 'numeric' }; 6431 } 6432 } 6433 } 6434 // Plugin 6435 // ----------------------------------------------------------------------------------------------------------------- 6436 function buildViewPropTransformers(theClasses) { 6437 return theClasses.map(function (theClass) { 6438 return new theClass(); 6439 }); 6440 } 6441 6442 var Interaction = /** @class */ (function () { 6443 function Interaction(settings) { 6444 this.component = settings.component; 6445 } 6446 Interaction.prototype.destroy = function () { 6447 }; 6448 return Interaction; 6449 }()); 6450 function parseInteractionSettings(component, input) { 6451 return { 6452 component: component, 6453 el: input.el, 6454 useEventCenter: input.useEventCenter != null ? input.useEventCenter : true 6455 }; 6456 } 6457 function interactionSettingsToStore(settings) { 6458 var _a; 6459 return _a = {}, 6460 _a[settings.component.uid] = settings, 6461 _a; 6462 } 6463 // global state 6464 var interactionSettingsStore = {}; 6465 6466 /* 6467 Detects when the user clicks on an event within a DateComponent 6468 */ 6469 var EventClicking = /** @class */ (function (_super) { 6470 __extends(EventClicking, _super); 6471 function EventClicking(settings) { 6472 var _this = _super.call(this, settings) || this; 6473 _this.handleSegClick = function (ev, segEl) { 6474 var component = _this.component; 6475 var seg = getElSeg(segEl); 6476 if (seg && // might be the <div> surrounding the more link 6477 component.isValidSegDownEl(ev.target)) { 6478 // our way to simulate a link click for elements that can't be <a> tags 6479 // grab before trigger fired in case trigger trashes DOM thru rerendering 6480 var hasUrlContainer = elementClosest(ev.target, '.fc-has-url'); 6481 var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : ''; 6482 component.publiclyTrigger('eventClick', [ 6483 { 6484 el: segEl, 6485 event: new EventApi(component.calendar, seg.eventRange.def, seg.eventRange.instance), 6486 jsEvent: ev, 6487 view: component.view 6488 } 6489 ]); 6490 if (url && !ev.defaultPrevented) { 6491 window.location.href = url; 6492 } 6493 } 6494 }; 6495 var component = settings.component; 6496 _this.destroy = listenBySelector(component.el, 'click', component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegClick); 6497 return _this; 6498 } 6499 return EventClicking; 6500 }(Interaction)); 6501 6502 /* 6503 Triggers events and adds/removes core classNames when the user's pointer 6504 enters/leaves event-elements of a component. 6505 */ 6506 var EventHovering = /** @class */ (function (_super) { 6507 __extends(EventHovering, _super); 6508 function EventHovering(settings) { 6509 var _this = _super.call(this, settings) || this; 6510 // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it 6511 _this.handleEventElRemove = function (el) { 6512 if (el === _this.currentSegEl) { 6513 _this.handleSegLeave(null, _this.currentSegEl); 6514 } 6515 }; 6516 _this.handleSegEnter = function (ev, segEl) { 6517 if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper 6518 segEl.classList.add('fc-allow-mouse-resize'); 6519 _this.currentSegEl = segEl; 6520 _this.triggerEvent('eventMouseEnter', ev, segEl); 6521 } 6522 }; 6523 _this.handleSegLeave = function (ev, segEl) { 6524 if (_this.currentSegEl) { 6525 segEl.classList.remove('fc-allow-mouse-resize'); 6526 _this.currentSegEl = null; 6527 _this.triggerEvent('eventMouseLeave', ev, segEl); 6528 } 6529 }; 6530 var component = settings.component; 6531 _this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave); 6532 component.calendar.on('eventElRemove', _this.handleEventElRemove); 6533 return _this; 6534 } 6535 EventHovering.prototype.destroy = function () { 6536 this.removeHoverListeners(); 6537 this.component.calendar.off('eventElRemove', this.handleEventElRemove); 6538 }; 6539 EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) { 6540 var component = this.component; 6541 var seg = getElSeg(segEl); 6542 if (!ev || component.isValidSegDownEl(ev.target)) { 6543 component.publiclyTrigger(publicEvName, [ 6544 { 6545 el: segEl, 6546 event: new EventApi(this.component.calendar, seg.eventRange.def, seg.eventRange.instance), 6547 jsEvent: ev, 6548 view: component.view 6549 } 6550 ]); 6551 } 6552 }; 6553 return EventHovering; 6554 }(Interaction)); 6555 6556 var StandardTheme = /** @class */ (function (_super) { 6557 __extends(StandardTheme, _super); 6558 function StandardTheme() { 6559 return _super !== null && _super.apply(this, arguments) || this; 6560 } 6561 return StandardTheme; 6562 }(Theme)); 6563 StandardTheme.prototype.classes = { 6564 widget: 'fc-unthemed', 6565 widgetHeader: 'fc-widget-header', 6566 widgetContent: 'fc-widget-content', 6567 buttonGroup: 'fc-button-group', 6568 button: 'fc-button fc-button-primary', 6569 buttonActive: 'fc-button-active', 6570 popoverHeader: 'fc-widget-header', 6571 popoverContent: 'fc-widget-content', 6572 // day grid 6573 headerRow: 'fc-widget-header', 6574 dayRow: 'fc-widget-content', 6575 // list view 6576 listView: 'fc-widget-content' 6577 }; 6578 StandardTheme.prototype.baseIconClass = 'fc-icon'; 6579 StandardTheme.prototype.iconClasses = { 6580 close: 'fc-icon-x', 6581 prev: 'fc-icon-chevron-left', 6582 next: 'fc-icon-chevron-right', 6583 prevYear: 'fc-icon-chevrons-left', 6584 nextYear: 'fc-icon-chevrons-right' 6585 }; 6586 StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; 6587 StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon'; 6588 StandardTheme.prototype.iconOverridePrefix = 'fc-icon-'; 6589 6590 var Calendar = /** @class */ (function () { 6591 function Calendar(el, overrides) { 6592 var _this = this; 6593 this.parseRawLocales = memoize(parseRawLocales); 6594 this.buildLocale = memoize(buildLocale); 6595 this.buildDateEnv = memoize(buildDateEnv); 6596 this.buildTheme = memoize(buildTheme); 6597 this.buildEventUiSingleBase = memoize(this._buildEventUiSingleBase); 6598 this.buildSelectionConfig = memoize(this._buildSelectionConfig); 6599 this.buildEventUiBySource = memoizeOutput(buildEventUiBySource, isObjectsSimilar); 6600 this.buildEventUiBases = memoize(buildEventUiBases); 6601 this.interactionsStore = {}; 6602 this.actionQueue = []; 6603 this.isReducing = false;
6604 // isDisplaying: boolean = false // installed in DOM? accepting renders? 6605 this.needsRerender = false; // needs a render? 6606 this.needsFullRerender = false; 6607 this.isRendering = false; // currently in the executeRender function? 6608 this.renderingPauseDepth = 0; 6609 this.buildDelayedRerender = memoize(buildDelayedRerender); 6610 this.afterSizingTriggers = {}; 6611 this.isViewUpdated = false; 6612 this.isDatesUpdated = false; 6613 this.isEventsUpdated = false; 6614 this.el = el; 6615 this.optionsManager = new OptionsManager(overrides || {}); 6616 this.pluginSystem = new PluginSystem(); 6617 // only do once. don't do in handleOptions. because can't remove plugins 6618 this.addPluginInputs(this.optionsManager.computed.plugins || []); 6619 this.handleOptions(this.optionsManager.computed); 6620 this.publiclyTrigger('_init'); // for tests 6621 this.hydrate(); 6622 this.calendarInteractions = this.pluginSystem.hooks.calendarInteractions 6623 .map(function (calendarInteractionClass) { 6624 return new calendarInteractionClass(_this); 6625 }); 6626 } 6627 Calendar.prototype.addPluginInputs = function (pluginInputs) { 6628 var pluginDefs = refinePluginDefs(pluginInputs); 6629 for (var _i = 0, pluginDefs_1 = pluginDefs; _i < pluginDefs_1.length; _i++) { 6630 var pluginDef = pluginDefs_1[_i]; 6631 this.pluginSystem.add(pluginDef); 6632 } 6633 }; 6634 Object.defineProperty(Calendar.prototype, "view", { 6635 // public API 6636 get: function () { 6637 return this.component ? this.component.view : null; 6638 }, 6639 enumerable: true, 6640 configurable: true 6641 }); 6642 // Public API for rendering 6643 // ----------------------------------------------------------------------------------------------------------------- 6644 Calendar.prototype.render = function () { 6645 if (!this.component) { 6646 this.renderableEventStore = createEmptyEventStore(); 6647 this.bindHandlers(); 6648 this.executeRender(); 6649 } 6650 else { 6651 this.requestRerender(true); 6652 } 6653 }; 6654 Calendar.prototype.destroy = function () { 6655 if (this.component) { 6656 this.unbindHandlers(); 6657 this.component.destroy(); // don't null-out. in case API needs access 6658 this.component = null; // umm ??? 6659 for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) { 6660 var interaction = _a[_i]; 6661 interaction.destroy(); 6662 } 6663 this.publiclyTrigger('_destroyed'); 6664 } 6665 }; 6666 // Handlers 6667 // ----------------------------------------------------------------------------------------------------------------- 6668 Calendar.prototype.bindHandlers = function () { 6669 var _this = this; 6670 // event delegation for nav links 6671 this.removeNavLinkListener = listenBySelector(this.el, 'click', 'a[data-goto]', function (ev, anchorEl) { 6672 var gotoOptions = anchorEl.getAttribute('data-goto'); 6673 gotoOptions = gotoOptions ? JSON.parse(gotoOptions) : {}; 6674 var dateEnv = _this.dateEnv; 6675 var dateMarker = dateEnv.createMarker(gotoOptions.date); 6676 var viewType = gotoOptions.type; 6677 // property like "navLinkDayClick". might be a string or a function 6678 var customAction = _this.viewOpt('navLink' + capitaliseFirstLetter(viewType) + 'Click'); 6679 if (typeof customAction === 'function') { 6680 customAction(dateEnv.toDate(dateMarker), ev); 6681 } 6682 else { 6683 if (typeof customAction === 'string') { 6684 viewType = customAction; 6685 }
6686 _this.zoomTo(dateMarker, viewType); 6687 } 6688 }); 6689 if (this.opt('handleWindowResize')) { 6690 window.addEventListener('resize', this.windowResizeProxy = debounce(// prevents rapid calls 6691 this.windowResize.bind(this), this.opt('windowResizeDelay'))); 6692 } 6693 }; 6694 Calendar.prototype.unbindHandlers = function () { 6695 this.removeNavLinkListener(); 6696 if (this.windowResizeProxy) { 6697 window.removeEventListener('resize', this.windowResizeProxy); 6698 this.windowResizeProxy = null; 6699 } 6700 }; 6701 // Dispatcher 6702 // ----------------------------------------------------------------------------------------------------------------- 6703 Calendar.prototype.hydrate = function () { 6704 var _this = this; 6705 this.state = this.buildInitialState(); 6706 var rawSources = this.opt('eventSources') || []; 6707 var singleRawSource = this.opt('events'); 6708 var sources = []; // parsed 6709 if (singleRawSource) { 6710 rawSources.unshift(singleRawSource); 6711 } 6712 for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) { 6713 var rawSource = rawSources_1[_i]; 6714 var source = parseEventSource(rawSource, this); 6715 if (source) { 6716 sources.push(source); 6717 } 6718 } 6719 this.batchRendering(function () { 6720 _this.dispatch({ type: 'INIT' }); // pass in sources here? 6721 _this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: sources }); 6722 _this.dispatch({ 6723 type: 'SET_VIEW_TYPE', 6724 viewType: _this.opt('defaultView') || _this.pluginSystem.hooks.defaultView 6725 }); 6726 }); 6727 }; 6728 Calendar.prototype.buildInitialState = function () { 6729 return { 6730 viewType: null, 6731 loadingLevel: 0, 6732 eventSourceLoadingLevel: 0, 6733 currentDate: this.getInitialDate(), 6734 dateProfile: null, 6735 eventSources: {}, 6736 eventStore: createEmptyEventStore(), 6737 dateSelection: null, 6738 eventSelection: '', 6739 eventDrag: null, 6740 eventResize: null 6741 }; 6742 }; 6743 Calendar.prototype.dispatch = function (action) { 6744 this.actionQueue.push(action); 6745 if (!this.isReducing) { 6746 this.isReducing = true; 6747 var oldState = this.state; 6748 while (this.actionQueue.length) { 6749 this.state = this.reduce(this.state, this.actionQueue.shift(), this); 6750 } 6751 var newState = this.state; 6752 this.isReducing = false; 6753 if (!oldState.loadingLevel && newState.loadingLevel) { 6754 this.publiclyTrigger('loading', [true]); 6755 } 6756 else if (oldState.loadingLevel && !newState.loadingLevel) { 6757 this.publiclyTrigger('loading', [false]); 6758 } 6759 var view = this.component && this.component.view; 6760 if (oldState.eventStore !== newState.eventStore || this.needsFullRerender) { 6761 if (oldState.eventStore) { 6762 this.isEventsUpdated = true; 6763 } 6764 } 6765 if (oldState.dateProfile !== newState.dateProfile || this.needsFullRerender) { 6766 if (oldState.dateProfile && view) { // why would view be null!? 6767 this.publiclyTrigger('datesDestroy', [ 6768 { 6769 view: view, 6770 el: view.el 6771 } 6772 ]); 6773 } 6774 this.isDatesUpdated = true; 6775 } 6776 if (oldState.viewType !== newState.viewType || this.needsFullRerender) { 6777 if (oldState.viewType && view) { // why would view be null!? 6778 this.publiclyTrigger('viewSkeletonDestroy', [ 6779 { 6780 view: view, 6781 el: view.el 6782 } 6783 ]); 6784 } 6785 this.isViewUpdated = true; 6786 } 6787 this.requestRerender(); 6788 } 6789 }; 6790 Calendar.prototype.reduce = function (state, action, calendar) { 6791 return reduce(state, action, calendar); 6792 }; 6793 // Render Queue 6794 // ----------------------------------------------------------------------------------------------------------------- 6795 Calendar.prototype.requestRerender = function (needsFull) { 6796 if (needsFull === void 0) { needsFull = false; } 6797 this.needsRerender = true; 6798 this.needsFullRerender = this.needsFullRerender || needsFull; 6799 this.delayedRerender(); // will call a debounced-version of tryRerender 6800 }; 6801 Calendar.prototype.tryRerender = function () { 6802 if (this.component && // must be accepting renders 6803 this.needsRerender && // indicates that a rerender was requested 6804 !this.renderingPauseDepth && // not paused 6805 !this.isRendering // not currently in the render loop 6806 ) {
6807 this.executeRender(); 6808 } 6809 }; 6810 Calendar.prototype.batchRendering = function (func) { 6811 this.renderingPauseDepth++; 6812 func(); 6813 this.renderingPauseDepth--; 6814 if (this.needsRerender) { 6815 this.requestRerender(); 6816 } 6817 }; 6818 // Rendering 6819 // ----------------------------------------------------------------------------------------------------------------- 6820 Calendar.prototype.executeRender = function () { 6821 var needsFullRerender = this.needsFullRerender; // save before clearing 6822 // clear these BEFORE the render so that new values will accumulate during render 6823 this.needsRerender = false; 6824 this.needsFullRerender = false; 6825 this.isRendering = true; 6826 this.renderComponent(needsFullRerender); 6827 this.isRendering = false; 6828 // received a rerender request while rendering 6829 if (this.needsRerender) { 6830 this.delayedRerender(); 6831 } 6832 }; 6833 /* 6834 don't call this directly. use executeRender instead 6835 */ 6836 Calendar.prototype.renderComponent = function (needsFull) { 6837 var _a = this, state = _a.state, component = _a.component; 6838 var viewType = state.viewType; 6839 var viewSpec = this.viewSpecs[viewType]; 6840 var savedScroll = (needsFull && component) ? component.view.queryScroll() : null; 6841 if (!viewSpec) { 6842 throw new Error("View type \"" + viewType + "\" is not valid"); 6843 } 6844 // if event sources are still loading and progressive rendering hasn't been enabled, 6845 // keep rendering the last fully loaded set of events 6846 var renderableEventStore = this.renderableEventStore = 6847 (state.eventSourceLoadingLevel && !this.opt('progressiveEventRendering')) ? 6848 this.renderableEventStore : 6849 state.eventStore; 6850 var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options); 6851 var eventUiBySource = this.buildEventUiBySource(state.eventSources); 6852 var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource); 6853 if (needsFull || !component) { 6854 if (component) { 6855 component.freezeHeight(); // next component will unfreeze it 6856 component.destroy(); 6857 } 6858 component = this.component = new CalendarComponent({ 6859 calendar: this, 6860 view: null, 6861 dateEnv: this.dateEnv, 6862 theme: this.theme, 6863 options: this.optionsManager.computed 6864 }, this.el); 6865 } 6866 component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfile: state.dateProfile, dateProfileGenerator: this.dateProfileGenerators[viewType], eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize })); 6867 if (savedScroll) { 6868 component.view.applyScroll(savedScroll, false); 6869 } 6870 if (this.isViewUpdated) { 6871 this.isViewUpdated = false; 6872 this.publiclyTrigger('viewSkeletonRender', [ 6873 { 6874 view: component.view, 6875 el: component.view.el 6876 } 6877 ]); 6878 } 6879 if (this.isDatesUpdated) { 6880 this.isDatesUpdated = false; 6881 this.publiclyTrigger('datesRender', [ 6882 { 6883 view: component.view, 6884 el: component.view.el 6885 } 6886 ]); 6887 } 6888 if (this.isEventsUpdated) { 6889 this.isEventsUpdated = false; 6890 } 6891 this.releaseAfterSizingTriggers(); 6892 }; 6893 // Options 6894 // ----------------------------------------------------------------------------------------------------------------- 6895 /* 6896 Not meant for public API 6897 */ 6898 Calendar.prototype.resetOptions = function (options) { 6899 var _this = this; 6900 var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers; 6901 var oldOptions = this.optionsManager.overrides; 6902 var oldNormalOptions = {}; 6903 var normalOptions = {}; 6904 var specialOptions = {}; 6905 for (var name_1 in oldOptions) { 6906 if (!changeHandlers[name_1]) { 6907 oldNormalOptions[name_1] = oldOptions[name_1]; 6908 } 6909 } 6910 for (var name_2 in options) { 6911 if (changeHandlers[name_2]) { 6912 specialOptions[name_2] = options[name_2]; 6913 } 6914 else { 6915 normalOptions[name_2] = options[name_2]; 6916 } 6917 } 6918 this.batchRendering(function () { 6919 if (anyKeysRemoved(oldNormalOptions, normalOptions)) { 6920 _this.processOptions(options, 'reset'); 6921 } 6922 else { 6923 _this.processOptions(computeChangedProps(oldNormalOptions, normalOptions)); 6924 } 6925 // handle special options last 6926 for (var name_3 in specialOptions) { 6927 changeHandlers[name_3](specialOptions[name_3], _this); 6928 } 6929 }); 6930 }; 6931 /* 6932 Not meant for public API. Won't give the same precedence that setOption does 6933 */ 6934 Calendar.prototype.setOptions = function (options) { 6935 var _this = this; 6936 var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers; 6937 var normalOptions = {}; 6938 var specialOptions = {}; 6939 for (var name_4 in options) { 6940 if (changeHandlers[name_4]) { 6941 specialOptions[name_4] = options[name_4]; 6942 } 6943 else { 6944 normalOptions[name_4] = options[name_4]; 6945 } 6946 } 6947 this.batchRendering(function () { 6948 _this.processOptions(normalOptions); 6949 // handle special options last 6950 for (var name_5 in specialOptions) { 6951 changeHandlers[name_5](specialOptions[name_5], _this); 6952 } 6953 }); 6954 }; 6955 Calendar.prototype.processOptions = function (options, mode) { 6956 var _this = this; 6957 var oldDateEnv = this.dateEnv; // do this before handleOptions 6958 var isTimeZoneDirty = false;
6959 var isSizeDirty = false; 6960 var anyDifficultOptions = false; 6961 for (var name_6 in options) { 6962 if (/^(height|contentHeight|aspectRatio)$/.test(name_6)) { 6963 isSizeDirty = true; 6964 } 6965 else if (/^(defaultDate|defaultView)$/.test(name_6)) ; 6966 else { 6967 anyDifficultOptions = true; 6968 if (name_6 === 'timeZone') { 6969 isTimeZoneDirty = true; 6970 } 6971 } 6972 } 6973 if (mode === 'reset') { 6974 anyDifficultOptions = true; 6975 this.optionsManager.reset(options); 6976 } 6977 else if (mode === 'dynamic') { 6978 this.optionsManager.addDynamic(options); // takes higher precedence 6979 } 6980 else { 6981 this.optionsManager.add(options); 6982 } 6983 if (anyDifficultOptions) { 6984 this.handleOptions(this.optionsManager.computed); // only for "difficult" options 6985 this.needsFullRerender = true; 6986 this.batchRendering(function () { 6987 if (isTimeZoneDirty) { 6988 _this.dispatch({ 6989 type: 'CHANGE_TIMEZONE', 6990 oldDateEnv: oldDateEnv 6991 }); 6992 } 6993 /* HACK 6994 has the same effect as calling this.requestRerender(true) 6995 but recomputes the state's dateProfile 6996 */ 6997 _this.dispatch({ 6998 type: 'SET_VIEW_TYPE', 6999 viewType: _this.state.viewType 7000 }); 7001 }); 7002 } 7003 if (isSizeDirty) { 7004 this.updateSize(); 7005 } 7006 }; 7007 Calendar.prototype.setOption = function (name, val) { 7008 var _a; 7009 this.processOptions((_a = {}, _a[name] = val, _a), 'dynamic'); 7010 }; 7011 Calendar.prototype.getOption = function (name) { 7012 return this.optionsManager.computed[name]; 7013 }; 7014 Calendar.prototype.opt = function (name) { 7015 return this.optionsManager.computed[name]; 7016 }; 7017 Calendar.prototype.viewOpt = function (name) { 7018 return this.viewOpts()[name]; 7019 }; 7020 Calendar.prototype.viewOpts = function () { 7021 return this.viewSpecs[this.state.viewType].options; 7022 }; 7023 /* 7024 rebuilds things based off of a complete set of refined options 7025 */ 7026 Calendar.prototype.handleOptions = function (options) { 7027 var _this = this; 7028 var pluginHooks = this.pluginSystem.hooks; 7029 this.defaultAllDayEventDuration = createDuration(options.defaultAllDayEventDuration); 7030 this.defaultTimedEventDuration = createDuration(options.defaultTimedEventDuration); 7031 this.delayedRerender = this.buildDelayedRerender(options.rerenderDelay); 7032 this.theme = this.buildTheme(options); 7033 var available = this.parseRawLocales(options.locales); 7034 this.availableRawLocales = available.map; 7035 var locale = this.buildLocale(options.locale || available.defaultCode, available.map); 7036 this.dateEnv = this.buildDateEnv(locale, options.timeZone, pluginHooks.namedTimeZonedImpl, options.firstDay, options.weekNumberCalculation, options.weekLabel, pluginHooks.cmdFormatter); 7037 this.selectionConfig = this.buildSelectionConfig(options); // needs dateEnv. do after :( 7038 // ineffecient to do every time? 7039 this.viewSpecs = buildViewSpecs(pluginHooks.views, this.optionsManager); 7040 // ineffecient to do every time? 7041 this.dateProfileGenerators = mapHash(this.viewSpecs, function (viewSpec) { 7042 return new viewSpec.class.prototype.dateProfileGeneratorClass(viewSpec, _this); 7043 }); 7044 }; 7045 Calendar.prototype.getAvailableLocaleCodes = function () { 7046 return Object.keys(this.availableRawLocales); 7047 }; 7048 Calendar.prototype._buildSelectionConfig = function (rawOpts) { 7049 return processScopedUiProps('select', rawOpts, this); 7050 }; 7051 Calendar.prototype._buildEventUiSingleBase = function (rawOpts) { 7052 if (rawOpts.editable) { // so 'editable' affected events 7053 rawOpts = __assign({}, rawOpts, { eventEditable: true }); 7054 } 7055 return processScopedUiProps('event', rawOpts, this); 7056 }; 7057 // Trigger 7058 // ----------------------------------------------------------------------------------------------------------------- 7059 Calendar.prototype.hasPublicHandlers = function (name) { 7060 return this.hasHandlers(name) || 7061 this.opt(name); // handler specified in options 7062 }; 7063 Calendar.prototype.publiclyTrigger = function (name, args) { 7064 var optHandler = this.opt(name); 7065 this.triggerWith(name, this, args); 7066 if (optHandler) { 7067 return optHandler.apply(this, args); 7068 } 7069 }; 7070 Calendar.prototype.publiclyTriggerAfterSizing = function (name, args) { 7071 var afterSizingTriggers = this.afterSizingTriggers; 7072 (afterSizingTriggers[name] || (afterSizingTriggers[name] = [])).push(args); 7073 }; 7074 Calendar.prototype.releaseAfterSizingTriggers = function () { 7075 var afterSizingTriggers = this.afterSizingTriggers; 7076 for (var name_7 in afterSizingTriggers) { 7077 for (var _i = 0, _a = afterSizingTriggers[name_7]; _i < _a.length; _i++) { 7078 var args = _a[_i]; 7079 this.publiclyTrigger(name_7, args); 7080 } 7081 } 7082 this.afterSizingTriggers = {}; 7083 }; 7084 // View 7085 // ----------------------------------------------------------------------------------------------------------------- 7086 // Returns a boolean about whether the view is okay to instantiate at some point 7087 Calendar.prototype.isValidViewType = function (viewType) { 7088 return Boolean(this.viewSpecs[viewType]); 7089 }; 7090 Calendar.prototype.changeView = function (viewType, dateOrRange) { 7091 var dateMarker = null; 7092 if (dateOrRange) { 7093 if (dateOrRange.start && dateOrRange.end) { // a range 7094 this.optionsManager.addDynamic({ visibleRange: dateOrRange }); // will not rerender 7095 this.handleOptions(this.optionsManager.computed); // ...but yuck 7096 } 7097 else { // a date 7098 dateMarker = this.dateEnv.createMarker(dateOrRange); // just like gotoDate 7099 } 7100 } 7101 this.unselect(); 7102 this.dispatch({ 7103 type: 'SET_VIEW_TYPE', 7104 viewType: viewType, 7105 dateMarker: dateMarker 7106 }); 7107 };
7108 // Forces navigation to a view for the given date. 7109 // `viewType` can be a specific view name or a generic one like "week" or "day". 7110 // needs to change 7111 Calendar.prototype.zoomTo = function (dateMarker, viewType) { 7112 var spec; 7113 viewType = viewType || 'day'; // day is default zoom 7114 spec = this.viewSpecs[viewType] || 7115 this.getUnitViewSpec(viewType); 7116 this.unselect(); 7117 if (spec) { 7118 this.dispatch({ 7119 type: 'SET_VIEW_TYPE', 7120 viewType: spec.type, 7121 dateMarker: dateMarker 7122 }); 7123 } 7124 else { 7125 this.dispatch({ 7126 type: 'SET_DATE', 7127 dateMarker: dateMarker 7128 }); 7129 } 7130 }; 7131 // Given a duration singular unit, like "week" or "day", finds a matching view spec. 7132 // Preference is given to views that have corresponding buttons. 7133 Calendar.prototype.getUnitViewSpec = function (unit) { 7134 var component = this.component; 7135 var viewTypes = []; 7136 var i; 7137 var spec; 7138 // put views that have buttons first. there will be duplicates, but oh 7139 if (component.header) { 7140 viewTypes.push.apply(viewTypes, component.header.viewsWithButtons); 7141 } 7142 if (component.footer) { 7143 viewTypes.push.apply(viewTypes, component.footer.viewsWithButtons); 7144 } 7145 for (var viewType in this.viewSpecs) { 7146 viewTypes.push(viewType); 7147 } 7148 for (i = 0; i < viewTypes.length; i++) { 7149 spec = this.viewSpecs[viewTypes[i]]; 7150 if (spec) { 7151 if (spec.singleUnit === unit) { 7152 return spec; 7153 } 7154 } 7155 } 7156 }; 7157 // Current Date 7158 // ----------------------------------------------------------------------------------------------------------------- 7159 Calendar.prototype.getInitialDate = function () { 7160 var defaultDateInput = this.opt('defaultDate'); 7161 // compute the initial ambig-timezone date 7162 if (defaultDateInput != null) { 7163 return this.dateEnv.createMarker(defaultDateInput); 7164 } 7165 else { 7166 return this.getNow(); // getNow already returns unzoned 7167 } 7168 }; 7169 Calendar.prototype.prev = function () { 7170 this.unselect(); 7171 this.dispatch({ type: 'PREV' }); 7172 }; 7173 Calendar.prototype.next = function () { 7174 this.unselect(); 7175 this.dispatch({ type: 'NEXT' }); 7176 }; 7177 Calendar.prototype.prevYear = function () { 7178 this.unselect(); 7179 this.dispatch({ 7180 type: 'SET_DATE', 7181 dateMarker: this.dateEnv.addYears(this.state.currentDate, -1) 7182 }); 7183 }; 7184 Calendar.prototype.nextYear = function () { 7185 this.unselect(); 7186 this.dispatch({ 7187 type: 'SET_DATE', 7188 dateMarker: this.dateEnv.addYears(this.state.currentDate, 1) 7189 }); 7190 }; 7191 Calendar.prototype.today = function () { 7192 this.unselect(); 7193 this.dispatch({ 7194 type: 'SET_DATE', 7195 dateMarker: this.getNow() 7196 }); 7197 }; 7198 Calendar.prototype.gotoDate = function (zonedDateInput) { 7199 this.unselect(); 7200 this.dispatch({ 7201 type: 'SET_DATE', 7202 dateMarker: this.dateEnv.createMarker(zonedDateInput) 7203 }); 7204 }; 7205 Calendar.prototype.incrementDate = function (deltaInput) { 7206 var delta = createDuration(deltaInput); 7207 if (delta) { // else, warn about invalid input? 7208 this.unselect(); 7209 this.dispatch({ 7210 type: 'SET_DATE', 7211 dateMarker: this.dateEnv.add(this.state.currentDate, delta) 7212 }); 7213 } 7214 }; 7215 // for external API 7216 Calendar.prototype.getDate = function () { 7217 return this.dateEnv.toDate(this.state.currentDate); 7218 }; 7219 // Date Formatting Utils 7220 // ----------------------------------------------------------------------------------------------------------------- 7221 Calendar.prototype.formatDate = function (d, formatter) { 7222 var dateEnv = this.dateEnv; 7223 return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter)); 7224 }; 7225 // `settings` is for formatter AND isEndExclusive 7226 Calendar.prototype.formatRange = function (d0, d1, settings) { 7227 var dateEnv = this.dateEnv; 7228 return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings, this.opt('defaultRangeSeparator')), settings); 7229 }; 7230 Calendar.prototype.formatIso = function (d, omitTime) { 7231 var dateEnv = this.dateEnv; 7232 return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime }); 7233 }; 7234 // Sizing 7235 // ----------------------------------------------------------------------------------------------------------------- 7236 Calendar.prototype.windowResize = function (ev) { 7237 if (!this.isHandlingWindowResize && 7238 this.component && // why? 7239 ev.target === window // not a jqui resize event 7240 ) { 7241 this.isHandlingWindowResize = true; 7242 this.updateSize(); 7243 this.publiclyTrigger('windowResize', [this.view]); 7244 this.isHandlingWindowResize = false;
7245 } 7246 }; 7247 Calendar.prototype.updateSize = function () { 7248 if (this.component) { // when? 7249 this.component.updateSize(true); 7250 } 7251 }; 7252 // Component Registration 7253 // ----------------------------------------------------------------------------------------------------------------- 7254 Calendar.prototype.registerInteractiveComponent = function (component, settingsInput) { 7255 var settings = parseInteractionSettings(component, settingsInput); 7256 var DEFAULT_INTERACTIONS = [ 7257 EventClicking, 7258 EventHovering 7259 ]; 7260 var interactionClasses = DEFAULT_INTERACTIONS.concat(this.pluginSystem.hooks.componentInteractions); 7261 var interactions = interactionClasses.map(function (interactionClass) { 7262 return new interactionClass(settings); 7263 }); 7264 this.interactionsStore[component.uid] = interactions; 7265 interactionSettingsStore[component.uid] = settings; 7266 }; 7267 Calendar.prototype.unregisterInteractiveComponent = function (component) { 7268 for (var _i = 0, _a = this.interactionsStore[component.uid]; _i < _a.length; _i++) { 7269 var listener = _a[_i]; 7270 listener.destroy(); 7271 } 7272 delete this.interactionsStore[component.uid]; 7273 delete interactionSettingsStore[component.uid]; 7274 }; 7275 // Date Selection / Event Selection / DayClick 7276 // ----------------------------------------------------------------------------------------------------------------- 7277 // this public method receives start/end dates in any format, with any timezone 7278 // NOTE: args were changed from v3 7279 Calendar.prototype.select = function (dateOrObj, endDate) { 7280 var selectionInput; 7281 if (endDate == null) { 7282 if (dateOrObj.start != null) { 7283 selectionInput = dateOrObj; 7284 } 7285 else { 7286 selectionInput = { 7287 start: dateOrObj, 7288 end: null 7289 }; 7290 } 7291 } 7292 else { 7293 selectionInput = { 7294 start: dateOrObj, 7295 end: endDate 7296 }; 7297 } 7298 var selection = parseDateSpan(selectionInput, this.dateEnv, createDuration({ days: 1 }) // TODO: cache this? 7299 ); 7300 if (selection) { // throw parse error otherwise? 7301 this.dispatch({ type: 'SELECT_DATES', selection: selection }); 7302 this.triggerDateSelect(selection); 7303 } 7304 }; 7305 // public method 7306 Calendar.prototype.unselect = function (pev) { 7307 if (this.state.dateSelection) { 7308 this.dispatch({ type: 'UNSELECT_DATES' }); 7309 this.triggerDateUnselect(pev); 7310 } 7311 }; 7312 Calendar.prototype.triggerDateSelect = function (selection, pev) { 7313 var arg = this.buildDateSpanApi(selection); 7314 arg.jsEvent = pev ? pev.origEvent : null; 7315 arg.view = this.view; 7316 this.publiclyTrigger('select', [arg]); 7317 }; 7318 Calendar.prototype.triggerDateUnselect = function (pev) { 7319 this.publiclyTrigger('unselect', [ 7320 { 7321 jsEvent: pev ? pev.origEvent : null, 7322 view: this.view 7323 } 7324 ]); 7325 }; 7326 // TODO: receive pev? 7327 Calendar.prototype.triggerDateClick = function (dateSpan, dayEl, view, ev) { 7328 var arg = this.buildDatePointApi(dateSpan); 7329 arg.dayEl = dayEl; 7330 arg.jsEvent = ev; 7331 arg.view = view; 7332 this.publiclyTrigger('dateClick', [arg]); 7333 }; 7334 Calendar.prototype.buildDatePointApi = function (dateSpan) { 7335 var props = {}; 7336 for (var _i = 0, _a = this.pluginSystem.hooks.datePointTransforms; _i < _a.length; _i++) { 7337 var transform = _a[_i]; 7338 __assign(props, transform(dateSpan, this)); 7339 } 7340 __assign(props, buildDatePointApi(dateSpan, this.dateEnv)); 7341 return props; 7342 }; 7343 Calendar.prototype.buildDateSpanApi = function (dateSpan) { 7344 var props = {}; 7345 for (var _i = 0, _a = this.pluginSystem.hooks.dateSpanTransforms; _i < _a.length; _i++) { 7346 var transform = _a[_i]; 7347 __assign(props, transform(dateSpan, this)); 7348 } 7349 __assign(props, buildDateSpanApi(dateSpan, this.dateEnv)); 7350 return props; 7351 }; 7352 // Date Utils 7353 // ----------------------------------------------------------------------------------------------------------------- 7354 // Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option 7355 Calendar.prototype.getNow = function () { 7356 var now = this.opt('now'); 7357 if (typeof now === 'function') { 7358 now = now(); 7359 } 7360 if (now == null) { 7361 return this.dateEnv.createNowMarker(); 7362 } 7363 return this.dateEnv.createMarker(now); 7364 }; 7365 // Event-Date Utilities 7366 // ----------------------------------------------------------------------------------------------------------------- 7367 // Given an event's allDay status and start date, return what its fallback end date should be. 7368 // TODO: rename to computeDefaultEventEnd 7369 Calendar.prototype.getDefaultEventEnd = function (allDay, marker) { 7370 var end = marker; 7371 if (allDay) { 7372 end = startOfDay(end); 7373 end = this.dateEnv.add(end, this.defaultAllDayEventDuration); 7374 } 7375 else { 7376 end = this.dateEnv.add(end, this.defaultTimedEventDuration); 7377 } 7378 return end; 7379 }; 7380 // Public Events API 7381 // ----------------------------------------------------------------------------------------------------------------- 7382 Calendar.prototype.addEvent = function (eventInput, sourceIn
7382put) { 7383 if (eventInput instanceof EventApi) { 7384 var def = eventInput._def; 7385 var instance = eventInput._instance; 7386 // not already present? don't want to add an old snapshot 7387 if (!this.state.eventStore.defs[def.defId]) { 7388 this.dispatch({ 7389 type: 'ADD_EVENTS', 7390 eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args? 7391 }); 7392 } 7393 return eventInput; 7394 } 7395 var sourceId; 7396 if (sourceInput instanceof EventSourceApi) { 7397 sourceId = sourceInput.internalEventSource.sourceId; 7398 } 7399 else if (sourceInput != null) { 7400 var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function 7401 if (!sourceApi) { 7402 console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test 7403 return null; 7404 } 7405 else { 7406 sourceId = sourceApi.internalEventSource.sourceId; 7407 } 7408 } 7409 var tuple = parseEvent(eventInput, sourceId, this); 7410 if (tuple) { 7411 this.dispatch({ 7412 type: 'ADD_EVENTS', 7413 eventStore: eventTupleToStore(tuple) 7414 }); 7415 return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance); 7416 } 7417 return null; 7418 }; 7419 // TODO: optimize 7420 Calendar.prototype.getEventById = function (id) { 7421 var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; 7422 id = String(id); 7423 for (var defId in defs) { 7424 var def = defs[defId]; 7425 if (def.publicId === id) { 7426 if (def.recurringDef) { 7427 return new EventApi(this, def, null); 7428 } 7429 else { 7430 for (var instanceId in instances) { 7431 var instance = instances[instanceId]; 7432 if (instance.defId === def.defId) { 7433 return new EventApi(this, def, instance); 7434 } 7435 } 7436 } 7437 } 7438 } 7439 return null; 7440 }; 7441 Calendar.prototype.getEvents = function () { 7442 var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; 7443 var eventApis = []; 7444 for (var id in instances) { 7445 var instance = instances[id]; 7446 var def = defs[instance.defId]; 7447 eventApis.push(new EventApi(this, def, instance)); 7448 } 7449 return eventApis; 7450 }; 7451 Calendar.prototype.removeAllEvents = function () { 7452 this.dispatch({ type: 'REMOVE_ALL_EVENTS' }); 7453 }; 7454 Calendar.prototype.rerenderEvents = function () { 7455 this.dispatch({ type: 'RESET_EVENTS' }); 7456 }; 7457 // Public Event Sources API 7458 // ----------------------------------------------------------------------------------------------------------------- 7459 Calendar.prototype.getEventSources = function () { 7460 var sourceHash = this.state.eventSources; 7461 var sourceApis = []; 7462 for (var internalId in sourceHash) { 7463 sourceApis.push(new EventSourceApi(this, sourceHash[internalId])); 7464 } 7465 return sourceApis; 7466 }; 7467 Calendar.prototype.getEventSourceById = function (id) { 7468 var sourceHash = this.state.eventSources; 7469 id = String(id); 7470 for (var sourceId in sourceHash) { 7471 if (sourceHash[sourceId].publicId === id) { 7472 return new EventSourceApi(this, sourceHash[sourceId]); 7473 } 7474 } 7475 return null; 7476 }; 7477 Calendar.prototype.addEventSource = function (sourceInput) { 7478 if (sourceInput instanceof EventSourceApi) { 7479 // not already present? don't want to add an old snapshot
7480 if (!this.state.eventSources[sourceInput.internalEventSource.sourceId]) { 7481 this.dispatch({ 7482 type: 'ADD_EVENT_SOURCES', 7483 sources: [sourceInput.internalEventSource] 7484 }); 7485 } 7486 return sourceInput; 7487 } 7488 var eventSource = parseEventSource(sourceInput, this); 7489 if (eventSource) { // TODO: error otherwise? 7490 this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] }); 7491 return new EventSourceApi(this, eventSource); 7492 } 7493 return null; 7494 }; 7495 Calendar.prototype.removeAllEventSources = function () { 7496 this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' }); 7497 }; 7498 Calendar.prototype.refetchEvents = function () { 7499 this.dispatch({ type: 'FETCH_EVENT_SOURCES' }); 7500 }; 7501 // Scroll 7502 // ----------------------------------------------------------------------------------------------------------------- 7503 Calendar.prototype.scrollToTime = function (timeInput) { 7504 var time = createDuration(timeInput); 7505 if (time) { 7506 this.component.view.scrollToTime(time); 7507 } 7508 }; 7509 return Calendar; 7510 }()); 7511 EmitterMixin.mixInto(Calendar); 7512 // for memoizers 7513 // ----------------------------------------------------------------------------------------------------------------- 7514 function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) { 7515 return new DateEnv({ 7516 calendarSystem: 'gregory', 7517 timeZone: timeZone, 7518 namedTimeZoneImpl: namedTimeZoneImpl, 7519 locale: locale, 7520 weekNumberCalculation: weekNumberCalculation, 7521 firstDay: firstDay, 7522 weekLabel: weekLabel, 7523 cmdFormatter: cmdFormatter 7524 }); 7525 } 7526 function buildTheme(calendarOptions) { 7527 var themeClass = this.pluginSystem.hooks.themeClasses[calendarOptions.themeSystem] || StandardTheme; 7528 return new themeClass(calendarOptions); 7529 } 7530 function buildDelayedRerender(wait) { 7531 var func = this.tryRerender.bind(this); 7532 if (wait != null) { 7533 func = debounce(func, wait); 7534 } 7535 return func; 7536 } 7537 function buildEventUiBySource(eventSources) { 7538 return mapHash(eventSources, function (eventSource) { 7539 return eventSource.ui; 7540 }); 7541 } 7542 function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) { 7543 var eventUiBases = { '': eventUiSingleBase }; 7544 for (var defId in eventDefs) { 7545 var def = eventDefs[defId]; 7546 if (def.sourceId && eventUiBySource[def.sourceId]) { 7547 eventUiBases[defId] = eventUiBySource[def.sourceId]; 7548 } 7549 } 7550 return eventUiBases; 7551 } 7552 7553 var View = /** @class */ (function (_super) { 7554 __extends(View, _super); 7555 function View(context, viewSpec, dateProfileGenerator, parentEl) { 7556 var _this = _super.call(this, context, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' }), true // isView (HACK) 7557 ) || this; 7558 _this.renderDatesMem = memoizeRendering(_this.renderDatesWrap, _this.unrenderDatesWrap); 7559 _this.renderBusinessHoursMem = memoizeRendering(_this.renderBusinessHours, _this.unrenderBusinessHours, [_this.renderDatesMem]); 7560 _this.renderDateSelectionMem = memoizeRendering(_this.renderDateSelectionWrap, _this.unrenderDateSelectionWrap, [_this.renderDatesMem]); 7561 _this.renderEventsMem = memoizeRendering(_this.renderEvents, _this.unrenderEvents, [_this.renderDatesMem]); 7562 _this.renderEventSelectionMem = memoizeRendering(_this.renderEventSelectionWrap, _this.unrenderEventSelectionWrap, [_this.renderEventsMem]); 7563 _this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]); 7564 _this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]); 7565 _this.viewSpec = viewSpec; 7566 _this.dateProfileGenerator = dateProfileGenerator; 7567 _this.type = viewSpec.type; 7568 _this.eventOrderSpecs = parseFieldSpecs(_this.opt('eventOrder')); 7569 _this.nextDayThreshold = createDuration(_this.opt('nextDayThreshold')); 7570 parentEl.appendChild(_this.el); 7571 _this.initialize(); 7572 return _this; 7573 } 7574 View.prototype.initialize = function () { 7575 }; 7576 Object.defineProperty(View.prototype, "activeStart", { 7577 // Date Setting/Unsetting 7578 // ----------------------------------------------------------------------------------------------------------------- 7579 get: function () { 7580 return this.dateEnv.toDate(this.props.dateProfile.activeRange.start); 7581 }, 7582 enumerable: true, 7583 configurable: true 7584 }); 7585 Object.defineProperty(View.prototype, "activeEnd", { 7586 get: function () { 7587 return this.dateEnv.toDate(this.props.dateProfile.activeRange.end); 7588 }, 7589 enumerable: true, 7590 configurable: true 7591 }); 7592 Object.defineProperty(View.prototype, "currentStart", { 7593 get: function () { 7594 return this.dateEnv.toDate(this.props.dateProfile.currentRange.start); 7595 }, 7596 enumerable: true, 7597 configurable: true 7598 }); 7599 Object.defineProperty(View.prototype, "currentEnd", { 7600 get: function () { 7601 return this.dateEnv.toDate(this.props.dateProfile.currentRange.end); 7602 }, 7603 enumerable: true, 7604 configurable: true 7605 }); 7606 // General Rendering 7607 // ----------------------------------------------------------------------------------------------------------------- 7608 View.prototype.render = function (props) { 7609 this.renderDatesMem(props.dateProfile); 7610 this.renderBusinessHoursMem(props.businessHours); 7611 this.renderDateSelectionMem(props.dateSelection); 7612 this.renderEventsMem(props.eventStore); 7613 this.renderEventSelectionMem(props.eventSelection); 7614 this.renderEventDragMem(props.eventDrag); 7615 this.renderEventResizeMem(props.eventResize); 7616 }; 7617 View.prototype.destroy = function () { 7618 _super.prototype.destroy.call(this); 7619 this.renderDatesMem.unrender(); // should unrender everything else 7620 }; 7621 // Sizing 7622 // ----------------------------------------------------------------------------------------------------------------- 7623 View.prototype.updateSize = function (isResize, viewHeight, isAuto) { 7624 var calendar = this.calendar; 7625 if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) {
7626 // sort of the catch-all sizing 7627 // anything that might cause dimension changes 7628 this.updateBaseSize(isResize, viewHeight, isAuto); 7629 } 7630 }; 7631 View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { 7632 }; 7633 // Date Rendering 7634 // ----------------------------------------------------------------------------------------------------------------- 7635 View.prototype.renderDatesWrap = function (dateProfile) { 7636 this.renderDates(dateProfile); 7637 this.addScroll({ 7638 timeMs: createDuration(this.opt('scrollTime')).milliseconds 7639 }); 7640 this.startNowIndicator(dateProfile); // shouldn't render yet because updateSize will be called soon 7641 }; 7642 View.prototype.unrenderDatesWrap = function () { 7643 this.stopNowIndicator(); 7644 this.unrenderDates(); 7645 }; 7646 View.prototype.renderDates = function (dateProfile) { }; 7647 View.prototype.unrenderDates = function () { }; 7648 // Business Hours 7649 // ----------------------------------------------------------------------------------------------------------------- 7650 View.prototype.renderBusinessHours = function (businessHours) { }; 7651 View.prototype.unrenderBusinessHours = function () { }; 7652 // Date Selection 7653 // ----------------------------------------------------------------------------------------------------------------- 7654 View.prototype.renderDateSelectionWrap = function (selection) { 7655 if (selection) { 7656 this.renderDateSelection(selection); 7657 } 7658 }; 7659 View.prototype.unrenderDateSelectionWrap = function (selection) { 7660 if (selection) { 7661 this.unrenderDateSelection(selection); 7662 } 7663 }; 7664 View.prototype.renderDateSelection = function (selection) { }; 7665 View.prototype.unrenderDateSelection = function (selection) { }; 7666 // Event Rendering 7667 // ----------------------------------------------------------------------------------------------------------------- 7668 View.prototype.renderEvents = function (eventStore) { }; 7669 View.prototype.unrenderEvents = function () { }; 7670 // util for subclasses 7671 View.prototype.sliceEvents = function (eventStore, allDay) { 7672 var props = this.props; 7673 return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.nextDayThreshold : null).fg; 7674 }; 7675 // Event Selection 7676 // ----------------------------------------------------------------------------------------------------------------- 7677 View.prototype.renderEventSelectionWrap = function (instanceId) { 7678 if (instanceId) { 7679 this.renderEventSelection(instanceId); 7680 } 7681 }; 7682 View.prototype.unrenderEventSelectionWrap = function (instanceId) { 7683 if (instanceId) { 7684 this.unrenderEventSelection(instanceId); 7685 } 7686 }; 7687 View.prototype.renderEventSelection = function (instanceId) { }; 7688 View.prototype.unrenderEventSelection = function (instanceId) { }; 7689 // Event Drag 7690 // ----------------------------------------------------------------------------------------------------------------- 7691 View.prototype.renderEventDragWrap = function (state) { 7692 if (state) { 7693 this.renderEventDrag(state); 7694 } 7695 }; 7696 View.prototype.unrenderEventDragWrap = function (state) { 7697 if (state) { 7698 this.unrenderEventDrag(state); 7699 } 7700 }; 7701 View.prototype.renderEventDrag = function (state) { }; 7702 View.prototype.unrenderEventDrag = function (state) { }; 7703 // Event Resize 7704 // ----------------------------------------------------------------------------------------------------------------- 7705 View.prototype.renderEventResizeWrap = function (state) { 7706 if (state) { 7707 this.renderEventResize(state); 7708 } 7709 }; 7710 View.prototype.unrenderEventResizeWrap = function (state) { 7711 if (state) { 7712 this.unrenderEventResize(state); 7713 } 7714 }; 7715 View.prototype.renderEventResize = function (state) { }; 7716 View.prototype.unrenderEventResize = function (state) { }; 7717 /* Now Indicator 7718 ------------------------------------------------------------------------------------------------------------------*/ 7719 // Immediately render the current time indicator and begins re-rendering it at an interval, 7720 // which is defined by this.getNowIndicatorUnit(). 7721 // TODO: somehow do this for the current whole day's background too 7722 View.prototype.startNowIndicator = function (dateProfile) { 7723 var _this = this; 7724 var dateEnv = this.dateEnv; 7725 var unit; 7726 var update; 7727 var delay; // ms wait value 7728 if (this.opt('nowIndicator')) { 7729 unit = this.getNowIndicatorUnit(dateProfile); 7730 if (unit) { 7731 update = this.updateNowIndicator.bind(this); 7732 this.initialNowDate = this.calendar.getNow(); 7733 this.initialNowQueriedMs = new Date().valueOf(); 7734 // wait until the beginning of the next interval
7735 delay = dateEnv.add(dateEnv.startOf(this.initialNowDate, unit), createDuration(1, unit)).valueOf() - this.initialNowDate.valueOf(); 7736 // TODO: maybe always use setTimeout, waiting until start of next unit 7737 this.nowIndicatorTimeoutID = setTimeout(function () { 7738 _this.nowIndicatorTimeoutID = null; 7739 update(); 7740 if (unit === 'second') { 7741 delay = 1000; // every second 7742 } 7743 else { 7744 delay = 1000 * 60; // otherwise, every minute 7745 } 7746 _this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval 7747 }, delay); 7748 } 7749 // rendering will be initiated in updateSize 7750 } 7751 }; 7752 // rerenders the now indicator, computing the new current time from the amount of time that has passed 7753 // since the initial getNow call. 7754 View.prototype.updateNowIndicator = function () { 7755 if (this.props.dateProfile && // a way to determine if dates were rendered yet 7756 this.initialNowDate // activated before? 7757 ) { 7758 this.unrenderNowIndicator(); // won't unrender if unnecessary 7759 this.renderNowIndicator(addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs)); 7760 this.isNowIndicatorRendered = true; 7761 } 7762 }; 7763 // Immediately unrenders the view's current time indicator and stops any re-rendering timers. 7764 // Won't cause side effects if indicator isn't rendered. 7765 View.prototype.stopNowIndicator = function () { 7766 if (this.isNowIndicatorRendered) { 7767 if (this.nowIndicatorTimeoutID) { 7768 clearTimeout(this.nowIndicatorTimeoutID); 7769 this.nowIndicatorTimeoutID = null; 7770 } 7771 if (this.nowIndicatorIntervalID) { 7772 clearInterval(this.nowIndicatorIntervalID); 7773 this.nowIndicatorIntervalID = null; 7774 } 7775 this.unrenderNowIndicator(); 7776 this.isNowIndicatorRendered = false; 7777 } 7778 }; 7779 View.prototype.getNowIndicatorUnit = function (dateProfile) { 7780 // subclasses should implement 7781 }; 7782 // Renders a current time indicator at the given datetime 7783 View.prototype.renderNowIndicator = function (date) { 7784 // SUBCLASSES MUST PASS TO CHILDREN! 7785 }; 7786 // Undoes the rendering actions from renderNowIndicator 7787 View.prototype.unrenderNowIndicator = function () { 7788 // SUBCLASSES MUST PASS TO CHILDREN! 7789 }; 7790 /* Scroller 7791 ------------------------------------------------------------------------------------------------------------------*/ 7792 View.prototype.addScroll = function (scroll) { 7793 var queuedScroll = this.queuedScroll || (this.queuedScroll = {}); 7794 __assign(queuedScroll, scroll); 7795 }; 7796 View.prototype.popScroll = function (isResize) { 7797 this.applyQueuedScroll(isResize); 7798 this.queuedScroll = null; 7799 }; 7800 View.prototype.applyQueuedScroll = function (isResize) { 7801 this.applyScroll(this.queuedScroll || {}, isResize); 7802 }; 7803 View.prototype.queryScroll = function () { 7804 var scroll = {}; 7805 if (this.props.dateProfile) { // dates rendered yet? 7806 __assign(scroll, this.queryDateScroll()); 7807 } 7808 return scroll; 7809 }; 7810 View.prototype.applyScroll = function (scroll, isResize) { 7811 var timeMs = scroll.timeMs; 7812 if (timeMs != null) { 7813 delete scroll.timeMs; 7814 if (this.props.dateProfile) { // dates rendered yet? 7815 __assign(scroll, this.computeDateScroll(timeMs)); 7816 } 7817 } 7818 if (this.props.dateProfile) { // dates rendered yet? 7819 this.applyDateScroll(scroll); 7820 } 7821 }; 7822 View.prototype.computeDateScroll = function (timeMs) { 7823 return {}; // subclasses must implement 7824 }; 7825 View.prototype.queryDateScroll = function () { 7826 return {}; // subclasses must implement 7827 }; 7828 View.prototype.applyDateScroll = function (scroll) { 7829 // subclasses must implement 7830 }; 7831 // for API 7832 View.prototype.scrollToTime = function (time) { 7833 this.applyScroll({ 7834 timeMs: time.milliseconds 7835 }, false); 7836 }; 7837 return View; 7838 }(DateComponent)); 7839 EmitterMixin.mixInto(View); 7840 View.prototype.usesMinMaxTime = false;
7841 View.prototype.dateProfileGeneratorClass = DateProfileGenerator; 7842 7843 var FgEventRenderer = /** @class */ (function () { 7844 function FgEventRenderer(context) { 7845 this.segs = []; 7846 this.isSizeDirty = false; 7847 this.context = context; 7848 } 7849 FgEventRenderer.prototype.renderSegs = function (segs, mirrorInfo) { 7850 this.rangeUpdated(); // called too frequently :( 7851 // render an `.el` on each seg 7852 // returns a subset of the segs. segs that were actually rendered 7853 segs = this.renderSegEls(segs, mirrorInfo); 7854 this.segs = segs; 7855 this.attachSegs(segs, mirrorInfo); 7856 this.isSizeDirty = true; 7857 this.context.view.triggerRenderedSegs(this.segs, Boolean(mirrorInfo)); 7858 }; 7859 FgEventRenderer.prototype.unrender = function (_segs, mirrorInfo) { 7860 this.context.view.triggerWillRemoveSegs(this.segs, Boolean(mirrorInfo)); 7861 this.detachSegs(this.segs); 7862 this.segs = []; 7863 }; 7864 // Updates values that rely on options and also relate to range 7865 FgEventRenderer.prototype.rangeUpdated = function () { 7866 var options = this.context.options; 7867 var displayEventTime; 7868 var displayEventEnd; 7869 this.eventTimeFormat = createFormatter(options.eventTimeFormat || this.computeEventTimeFormat(), options.defaultRangeSeparator); 7870 displayEventTime = options.displayEventTime; 7871 if (displayEventTime == null) { 7872 displayEventTime = this.computeDisplayEventTime(); // might be based off of range 7873 } 7874 displayEventEnd = options.displayEventEnd; 7875 if (displayEventEnd == null) { 7876 displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range 7877 } 7878 this.displayEventTime = displayEventTime; 7879 this.displayEventEnd = displayEventEnd; 7880 }; 7881 // Renders and assigns an `el` property for each foreground event segment. 7882 // Only returns segments that successfully rendered. 7883 FgEventRenderer.prototype.renderSegEls = function (segs, mirrorInfo) { 7884 var html = ''; 7885 var i; 7886 if (segs.length) { // don't build an empty html string 7887 // build a large concatenation of event segment HTML 7888 for (i = 0; i < segs.length; i++) { 7889 html += this.renderSegHtml(segs[i], mirrorInfo); 7890 } 7891 // Grab individual elements from the combined HTML string. Use each as the default rendering. 7892 // Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false. 7893 htmlToElements(html).forEach(function (el, i) { 7894 var seg = segs[i]; 7895 if (el) { 7896 seg.el = el; 7897 } 7898 }); 7899 segs = filterSegsViaEls(this.context.view, segs, Boolean(mirrorInfo)); 7900 } 7901 return segs; 7902 }; 7903 // Generic utility for generating the HTML classNames for an event segment's element 7904 FgEventRenderer.prototype.getSegClasses = function (seg, isDraggable, isResizable, mirrorInfo) { 7905 var classes = [ 7906 'fc-event', 7907 seg.isStart ? 'fc-start' : 'fc-not-start', 7908 seg.isEnd ? 'fc-end' : 'fc-not-end' 7909 ].concat(seg.eventRange.ui.classNames); 7910 if (isDraggable) { 7911 classes.push('fc-draggable'); 7912 } 7913 if (isResizable) { 7914 classes.push('fc-resizable'); 7915 } 7916 if (mirrorInfo) { 7917 classes.push('fc-mirror'); 7918 if (mirrorInfo.isDragging) { 7919 classes.push('fc-dragging'); 7920 } 7921 if (mirrorInfo.isResizing) { 7922 classes.push('fc-resizing'); 7923 } 7924 } 7925 return classes; 7926 }; 7927 // Compute the text that should be displayed on an event's element. 7928 // `range` can be the Event object itself, or something range-like, with at least a `start`. 7929 // If event times are disabled, or the event has no time, will return a blank string. 7930 // If not specified, formatter will default to the eventTimeFormat setting, 7931 // and displayEnd will default to the displayEventEnd setting. 7932 FgEventRenderer.prototype.getTimeText = function (eventRange, formatter, displayEnd) { 7933 var def = eventRange.def, instance = eventRange.instance; 7934 return this._getTimeText(instance.range.start, def.hasEnd ? instance.range.end : null, def.allDay, formatter, displayEnd, instance.forcedStartTzo, instance.forcedEndTzo); 7935 }; 7936 FgEventRenderer.prototype._getTimeText = function (start, end, allDay, formatter, displayEnd, forcedStartTzo, forcedEndTzo) { 7937 var dateEnv = this.context.dateEnv; 7938 if (formatter == null) { 7939 formatter = this.eventTimeFormat; 7940 } 7941 if (displayEnd == null) { 7942 displayEnd = this.displayEventEnd; 7943 } 7944 if (this.displayEventTime && !allDay) { 7945 if (displayEnd && end) { 7946 return dateEnv.formatRange(start, end, formatter, { 7947 forcedStartTzo: forcedStartTzo, 7948 forcedEndTzo: forcedEndTzo 7949 }); 7950 } 7951 else { 7952 return dateEnv.format(start, formatter, { 7953 forcedTzo: forcedStartTzo 7954 }); 7955 } 7956 } 7957 return ''; 7958 }; 7959 FgEventRenderer.prototype.computeEventTimeFormat = function () { 7960 return { 7961 hour: 'numeric', 7962 minute: '2-digit', 7963 omitZeroMinute: true 7964 }; 7965 }; 7966 FgEventRenderer.prototype.computeDisplayEventTime = function () { 7967 return true; 7968 }; 7969 FgEventRenderer.prototype.computeDisplayEventEnd = function () { 7970 return true; 7971 }; 7972 // Utility for generating event skin-related CSS properties 7973 FgEventRenderer.prototype.getSkinCss = function (ui) { 7974 return { 7975 'background-color': ui.backgroundColor, 7976 'border-color': ui.borderColor, 7977 color: ui.textColor 7978 }; 7979 }; 7980 FgEventRenderer.prototype.sortEventSegs = function (segs) { 7981 var specs = this.context.view.eventOrderSpecs; 7982 var objs = segs.map(buildSegCompareObj); 7983 objs.sort(function (obj0, obj1) { 7984 return compareByFieldSpecs(obj0, obj1, specs); 7985 }); 7986 return objs.map(function (c) { 7987 return c._seg; 7988 }); 7989 }; 7990 FgEventRenderer.prototype.computeSizes = function (force) { 7991 if (force || this.isSizeDirty) { 7992 this.computeSegSizes(this.segs); 7993 } 7994 }; 7995 FgEventRenderer.prototype.assignSizes = function (force) { 7996 if (force || this.isSizeDirty) { 7997 this.assignSegSizes(this.segs); 7998 this.isSizeDirty = false;
7999 } 8000 }; 8001 FgEventRenderer.prototype.computeSegSizes = function (segs) { 8002 }; 8003 FgEventRenderer.prototype.assignSegSizes = function (segs) { 8004 }; 8005 // Manipulation on rendered segs 8006 FgEventRenderer.prototype.hideByHash = function (hash) { 8007 if (hash) { 8008 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 8009 var seg = _a[_i]; 8010 if (hash[seg.eventRange.instance.instanceId]) { 8011 seg.el.style.visibility = 'hidden'; 8012 } 8013 } 8014 } 8015 }; 8016 FgEventRenderer.prototype.showByHash = function (hash) { 8017 if (hash) { 8018 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 8019 var seg = _a[_i]; 8020 if (hash[seg.eventRange.instance.instanceId]) { 8021 seg.el.style.visibility = ''; 8022 } 8023 } 8024 } 8025 }; 8026 FgEventRenderer.prototype.selectByInstanceId = function (instanceId) { 8027 if (instanceId) { 8028 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 8029 var seg = _a[_i]; 8030 var eventInstance = seg.eventRange.instance; 8031 if (eventInstance && eventInstance.instanceId === instanceId && 8032 seg.el // necessary? 8033 ) { 8034 seg.el.classList.add('fc-selected'); 8035 } 8036 } 8037 } 8038 }; 8039 FgEventRenderer.prototype.unselectByInstanceId = function (instanceId) { 8040 if (instanceId) { 8041 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 8042 var seg = _a[_i]; 8043 if (seg.el) { // necessary? 8044 seg.el.classList.remove('fc-selected'); 8045 } 8046 } 8047 } 8048 }; 8049 return FgEventRenderer; 8050 }()); 8051 // returns a object with all primitive props that can be compared 8052 function buildSegCompareObj(seg) { 8053 var eventDef = seg.eventRange.def; 8054 var range = seg.eventRange.instance.range; 8055 var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events 8056 var end = range.end ? range.end.valueOf() : 0; // " 8057 return __assign({}, eventDef.extendedProps, eventDef, { id: eventDef.publicId, start: start, 8058 end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg // for later retrieval 8059 }); 8060 } 8061 8062 var FillRenderer = /** @class */ (function () { 8063 function FillRenderer(context) { 8064 this.fillSegTag = 'div'; 8065 this.dirtySizeFlags = {}; 8066 this.context = context; 8067 this.containerElsByType = {}; 8068 this.segsByType = {}; 8069 } 8070 FillRenderer.prototype.getSegsByType = function (type) { 8071 return this.segsByType[type] || []; 8072 }; 8073 FillRenderer.prototype.renderSegs = function (type, segs) { 8074 var _a; 8075 var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs 8076 var containerEls = this.attachSegs(type, renderedSegs); 8077 if (containerEls) { 8078 (_a = (this.containerElsByType[type] || (this.containerElsByType[type] = []))).push.apply(_a, containerEls); 8079 } 8080 this.segsByType[type] = renderedSegs; 8081 if (type === 'bgEvent') { 8082 this.context.view.triggerRenderedSegs(renderedSegs, false); // isMirror=false 8083 } 8084 this.dirtySizeFlags[type] = true; 8085 }; 8086 // Unrenders a specific type of fill that is currently rendered on the grid 8087 FillRenderer.prototype.unrender = function (type) { 8088 var segs = this.segsByType[type]; 8089 if (segs) { 8090 if (type === 'bgEvent') { 8091 this.context.view.triggerWillRemoveSegs(segs, false); // isMirror=false 8092 } 8093 this.detachSegs(type, segs); 8094 } 8095 }; 8096 // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types. 8097 // Only returns segments that successfully rendered.
8098 FillRenderer.prototype.renderSegEls = function (type, segs) { 8099 var _this = this; 8100 var html = ''; 8101 var i; 8102 if (segs.length) { 8103 // build a large concatenation of segment HTML 8104 for (i = 0; i < segs.length; i++) { 8105 html += this.renderSegHtml(type, segs[i]); 8106 } 8107 // Grab individual elements from the combined HTML string. Use each as the default rendering. 8108 // Then, compute the 'el' for each segment. 8109 htmlToElements(html).forEach(function (el, i) { 8110 var seg = segs[i]; 8111 if (el) { 8112 seg.el = el; 8113 } 8114 }); 8115 if (type === 'bgEvent') { 8116 segs = filterSegsViaEls(this.context.view, segs, false // isMirror. background events can never be mirror elements 8117 ); 8118 } 8119 // correct element type? (would be bad if a non-TD were inserted into a table for example) 8120 segs = segs.filter(function (seg) { 8121 return elementMatches(seg.el, _this.fillSegTag); 8122 }); 8123 } 8124 return segs; 8125 }; 8126 // Builds the HTML needed for one fill segment. Generic enough to work with different types. 8127 FillRenderer.prototype.renderSegHtml = function (type, seg) { 8128 var css = null; 8129 var classNames = []; 8130 if (type !== 'highlight' && type !== 'businessHours') { 8131 css = { 8132 'background-color': seg.eventRange.ui.backgroundColor 8133 }; 8134 } 8135 if (type !== 'highlight') { 8136 classNames = classNames.concat(seg.eventRange.ui.classNames); 8137 } 8138 if (type === 'businessHours') { 8139 classNames.push('fc-bgevent'); 8140 } 8141 else { 8142 classNames.push('fc-' + type.toLowerCase()); 8143 } 8144 return '<' + this.fillSegTag + 8145 (classNames.length ? ' class="' + classNames.join(' ') + '"' : '') + 8146 (css ? ' style="' + cssToStr(css) + '"' : '') + 8147 '></' + this.fillSegTag + '>'; 8148 }; 8149 FillRenderer.prototype.detachSegs = function (type, segs) { 8150 var containerEls = this.containerElsByType[type]; 8151 if (containerEls) { 8152 containerEls.forEach(removeElement); 8153 delete this.containerElsByType[type]; 8154 } 8155 }; 8156 FillRenderer.prototype.computeSizes = function (force) { 8157 for (var type in this.segsByType) { 8158 if (force || this.dirtySizeFlags[type]) { 8159 this.computeSegSizes(this.segsByType[type]); 8160 } 8161 } 8162 }; 8163 FillRenderer.prototype.assignSizes = function (force) { 8164 for (var type in this.segsByType) { 8165 if (force || this.dirtySizeFlags[type]) { 8166 this.assignSegSizes(this.segsByType[type]); 8167 } 8168 } 8169 this.dirtySizeFlags = {}; 8170 }; 8171 FillRenderer.prototype.computeSegSizes = function (segs) { 8172 }; 8173 FillRenderer.prototype.assignSegSizes = function (segs) { 8174 }; 8175 return FillRenderer; 8176 }()); 8177 8178 var NamedTimeZoneImpl = /** @class */ (function () { 8179 function NamedTimeZoneImpl(timeZoneName) { 8180 this.timeZoneName = timeZoneName; 8181 } 8182 return NamedTimeZoneImpl; 8183 }()); 8184 8185 /* 8186 An abstraction for a dragging interaction originating on an event. 8187 Does higher-level things than PointerDragger, such as possibly: 8188 - a "mirror" that moves with the pointer 8189 - a minimum number of pixels or other criteria for a true drag to begin 8190 8191 subclasses must emit: 8192 - pointerdown 8193 - dragstart 8194 - dragmove 8195 - pointerup 8196 - dragend 8197 */ 8198 var ElementDragging = /** @class */ (function () { 8199 function ElementDragging(el) { 8200 this.emitter = new EmitterMixin(); 8201 } 8202 ElementDragging.prototype.destroy = function () { 8203 }; 8204 ElementDragging.prototype.setMirrorIsVisible = function (bool) {
8205 // optional if subclass doesn't want to support a mirror 8206 }; 8207 ElementDragging.prototype.setMirrorNeedsRevert = function (bool) { 8208 // optional if subclass doesn't want to support a mirror 8209 }; 8210 ElementDragging.prototype.setAutoScrollEnabled = function (bool) { 8211 // optional 8212 }; 8213 return ElementDragging; 8214 }()); 8215 8216 function formatDate(dateInput, settings) { 8217 if (settings === void 0) { settings = {}; } 8218 var dateEnv = buildDateEnv$1(settings); 8219 var formatter = createFormatter(settings); 8220 var dateMeta = dateEnv.createMarkerMeta(dateInput); 8221 if (!dateMeta) { // TODO: warning? 8222 return ''; 8223 } 8224 return dateEnv.format(dateMeta.marker, formatter, { 8225 forcedTzo: dateMeta.forcedTzo 8226 }); 8227 } 8228 function formatRange(startInput, endInput, settings // mixture of env and formatter settings 8229 ) { 8230 var dateEnv = buildDateEnv$1(typeof settings === 'object' && settings ? settings : {}); // pass in if non-null object 8231 var formatter = createFormatter(settings, globalDefaults.defaultRangeSeparator); 8232 var startMeta = dateEnv.createMarkerMeta(startInput); 8233 var endMeta = dateEnv.createMarkerMeta(endInput); 8234 if (!startMeta || !endMeta) { // TODO: warning? 8235 return ''; 8236 } 8237 return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, { 8238 forcedStartTzo: startMeta.forcedTzo, 8239 forcedEndTzo: endMeta.forcedTzo, 8240 isEndExclusive: settings.isEndExclusive 8241 }); 8242 } 8243 // TODO: more DRY and optimized 8244 function buildDateEnv$1(settings) { 8245 var locale = buildLocale(settings.locale || 'en', parseRawLocales([]).map); // TODO: don't hardcode 'en' everywhere 8246 // ensure required settings 8247 settings = __assign({ timeZone: globalDefaults.timeZone, calendarSystem: 'gregory' }, settings, { locale: locale }); 8248 return new DateEnv(settings); 8249 } 8250 8251 var DRAG_META_PROPS = { 8252 startTime: createDuration, 8253 duration: createDuration, 8254 create: Boolean, 8255 sourceId: String 8256 }; 8257 var DRAG_META_DEFAULTS = { 8258 create: true 8259 }; 8260 function parseDragMeta(raw) { 8261 var leftoverProps = {}; 8262 var refined = refineProps(raw, DRAG_META_PROPS, DRAG_META_DEFAULTS, leftoverProps); 8263 refined.leftoverProps = leftoverProps; 8264 return refined; 8265 } 8266 8267 // Computes a default column header formatting string if `colFormat` is not explicitly defined 8268 function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) { 8269 // if more than one week row, or if there are a lot of columns with not much space, 8270 // put just the day numbers will be in each cell 8271 if (!datesRepDistinctDays || dayCnt > 10) { 8272 return { weekday: 'short' }; // "Sat" 8273 } 8274 else if (dayCnt > 1) { 8275 return { weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }; // "Sat 11/12" 8276 } 8277 else { 8278 return { weekday: 'long' }; // "Saturday" 8279 } 8280 } 8281 function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) { 8282 var view = context.view, dateEnv = context.dateEnv, theme = context.theme, options = context.options; 8283 var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow. 8284 var classNames = [ 8285 'fc-day-header', 8286 theme.getClass('widgetHeader') 8287 ]; 8288 var innerHtml; 8289 if (typeof options.columnHeaderHtml === 'function') { 8290 innerHtml = options.columnHeaderHtml(dateEnv.toDate(dateMarker)); 8291 } 8292 else if (typeof options.columnHeaderText === 'function') { 8293 innerHtml = htmlEscape(options.columnHeaderText(dateEnv.toDate(dateMarker))); 8294 } 8295 else { 8296 innerHtml = htmlEscape(dateEnv.format(dateMarker, colHeadFormat)); 8297 } 8298 // if only one row of days, the classNames on the header can represent the specific days beneath 8299 if (datesRepDistinctDays) {
8300 classNames = classNames.concat( 8301 // includes the day-of-week class 8302 // noThemeHighlight=true (don't highlight the header) 8303 getDayClasses(dateMarker, dateProfile, context, true)); 8304 } 8305 else { 8306 classNames.push('fc-' + DAY_IDS[dateMarker.getUTCDay()]); // only add the day-of-week class 8307 } 8308 return '' + 8309 '<th class="' + classNames.join(' ') + '"' + 8310 ((isDateValid && datesRepDistinctDays) ? 8311 ' data-date="' + dateEnv.formatIso(dateMarker, { omitTime: true }) + '"' : 8312 '') + 8313 (colspan > 1 ? 8314 ' colspan="' + colspan + '"' : 8315 '') + 8316 (otherAttrs ? 8317 ' ' + otherAttrs : 8318 '') + 8319 '>' + 8320 (isDateValid ? 8321 // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff) 8322 buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) : 8323 // if not valid, display text, but no link 8324 innerHtml) + 8325 '</th>'; 8326 } 8327 8328 var DayHeader = /** @class */ (function (_super) { 8329 __extends(DayHeader, _super); 8330 function DayHeader(context, parentEl) { 8331 var _this = _super.call(this, context) || this; 8332 parentEl.innerHTML = ''; // because might be nbsp 8333 parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' + 8334 '<table class="' + _this.theme.getClass('tableGrid') + '">' + 8335 '<thead></thead>' + 8336 '</table>' + 8337 '</div>')); 8338 _this.thead = _this.el.querySelector('thead'); 8339 return _this; 8340 } 8341 DayHeader.prototype.destroy = function () { 8342 removeElement(this.el); 8343 }; 8344 DayHeader.prototype.render = function (props) { 8345 var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays; 8346 var parts = []; 8347 if (props.renderIntroHtml) { 8348 parts.push(props.renderIntroHtml()); 8349 } 8350 var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') || 8351 computeFallbackHeaderFormat(datesRepDistinctDays, dates.length)); 8352 for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) { 8353 var date = dates_1[_i]; 8354 parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context)); 8355 } 8356 if (this.isRtl) { 8357 parts.reverse(); 8358 } 8359 this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>'; 8360 }; 8361 return DayHeader; 8362 }(Component)); 8363 8364 var DaySeries = /** @class */ (function () { 8365 function DaySeries(range, dateProfileGenerator) { 8366 var date = range.start; 8367 var end = range.end; 8368 var indices = []; 8369 var dates = []; 8370 var dayIndex = -1; 8371 while (date < end) { // loop each day from start to end 8372 if (dateProfileGenerator.isHiddenDay(date)) { 8373 indices.push(dayIndex + 0.5); // mark that it's between indices 8374 } 8375 else { 8376 dayIndex++; 8377 indices.push(dayIndex); 8378 dates.push(date); 8379 } 8380 date = addDays(date, 1); 8381 } 8382 this.dates = dates; 8383 this.indices = indices; 8384 this.cnt = dates.length; 8385 } 8386 DaySeries.prototype.sliceRange = function (range) { 8387 var firstIndex = this.getDateDayIndex(range.start); // inclusive first index 8388 var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index 8389 var clippedFirstIndex = Math.max(0, firstIndex); 8390 var clippedLastIndex = Math.min(this.cnt - 1, lastIndex); 8391 // deal with in-between indices 8392 clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell 8393 clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell 8394 if (clippedFirstIndex <= clippedLastIndex) { 8395 return { 8396 firstIndex: clippedFirstIndex, 8397 lastIndex: clippedLastIndex, 8398 isStart: firstIndex === clippedFirstIndex, 8399 isEnd: lastIndex === clippedLastIndex 8400 }; 8401 } 8402 else { 8403 return null; 8404 } 8405 }; 8406 // Given a date, returns its chronolocial cell-index from the first cell of the grid. 8407 // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets. 8408 // If before the first offset, returns a negative number. 8409 // If after the last offset, returns an offset past the last cell offset. 8410 // Only works for *start* dates of cells. Will not work for exclusive end dates for cells. 8411 DaySeries.prototype.getDateDayIndex = function (date) { 8412 var indices = this.indices; 8413 var dayOffset = Math.floor(diffDays(this.dates[0], date)); 8414 if (dayOffset < 0) {
8415 return indices[0] - 1; 8416 } 8417 else if (dayOffset >= indices.length) { 8418 return indices[indices.length - 1] + 1; 8419 } 8420 else { 8421 return indices[dayOffset]; 8422 } 8423 }; 8424 return DaySeries; 8425 }()); 8426 8427 var DayTable = /** @class */ (function () { 8428 function DayTable(daySeries, breakOnWeeks) { 8429 var dates = daySeries.dates; 8430 var daysPerRow; 8431 var firstDay; 8432 var rowCnt; 8433 if (breakOnWeeks) { 8434 // count columns until the day-of-week repeats 8435 firstDay = dates[0].getUTCDay(); 8436 for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) { 8437 if (dates[daysPerRow].getUTCDay() === firstDay) { 8438 break; 8439 } 8440 } 8441 rowCnt = Math.ceil(dates.length / daysPerRow); 8442 } 8443 else { 8444 rowCnt = 1; 8445 daysPerRow = dates.length; 8446 } 8447 this.rowCnt = rowCnt; 8448 this.colCnt = daysPerRow; 8449 this.daySeries = daySeries; 8450 this.cells = this.buildCells(); 8451 this.headerDates = this.buildHeaderDates(); 8452 } 8453 DayTable.prototype.buildCells = function () { 8454 var rows = []; 8455 for (var row = 0; row < this.rowCnt; row++) { 8456 var cells = []; 8457 for (var col = 0; col < this.colCnt; col++) { 8458 cells.push(this.buildCell(row, col)); 8459 } 8460 rows.push(cells); 8461 } 8462 return rows; 8463 }; 8464 DayTable.prototype.buildCell = function (row, col) { 8465 return { 8466 date: this.daySeries.dates[row * this.colCnt + col] 8467 }; 8468 }; 8469 DayTable.prototype.buildHeaderDates = function () { 8470 var dates = []; 8471 for (var col = 0; col < this.colCnt; col++) { 8472 dates.push(this.cells[0][col].date); 8473 } 8474 return dates; 8475 }; 8476 DayTable.prototype.sliceRange = function (range) { 8477 var colCnt = this.colCnt; 8478 var seriesSeg = this.daySeries.sliceRange(range); 8479 var segs = []; 8480 if (seriesSeg) { 8481 var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex; 8482 var index = firstIndex; 8483 while (index <= lastIndex) { 8484 var row = Math.floor(index / colCnt); 8485 var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1); 8486 segs.push({ 8487 row: row, 8488 firstCol: index % colCnt, 8489 lastCol: (nextIndex - 1) % colCnt, 8490 isStart: seriesSeg.isStart && index === firstIndex, 8491 isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex 8492 }); 8493 index = nextIndex; 8494 } 8495 } 8496 return segs; 8497 }; 8498 return DayTable; 8499 }()); 8500 8501 var Slicer = /** @class */ (function () { 8502 function Slicer() { 8503 this.sliceBusinessHours = memoize(this._sliceBusinessHours); 8504 this.sliceDateSelection = memoize(this._sliceDateSpan); 8505 this.sliceEventStore = memoize(this._sliceEventStore); 8506 this.sliceEventDrag = memoize(this._sliceInteraction); 8507 this.sliceEventResize = memoize(this._sliceInteraction); 8508 } 8509 Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, component) { 8510 var extraArgs = []; 8511 for (var _i = 4; _i < arguments.length; _i++) { 8512 extraArgs[_i - 4] = arguments[_i]; 8513 } 8514 var eventUiBases = props.eventUiBases; 8515 var eventSegs = this.sliceEventStore.apply(this, [props.eventStore, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)); 8516 return { 8517 dateSelectionSegs: this.sliceDateSelection.apply(this, [props.dateSelection, eventUiBases, component].concat(extraArgs)), 8518 businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, component].concat(extraArgs)), 8519 fgEventSegs: eventSegs.fg, 8520 bgEventSegs: eventSegs.bg, 8521 eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), 8522 eventResize: this.sliceEventResize.apply(this, [props.eventResize, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), 8523 eventSelection: props.eventSelection 8524 }; // TODO: give interactionSegs? 8525 }; 8526 Slicer.prototype.sliceNowDate = function (// does not memoize 8527 date, component) { 8528 var extraArgs = []; 8529 for (var _i = 2; _i < arguments.length; _i++) { 8530 extraArgs[_i - 2] = arguments[_i]; 8531 } 8532 return this._sliceDateSpan.apply(this, [{ range: { start: date, end: addMs(date, 1) }, allDay: false }, 8533 {}, 8534 component].concat(extraArgs)); 8535 }; 8536 Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, component) { 8537 var extraArgs = []; 8538 for (var _i = 4; _i < arguments.length; _i++) { 8539 extraArgs[_i - 4] = arguments[_i]; 8540 } 8541 if (!businessHours) { 8542 return []; 8543 } 8544 return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), component.calendar), 8545 {}, 8546 dateProfile, 8547 nextDayThreshold, 8548 component].concat(extraArgs)).bg; 8549 }; 8550 Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold, component) { 8551 var extraArgs = []; 8552 for (var _i = 5; _i < arguments.length; _i++) { 8553 extraArgs[_i - 5] = arguments[_i]; 8554 } 8555 if (eventStore) { 8556 var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8557 return { 8558 bg: this.sliceEventRanges(rangeRes.bg, component, extraArgs), 8559 fg: this.sliceEventRanges(rangeRes.fg, component, extraArgs) 8560 }; 8561 } 8562 else { 8563 return { bg: [], fg: [] }; 8564 } 8565 }; 8566 Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold, component) { 8567 var extraArgs = []; 8568 for (var _i = 5; _i < arguments.length; _i++) { 8569 extraArgs[_i - 5] = arguments[_i]; 8570 } 8571 if (!interaction) { 8572 return null; 8573 } 8574 var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8575 return { 8576 segs: this.sliceEventRanges(rangeRes.fg, component, extraArgs), 8577 affectedInstances: interaction.affectedEvents.instances, 8578 isEvent: interaction.isEvent, 8579 sourceSeg: interaction.origSeg 8580 }; 8581 }; 8582 Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, component) { 8583 var extraArgs = []; 8584 for (var _i = 3; _i < arguments.length; _i++) { 8585 extraArgs[_i - 3] = arguments[_i]; 8586 } 8587 if (!dateSpan) { 8588 return []; 8589 } 8590 var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.calendar); 8591 var segs = this.sliceRange.apply(this, [dateSpan.range].concat(extraArgs)); 8592 for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) { 8593 var seg = segs_1[_a]; 8594 seg.component = component; 8595 seg.eventRange = eventRange; 8596 } 8597 return segs; 8598 }; 8599 /* 8600 "complete" seg means it has component and eventRange 8601 */ 8602 Slicer.prototype.sliceEventRanges = function (eventRanges, component, // TODO: kill 8603 extraArgs) { 8604 var segs = []; 8605 for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { 8606 var eventRange = eventRanges_1[_i]; 8607 segs.push.apply(segs, this.sliceEventRange(eventRange, component, extraArgs)); 8608 } 8609 return segs; 8610 }; 8611 /* 8612 "complete" seg means it has component and eventRange 8613 */ 8614 Slicer.prototype.sliceEventRange = function (eventRange, component, // TODO: kill 8615 extraArgs) { 8616 var segs = this.sliceRange.apply(this, [eventRange.range].concat(extraArgs)); 8617 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 8618 var seg = segs_2[_i]; 8619 seg.component = component; 8620 seg.eventRange = eventRange; 8621 seg.isStart = eventRange.isStart && seg.isStart; 8622 seg.isEnd = eventRange.isEnd && seg.isEnd; 8623 } 8624 return segs; 8625 }; 8626 return Slicer; 8627 }()); 8628 /* 8629 for incorporating minTime/maxTime if appropriate 8630 TODO: should be part of DateProfile! 8631 TimelineDateProfile already does this btw 8632 */ 8633 function computeActiveRange(dateProfile, isComponentAllDay) { 8634 var range = dateProfile.activeRange; 8635 if (isComponentAllDay) { 8636 return range; 8637 } 8638 return { 8639 start: addMs(range.start, dateProfile.minTime.milliseconds), 8640 end: addMs(range.end, dateProfile.maxTime.milliseconds - 864e5) // 864e5 = ms in a day 8641 }; 8642 } 8643 8644 // exports 8645 // -------------------------------------------------------------------------------------------------- 8646 var version = '4.1.0'; 8647 8648 exports.Calendar = Calendar; 8649 exports.Component = Component; 8650 exports.DateComponent = DateComponent; 8651 exports.DateEnv = DateEnv; 8652 exports.DateProfileGenerator = DateProfileGenerator; 8653 exports.DayHeader = DayHeader; 8654 exports.DaySeries = DaySeries; 8655 exports.DayTable = DayTable; 8656 exports.ElementDragging = ElementDragging; 8657 exports.ElementScrollController = ElementScrollController; 8658 exports.EmitterMixin = EmitterMixin; 8659 exports.EventApi = EventApi; 8660 exports.FgEventRenderer = FgEventRenderer;
8661 exports.FillRenderer = FillRenderer; 8662 exports.Interaction = Interaction; 8663 exports.Mixin = Mixin; 8664 exports.NamedTimeZoneImpl = NamedTimeZoneImpl; 8665 exports.PositionCache = PositionCache; 8666 exports.ScrollComponent = ScrollComponent; 8667 exports.ScrollController = ScrollController; 8668 exports.Slicer = Slicer; 8669 exports.Splitter = Splitter; 8670 exports.Theme = Theme; 8671 exports.View = View; 8672 exports.WindowScrollController = WindowScrollController; 8673 exports.addDays = addDays; 8674 exports.addDurations = addDurations; 8675 exports.addMs = addMs; 8676 exports.addWeeks = addWeeks; 8677 exports.allowContextMenu = allowContextMenu; 8678 exports.allowSelection = allowSelection; 8679 exports.appendToElement = appendToElement; 8680 exports.applyAll = applyAll; 8681 exports.applyMutationToEventStore = applyMutationToEventStore; 8682 exports.applyStyle = applyStyle; 8683 exports.applyStyleProp = applyStyleProp; 8684 exports.asRoughMinutes = asRoughMinutes; 8685 exports.asRoughMs = asRoughMs; 8686 exports.asRoughSeconds = asRoughSeconds; 8687 exports.buildGotoAnchorHtml = buildGotoAnchorHtml; 8688 exports.buildSegCompareObj = buildSegCompareObj; 8689 exports.capitaliseFirstLetter = capitaliseFirstLetter; 8690 exports.combineEventUis = combineEventUis; 8691 exports.compareByFieldSpec = compareByFieldSpec; 8692 exports.compareByFieldSpecs = compareByFieldSpecs; 8693 exports.compareNumbers = compareNumbers; 8694 exports.compensateScroll = compensateScroll; 8695 exports.computeClippingRect = computeClippingRect; 8696 exports.computeEdges = computeEdges; 8697 exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat; 8698 exports.computeHeightAndMargins = computeHeightAndMargins; 8699 exports.computeInnerRect = computeInnerRect; 8700 exports.computeRect = computeRect; 8701 exports.computeVisibleDayRange = computeVisibleDayRange; 8702 exports.config = config; 8703 exports.constrainPoint = constrainPoint; 8704 exports.createDuration = createDuration; 8705 exports.createElement = createElement; 8706 exports.createEmptyEventStore = createEmptyEventStore; 8707 exports.createEventInstance = createEventInstance; 8708 exports.createFormatter = createFormatter; 8709 exports.createPlugin = createPlugin; 8710 exports.cssToStr = cssToStr; 8711 exports.debounce = debounce; 8712 exports.diffDates = diffDates; 8713 exports.diffDayAndTime = diffDayAndTime; 8714 exports.diffDays = diffDays; 8715 exports.diffPoints = diffPoints; 8716 exports.diffWeeks = diffWeeks; 8717 exports.diffWholeDays = diffWholeDays; 8718 exports.diffWholeWeeks = diffWholeWeeks; 8719 exports.disableCursor = disableCursor; 8720 exports.distributeHeight = distributeHeight; 8721 exports.elementClosest = elementClosest; 8722 exports.elementMatches = elementMatches; 8723 exports.enableCursor = enableCursor; 8724 exports.eventTupleToStore = eventTupleToStore; 8725 exports.filterEventStoreDefs = filterEventStoreDefs; 8726 exports.filterHash = filterHash; 8727 exports.findChildren = findChildren; 8728 exports.findElements = findElements; 8729 exports.flexibleCompare = flexibleCompare; 8730 exports.forceClassName = forceClassName; 8731 exports.formatDate = formatDate; 8732 exports.formatIsoTimeString = formatIsoTimeString; 8733 exports.formatRange = formatRange; 8734 exports.freezeRaw = freezeRaw; 8735 exports.getAllDayHtml = getAllDayHtml; 8736 exports.getClippingParents = getClippingParents; 8737 exports.getDayClasses = getDayClasses; 8738 exports.getElSeg = getElSeg; 8739 exports.getRectCenter = getRectCenter; 8740 exports.getRelevantEvents = getRelevantEvents; 8741 exports.globalDefaults = globalDefaults; 8742 exports.greatestDurationDenominator = greatestDurationDenominator; 8743 exports.hasBgRendering = hasBgRendering; 8744 exports.htmlEscape = htmlEscape; 8745 exports.htmlToElement = htmlToElement; 8746 exports.insertAfterElement = insertAfterElement; 8747 exports.interactionSettingsStore = interactionSettingsStore; 8748 exports.interactionSettingsToStore = interactionSettingsToStore; 8749 exports.intersectRanges = intersectRanges; 8750 exports.intersectRects = intersectRects; 8751 exports.isArraysEqual = isArraysEqual; 8752 exports.isDateSpansEqual = isDateSpansEqual; 8753 exports.isInt = isInt; 8754 exports.isInteractionValid = isInteractionValid; 8755 exports.isMultiDayRange = isMultiDayRange; 8756 exports.isObjectsSimilar = isObjectsSimilar; 8757 exports.isPropsValid = isPropsValid; 8758 exports.isSingleDay = isSingleDay; 8759 exports.isValidDate = isValidDate; 8760 exports.isValuesSimilar = isValuesSimilar; 8761 exports.listenBySelector = listenBySelector; 8762 exports.mapHash = mapHash;
8763 exports.matchCellWidths = matchCellWidths; 8764 exports.memoize = memoize; 8765 exports.memoizeOutput = memoizeOutput; 8766 exports.memoizeRendering = memoizeRendering; 8767 exports.mergeEventStores = mergeEventStores; 8768 exports.multiplyDuration = multiplyDuration; 8769 exports.padStart = padStart; 8770 exports.parseBusinessHours = parseBusinessHours; 8771 exports.parseDragMeta = parseDragMeta; 8772 exports.parseEventDef = parseEventDef; 8773 exports.parseFieldSpecs = parseFieldSpecs; 8774 exports.parseMarker = parse; 8775 exports.pointInsideRect = pointInsideRect; 8776 exports.prependToElement = prependToElement; 8777 exports.preventContextMenu = preventContextMenu; 8778 exports.preventDefault = preventDefault; 8779 exports.preventSelection = preventSelection; 8780 exports.processScopedUiProps = processScopedUiProps; 8781 exports.rangeContainsMarker = rangeContainsMarker; 8782 exports.rangeContainsRange = rangeContainsRange; 8783 exports.rangesEqual = rangesEqual; 8784 exports.rangesIntersect = rangesIntersect; 8785 exports.refineProps = refineProps; 8786 exports.removeElement = removeElement; 8787 exports.removeExact = removeExact; 8788 exports.renderDateCell = renderDateCell; 8789 exports.requestJson = requestJson; 8790 exports.sliceEventStore = sliceEventStore; 8791 exports.startOfDay = startOfDay; 8792 exports.subtractInnerElHeight = subtractInnerElHeight; 8793 exports.translateRect = translateRect; 8794 exports.uncompensateScroll = uncompensateScroll; 8795 exports.undistributeHeight = undistributeHeight; 8796 exports.unpromisify = unpromisify; 8797 exports.version = version; 8798 exports.whenTransitionDone = whenTransitionDone; 8799 exports.wholeDivideDurations = wholeDivideDurations; 8800 8801 Object.defineProperty(exports, '__esModule', { value: true }); 8802 8803})); 8804 8805/*! 8806FullCalendar Day Grid Plugin v4.1.0 8807Docs & License: https://fullcalendar.io/ 8808(c) 2019 Adam Shaw 8809*/ 8810(function (global, factory) { 8811 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : 8812 typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : 8813 (global = global || self, factory(global.FullCalendarDayGrid = {}, global.FullCalendar)); 8814}(this, function (exports, core) { 'use strict'; 8815 8816 /*! ***************************************************************************** 8817 Copyright (c) Microsoft Corporation. All rights reserved. 8818 Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8819 this file except in compliance with the License. You may obtain a copy of the 8820 License at http://www.apache.org/licenses/LICENSE-2.0 8821 8822 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 8823 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 8824 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 8825 MERCHANTABLITY OR NON-INFRINGEMENT. 8826 8827 See the Apache Version 2.0 License for specific language governing permissions 8828 and limitations under the License. 8829 ***************************************************************************** */ 8830 /* global Reflect, Promise */ 8831 8832 var extendStatics = function(d, b) { 8833 extendStatics = Object.setPrototypeOf || 8834 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 8835 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 8836 return extendStatics(d, b); 8837 }; 8838 8839 function __extends(d, b) { 8840 extendStatics(d, b); 8841 function __() { this.constructor = d; } 8842 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 8843 } 8844 8845 var __assign = function() { 8846 __assign = Object.assign || function __assign(t) { 8847 for (var s, i = 1, n = arguments.length; i < n; i++) { 8848 s = arguments[i]; 8849 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 8850 } 8851 return t; 8852 }; 8853 return __assign.apply(this, arguments); 8854 }; 8855 8856 var DayGridDateProfileGenerator = /** @class */ (function (_super) { 8857 __extends(DayGridDateProfileGenerator, _super); 8858 function DayGridDateProfileGenerator() { 8859 return _super !== null && _super.apply(this, arguments) || this; 8860 } 8861 // Computes the date range that will be rendered. 8862 DayGridDateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { 8863 var dateEnv = this.dateEnv; 8864 var renderRange = _super.prototype.buildRenderRange.call(this, currentRange, currentRangeUnit, isRangeAllDay); 8865 var start = renderRange.start; 8866 var end = renderRange.end; 8867 var endOfWeek; 8868 // year and month views should be aligned with weeks. this is already done for week 8869 if (/^(year|month)$/.test(currentRangeUnit)) { 8870 start = dateEnv.startOfWeek(start); 8871 // make end-of-week if not already 8872 endOfWeek = dateEnv.startOfWeek(end); 8873 if (endOfWeek.valueOf() !== end.valueOf()) { 8874 end = core.addWeeks(endOfWeek, 1); 8875 } 8876 } 8877 // ensure 6 weeks 8878 if (this.options.monthMode && 8879 this.options.fixedWeekCount) {
8880 var rowCnt = Math.ceil(// could be partial weeks due to hiddenDays 8881 core.diffWeeks(start, end)); 8882 end = core.addWeeks(end, 6 - rowCnt); 8883 } 8884 return { start: start, end: end }; 8885 }; 8886 return DayGridDateProfileGenerator; 8887 }(core.DateProfileGenerator)); 8888 8889 /* A rectangular panel that is absolutely positioned over other content 8890 ------------------------------------------------------------------------------------------------------------------------ 8891 Options: 8892 - className (string) 8893 - content (HTML string, element, or element array) 8894 - parentEl 8895 - top 8896 - left 8897 - right (the x coord of where the right edge should be. not a "CSS" right) 8898 - autoHide (boolean) 8899 - show (callback) 8900 - hide (callback) 8901 */ 8902 var Popover = /** @class */ (function () { 8903 function Popover(options) { 8904 var _this = this; 8905 this.isHidden = true; 8906 this.margin = 10; // the space required between the popover and the edges of the scroll container 8907 // Triggered when the user clicks *anywhere* in the document, for the autoHide feature 8908 this.documentMousedown = function (ev) { 8909 // only hide the popover if the click happened outside the popover 8910 if (_this.el && !_this.el.contains(ev.target)) { 8911 _this.hide(); 8912 } 8913 }; 8914 this.options = options; 8915 } 8916 // Shows the popover on the specified position. Renders it if not already 8917 Popover.prototype.show = function () { 8918 if (this.isHidden) { 8919 if (!this.el) { 8920 this.render(); 8921 } 8922 this.el.style.display = ''; 8923 this.position(); 8924 this.isHidden = false; 8925 this.trigger('show'); 8926 } 8927 }; 8928 // Hides the popover, through CSS, but does not remove it from the DOM 8929 Popover.prototype.hide = function () { 8930 if (!this.isHidden) { 8931 this.el.style.display = 'none'; 8932 this.isHidden = true; 8933 this.trigger('hide'); 8934 } 8935 }; 8936 // Creates `this.el` and renders content inside of it 8937 Popover.prototype.render = function () { 8938 var _this = this; 8939 var options = this.options; 8940 var el = this.el = core.createElement('div', { 8941 className: 'fc-popover ' + (options.className || ''), 8942 style: { 8943 top: '0', 8944 left: '0' 8945 } 8946 }); 8947 if (typeof options.content === 'function') { 8948 options.content(el); 8949 } 8950 options.parentEl.appendChild(el); 8951 // when a click happens on anything inside with a 'fc-close' className, hide the popover 8952 core.listenBySelector(el, 'click', '.fc-close', function (ev) { 8953 _this.hide(); 8954 }); 8955 if (options.autoHide) { 8956 document.addEventListener('mousedown', this.documentMousedown); 8957 } 8958 }; 8959 // Hides and unregisters any handlers 8960 Popover.prototype.destroy = function () { 8961 this.hide(); 8962 if (this.el) { 8963 core.removeElement(this.el); 8964 this.el = null; 8965 } 8966 document.removeEventListener('mousedown', this.documentMousedown); 8967 }; 8968 // Positions the popover optimally, using the top/left/right options 8969 Popover.prototype.position = function () { 8970 var options = this.options; 8971 var el = this.el; 8972 var elDims = el.getBoundingClientRect(); // only used for width,height 8973 var origin = core.computeRect(el.offsetParent); 8974 var clippingRect = core.computeClippingRect(options.parentEl); 8975 var top; // the "position" (not "offset") values for the popover 8976 var left; // 8977 // compute top and left 8978 top = options.top || 0; 8979 if (options.left !== undefined) { 8980 left = options.left; 8981 } 8982 else if (options.right !== undefined) { 8983 left = options.right - elDims.width; // derive the left value from the right value 8984 } 8985 else { 8986 left = 0; 8987 } 8988 // constrain to the view port. if constrained by two edges, give precedence to top/left 8989 top = Math.min(top, clippingRect.bottom - elDims.height - this.margin); 8990 top = Math.max(top, clippingRect.top + this.margin); 8991 left = Math.min(left, clippingRect.right - elDims.width - this.margin); 8992 left = Math.max(left, clippingRect.left + this.margin); 8993 core.applyStyle(el, { 8994 top: top - origin.top, 8995 left: left - origin.left 8996 }); 8997 }; 8998 // Triggers a callback. Calls a function in the option hash of the same name. 8999 // Arguments beyond the first `name` are forwarded on. 9000 // TODO: better code reuse for this. Repeat code 9001 // can kill this??? 9002 Popover.prototype.trigger = function (name) { 9003 if (this.options[name]) { 9004 this.options[name].apply(this, Array.prototype.slice.call(arguments, 1)); 9005 } 9006 }; 9007 return Popover; 9008 }()); 9009 9010 /* Event-rendering methods for the DayGrid class 9011 ----------------------------------------------------------------------------------------------------------------------*/ 9012 // "Simple" is bad a name. has nothing to do with SimpleDayGrid 9013 var SimpleDayGridEventRenderer = /** @class */ (function (_super) { 9014 __extends(SimpleDayGridEventRenderer, _super); 9015 function SimpleDayGridEventRenderer() { 9016 return _super !== null && _super.apply(this, arguments) || this; 9017 } 9018 // Builds the HTML to be used for the default element for an individual segment 9019 SimpleDayGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { 9020 var options = this.context.options; 9021 var eventRange = seg.eventRange; 9022 var eventDef = eventRange.def; 9023 var eventUi = eventRange.ui; 9024 var allDay = eventDef.allDay; 9025 var isDraggable = eventUi.startEditable; 9026 var isResizableFromStart = allDay && seg.isStart && eventUi.durationEditable && options.eventResizableFromStart; 9027 var isResizableFromEnd = allDay && seg.isEnd && eventUi.durationEditable;
9028 var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); 9029 var skinCss = core.cssToStr(this.getSkinCss(eventUi)); 9030 var timeHtml = ''; 9031 var timeText; 9032 var titleHtml; 9033 classes.unshift('fc-day-grid-event', 'fc-h-event'); 9034 // Only display a timed events time if it is the starting segment 9035 if (seg.isStart) { 9036 timeText = this.getTimeText(eventRange); 9037 if (timeText) { 9038 timeHtml = '<span class="fc-time">' + core.htmlEscape(timeText) + '</span>'; 9039 } 9040 } 9041 titleHtml = 9042 '<span class="fc-title">' + 9043 (core.htmlEscape(eventDef.title || '') || ' ') + // we always want one line of height 9044 '</span>'; 9045 return '<a class="' + classes.join(' ') + '"' + 9046 (eventDef.url ? 9047 ' href="' + core.htmlEscape(eventDef.url) + '"' : 9048 '') + 9049 (skinCss ? 9050 ' style="' + skinCss + '"' : 9051 '') + 9052 '>' + 9053 '<div class="fc-content">' + 9054 (options.dir === 'rtl' ? 9055 titleHtml + ' ' + timeHtml : // put a natural space in between 9056 timeHtml + ' ' + titleHtml // 9057 ) + 9058 '</div>' + 9059 (isResizableFromStart ? 9060 '<div class="fc-resizer fc-start-resizer"></div>' : 9061 '') + 9062 (isResizableFromEnd ? 9063 '<div class="fc-resizer fc-end-resizer"></div>' : 9064 '') + 9065 '</a>'; 9066 }; 9067 // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined 9068 SimpleDayGridEventRenderer.prototype.computeEventTimeFormat = function () { 9069 return { 9070 hour: 'numeric', 9071 minute: '2-digit', 9072 omitZeroMinute: true, 9073 meridiem: 'narrow' 9074 }; 9075 }; 9076 SimpleDayGridEventRenderer.prototype.computeDisplayEventEnd = function () { 9077 return false; // TODO: somehow consider the originating DayGrid's column count 9078 }; 9079 return SimpleDayGridEventRenderer; 9080 }(core.FgEventRenderer)); 9081 9082 /* Event-rendering methods for the DayGrid class 9083 ----------------------------------------------------------------------------------------------------------------------*/ 9084 var DayGridEventRenderer = /** @class */ (function (_super) { 9085 __extends(DayGridEventRenderer, _super); 9086 function DayGridEventRenderer(dayGrid) { 9087 var _this = _super.call(this, dayGrid.context) || this; 9088 _this.dayGrid = dayGrid; 9089 return _this; 9090 } 9091 // Renders the given foreground event segments onto the grid 9092 DayGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { 9093 var rowStructs = this.rowStructs = this.renderSegRows(segs); 9094 // append to each row's content skeleton 9095 this.dayGrid.rowEls.forEach(function (rowNode, i) { 9096 rowNode.querySelector('.fc-content-skeleton > table').appendChild(rowStructs[i].tbodyEl); 9097 }); 9098 // removes the "more.." events popover 9099 if (!mirrorInfo) { 9100 this.dayGrid.removeSegPopover(); 9101 } 9102 }; 9103 // Unrenders all currently rendered foreground event segments 9104 DayGridEventRenderer.prototype.detachSegs = function () { 9105 var rowStructs = this.rowStructs || []; 9106 var rowStruct; 9107 while ((rowStruct = rowStructs.pop())) { 9108 core.removeElement(rowStruct.tbodyEl); 9109 } 9110 this.rowStructs = null; 9111 }; 9112 // Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton. 9113 // Returns an array of rowStruct objects (see the bottom of `renderSegRow`). 9114 // PRECONDITION: each segment shoud already have a rendered and assigned `.el` 9115 DayGridEventRenderer.prototype.renderSegRows = function (segs) { 9116 var rowStructs = []; 9117 var segRows; 9118 var row; 9119 segRows = this.groupSegRows(segs); // group into nested arrays 9120 // iterate each row of segment groupings 9121 for (row = 0; row < segRows.length; row++) { 9122 rowStructs.push(this.renderSegRow(row, segRows[row])); 9123 } 9124 return rowStructs; 9125 }; 9126 // Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains 9127 // the segments. Returns object with a bunch of internal data about how the render was calculated. 9128 // NOTE: modifies rowSegs 9129 DayGridEventRenderer.prototype.renderSegRow = function (row, rowSegs) { 9130 var dayGrid = this.dayGrid; 9131 var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl; 9132 var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels 9133 var levelCnt = Math.max(1, segLevels.length); // ensure at least one level 9134 var tbody = document.createElement('tbody'); 9135 var segMatrix = []; // lookup for which segments are rendered into which level+col cells 9136 var cellMatrix = []; // lookup for all <td> elements of the level+col matrix 9137 var loneCellMatrix = []; // lookup for <td> elements that only take up a single column 9138 var i; 9139 var levelSegs; 9140 var col; 9141 var tr; 9142 var j; 9143 var seg; 9144 var td; 9145 // populates empty cells from the current column (`col`) to `endCol` 9146 function emptyCellsUntil(endCol) { 9147 while (col < endCol) { 9148 // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell 9149 td = (loneCellMatrix[i - 1] || [])[col]; 9150 if (td) { 9151 td.rowSpan = (td.rowSpan || 1) + 1; 9152 } 9153 else { 9154 td = document.createElement('td'); 9155 tr.appendChild(td); 9156 } 9157 cellMatrix[i][col] = td; 9158 loneCellMatrix[i][col] = td; 9159 col++; 9160 } 9161 } 9162 for (i = 0; i < levelCnt; i++) { // iterate through all levels 9163 levelSegs = segLevels[i]; 9164 col = 0; 9165 tr = document.createElement('tr'); 9166 segMatrix.push([]); 9167 cellMatrix.push([]); 9168 loneCellMatrix.push([]); 9169 // levelCnt might be 1 even though there are no actual levels. protect against this. 9170 // this single empty row is useful for styling. 9171 if (levelSegs) { 9172 for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level 9173 seg = levelSegs[j]; 9174 var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; 9175 var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; 9176 emptyCellsUntil(leftCol); 9177 // create a container that occupies or more columns. append the event element. 9178 td = core.createElement('td', { className: 'fc-event-container' }, seg.el); 9179 if (leftCol !== rightCol) { 9180 td.colSpan = rightCol - leftCol + 1; 9181 } 9182 else { // a single-column segment 9183 loneCellMatrix[i][col] = td; 9184 } 9185 while (col <= rightCol) { 9186 cellMatrix[i][col] = td; 9187 segMatrix[i][col] = seg; 9188 col++; 9189 } 9190 tr.appendChild(td); 9191 } 9192 } 9193 emptyCellsUntil(colCnt); // finish off the row 9194 var introHtml = dayGrid.renderProps.renderIntroHtml(); 9195 if (introHtml) { 9196 if (dayGrid.isRtl) { 9197 core.appendToElement(tr, introHtml); 9198 } 9199 else { 9200 core.prependToElement(tr, introHtml); 9201 } 9202 } 9203 tbody.appendChild(tr); 9204 } 9205 return { 9206 row: row, 9207 tbodyEl: tbody, 9208 cellMatrix: cellMatrix, 9209 segMatrix: segMatrix, 9210 segLevels: segLevels, 9211 segs: rowSegs 9212 }; 9213 }; 9214 // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels. 9215 // NOTE: modifies segs 9216 DayGridEventRenderer.prototype.buildSegLevels = function (segs) { 9217 var _a = this.dayGrid, isRtl = _a.isRtl, colCnt = _a.colCnt; 9218 var levels = []; 9219 var i; 9220 var seg; 9221 var j; 9222 // Give preference to elements with certain criteria, so they have 9223 // a chance to be closer to the top. 9224 segs = this.sortEventSegs(segs); 9225 for (i = 0; i < segs.length; i++) { 9226 seg = segs[i]; 9227 // loop through levels, starting with the topmost, until the segment doesn't collide with other segments 9228 for (j = 0; j < levels.length; j++) {
9229 if (!isDaySegCollision(seg, levels[j])) { 9230 break; 9231 } 9232 } 9233 // `j` now holds the desired subrow index 9234 seg.level = j; 9235 seg.leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; // for sorting only 9236 seg.rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol // for sorting only 9237 ; 9238 (levels[j] || (levels[j] = [])).push(seg); 9239 } 9240 // order segments left-to-right. very important if calendar is RTL 9241 for (j = 0; j < levels.length; j++) { 9242 levels[j].sort(compareDaySegCols); 9243 } 9244 return levels; 9245 }; 9246 // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row 9247 DayGridEventRenderer.prototype.groupSegRows = function (segs) { 9248 var segRows = []; 9249 var i; 9250 for (i = 0; i < this.dayGrid.rowCnt; i++) { 9251 segRows.push([]); 9252 } 9253 for (i = 0; i < segs.length; i++) { 9254 segRows[segs[i].row].push(segs[i]); 9255 } 9256 return segRows; 9257 }; 9258 // Computes a default `displayEventEnd` value if one is not expliclty defined 9259 DayGridEventRenderer.prototype.computeDisplayEventEnd = function () { 9260 return this.dayGrid.colCnt === 1; // we'll likely have space if there's only one day 9261 }; 9262 return DayGridEventRenderer; 9263 }(SimpleDayGridEventRenderer)); 9264 // Computes whether two segments' columns collide. They are assumed to be in the same row. 9265 function isDaySegCollision(seg, otherSegs) { 9266 var i; 9267 var otherSeg; 9268 for (i = 0; i < otherSegs.length; i++) { 9269 otherSeg = otherSegs[i]; 9270 if (otherSeg.firstCol <= seg.lastCol && 9271 otherSeg.lastCol >= seg.firstCol) { 9272 return true; 9273 } 9274 } 9275 return false; 9276 } 9277 // A cmp function for determining the leftmost event 9278 function compareDaySegCols(a, b) { 9279 return a.leftCol - b.leftCol; 9280 } 9281 9282 var DayGridMirrorRenderer = /** @class */ (function (_super) { 9283 __extends(DayGridMirrorRenderer, _super); 9284 function DayGridMirrorRenderer() { 9285 return _super !== null && _super.apply(this, arguments) || this; 9286 } 9287 DayGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) { 9288 var sourceSeg = mirrorInfo.sourceSeg; 9289 var rowStructs = this.rowStructs = this.renderSegRows(segs); 9290 // inject each new event skeleton into each associated row 9291 this.dayGrid.rowEls.forEach(function (rowNode, row) { 9292 var skeletonEl = core.htmlToElement('<div class="fc-mirror-skeleton"><table></table></div>'); // will be absolutely positioned 9293 var skeletonTopEl; 9294 var skeletonTop; 9295 // If there is an original segment, match the top position. Otherwise, put it at the row's top level 9296 if (sourceSeg && sourceSeg.row === row) { 9297 skeletonTopEl = sourceSeg.el; 9298 } 9299 else { 9300 skeletonTopEl = rowNode.querySelector('.fc-content-skeleton tbody'); 9301 if (!skeletonTopEl) { // when no events 9302 skeletonTopEl = rowNode.querySelector('.fc-content-skeleton table'); 9303 } 9304 } 9305 skeletonTop = skeletonTopEl.getBoundingClientRect().top - 9306 rowNode.getBoundingClientRect().top; // the offsetParent origin 9307 skeletonEl.style.top = skeletonTop + 'px'; 9308 skeletonEl.querySelector('table').appendChild(rowStructs[row].tbodyEl); 9309 rowNode.appendChild(skeletonEl); 9310 }); 9311 }; 9312 return DayGridMirrorRenderer; 9313 }(DayGridEventRenderer)); 9314 9315 var DayGridFillRenderer = /** @class */ (function (_super) { 9316 __extends(DayGridFillRenderer, _super); 9317 function DayGridFillRenderer(dayGrid) { 9318 var _this = _super.call(this, dayGrid.context) || this; 9319 _this.fillSegTag = 'td'; // override the default tag name 9320 _this.dayGrid = dayGrid; 9321 return _this; 9322 } 9323 DayGridFillRenderer.prototype.renderSegs = function (type, segs) { 9324 // don't render timed background events 9325 if (type === 'bgEvent') { 9326 segs = segs.filter(function (seg) { 9327 return seg.eventRange.def.allDay; 9328 }); 9329 }
9330 _super.prototype.renderSegs.call(this, type, segs); 9331 }; 9332 DayGridFillRenderer.prototype.attachSegs = function (type, segs) { 9333 var els = []; 9334 var i; 9335 var seg; 9336 var skeletonEl; 9337 for (i = 0; i < segs.length; i++) { 9338 seg = segs[i]; 9339 skeletonEl = this.renderFillRow(type, seg); 9340 this.dayGrid.rowEls[seg.row].appendChild(skeletonEl); 9341 els.push(skeletonEl); 9342 } 9343 return els; 9344 }; 9345 // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered. 9346 DayGridFillRenderer.prototype.renderFillRow = function (type, seg) { 9347 var dayGrid = this.dayGrid; 9348 var colCnt = dayGrid.colCnt, isRtl = dayGrid.isRtl; 9349 var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; 9350 var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; 9351 var startCol = leftCol; 9352 var endCol = rightCol + 1; 9353 var className; 9354 var skeletonEl; 9355 var trEl; 9356 if (type === 'businessHours') { 9357 className = 'bgevent'; 9358 } 9359 else { 9360 className = type.toLowerCase(); 9361 } 9362 skeletonEl = core.htmlToElement('<div class="fc-' + className + '-skeleton">' + 9363 '<table><tr></tr></table>' + 9364 '</div>'); 9365 trEl = skeletonEl.getElementsByTagName('tr')[0]; 9366 if (startCol > 0) { 9367 core.appendToElement(trEl, 9368 // will create (startCol + 1) td's 9369 new Array(startCol + 1).join('<td></td>')); 9370 } 9371 seg.el.colSpan = endCol - startCol; 9372 trEl.appendChild(seg.el); 9373 if (endCol < colCnt) { 9374 core.appendToElement(trEl, 9375 // will create (colCnt - endCol) td's 9376 new Array(colCnt - endCol + 1).join('<td></td>')); 9377 } 9378 var introHtml = dayGrid.renderProps.renderIntroHtml(); 9379 if (introHtml) { 9380 if (dayGrid.isRtl) { 9381 core.appendToElement(trEl, introHtml); 9382 } 9383 else { 9384 core.prependToElement(trEl, introHtml); 9385 } 9386 } 9387 return skeletonEl; 9388 }; 9389 return DayGridFillRenderer; 9390 }(core.FillRenderer)); 9391 9392 var DayTile = /** @class */ (function (_super) { 9393 __extends(DayTile, _super); 9394 function DayTile(context, el) { 9395 var _this = _super.call(this, context, el) || this; 9396 var eventRenderer = _this.eventRenderer = new DayTileEventRenderer(_this); 9397 var renderFrame = _this.renderFrame = core.memoizeRendering(_this._renderFrame); 9398 _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderFrame]); 9399 _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); 9400 _this.renderEventDrag = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); 9401 _this.renderEventResize = core.memoizeRendering(eventRenderer.hideByHash.bind(eventRenderer), eventRenderer.showByHash.bind(eventRenderer), [renderFrame]); 9402 context.calendar.registerInteractiveComponent(_this, { 9403 el: _this.el, 9404 useEventCenter: false 9405 }); 9406 return _this; 9407 } 9408 DayTile.prototype.render = function (props) { 9409 this.renderFrame(props.date); 9410 this.renderFgEvents(props.fgSegs); 9411 this.renderEventSelection(props.eventSelection); 9412 this.renderEventDrag(props.eventDragInstances); 9413 this.renderEventResize(props.eventResizeInstances); 9414 }; 9415 DayTile.prototype.destroy = function () { 9416 _super.prototype.destroy.call(this); 9417 this.renderFrame.unrender(); // should unrender everything else 9418 this.calendar.unregisterInteractiveComponent(this); 9419 }; 9420 DayTile.prototype._renderFrame = function (date) { 9421 var _a = this, theme = _a.theme, dateEnv = _a.dateEnv; 9422 var title = dateEnv.format(date, core.createFormatter(this.opt('dayPopoverFormat')) // TODO: cache 9423 ); 9424 this.el.innerHTML = 9425 '<div class="fc-header ' + theme.getClass('popoverHeader') + '">' + 9426 '<span class="fc-title">' + 9427 core.htmlEscape(title) + 9428 '</span>' + 9429 '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' + 9430 '</div>' + 9431 '<div class="fc-body ' + theme.getClass('popoverContent') + '">' + 9432 '<div class="fc-event-container"></div>' + 9433 '</div>'; 9434 this.segContainerEl = this.el.querySelector('.fc-event-container'); 9435 }; 9436 DayTile.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { 9437 var date = this.props.date; // HACK 9438 if (positionLeft < elWidth && positionTop < elHeight) { 9439 return { 9440 component: this, 9441 dateSpan: { 9442 allDay: true, 9443 range: { start: date, end: core.addDays(date, 1) } 9444 }, 9445 dayEl: this.el, 9446 rect: { 9447 left: 0, 9448 top: 0, 9449 right: elWidth, 9450 bottom: elHeight 9451 }, 9452 layer: 1 9453 }; 9454 } 9455 }; 9456 return DayTile; 9457 }(core.DateComponent)); 9458 var DayTileEventRenderer = /** @class */ (function (_super) { 9459 __extends(DayTileEventRenderer, _super); 9460 function DayTileEventRenderer(dayTile) { 9461 var _this = _super.call(this, dayTile.context) || this; 9462 _this.dayTile = dayTile; 9463 return _this; 9464 } 9465 DayTileEventRenderer.prototype.attachSegs = function (segs) { 9466 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 9467 var seg = segs_1[_i]; 9468 this.dayTile.segContainerEl.appendChild(seg.el); 9469 } 9470 }; 9471 DayTileEventRenderer.prototype.detachSegs = function (segs) { 9472 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 9473 var seg = segs_2[_i]; 9474 core.removeElement(seg.el); 9475 } 9476 }; 9477 return DayTileEventRenderer; 9478 }(SimpleDayGridEventRenderer)); 9479 9480 var DayBgRow = /** @class */ (function () { 9481 function DayBgRow(context) { 9482 this.context = context; 9483 } 9484 DayBgRow.prototype.renderHtml = function (props) { 9485 var parts = []; 9486 if (props.renderIntroHtml) { 9487 parts.push(props.renderIntroHtml()); 9488 } 9489 for (var _i = 0, _a = props.cells; _i < _a.length; _i++) { 9490 var cell = _a[_i]; 9491 parts.push(renderCellHtml(cell.date, props.dateProfile, this.context, cell.htmlAttrs)); 9492 } 9493 if (!props.cells.length) { 9494 parts.push('<td class="fc-day ' + this.context.theme.getClass('widgetContent') + '"></td>'); 9495 } 9496 if (this.context.options.dir === 'rtl') { 9497 parts.reverse(); 9498 } 9499 return '<tr>' + parts.join('') + '</tr>'; 9500 }; 9501 return DayBgRow; 9502 }()); 9503 function renderCellHtml(date, dateProfile, context, otherAttrs) { 9504 var dateEnv = context.dateEnv, theme = context.theme; 9505 var isDateValid = core.rangeContainsMarker(dateProfile.activeRange, date); // TODO: called too frequently. cache somehow. 9506 var classes = core.getDayClasses(date, dateProfile, context); 9507 classes.unshift('fc-day', theme.getClass('widgetContent')); 9508 return '<td class="' + classes.join(' ') + '"' + 9509 (isDateValid ? 9510 ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : 9511 '') + 9512 (otherAttrs ?
9513 ' ' + otherAttrs : 9514 '') + 9515 '></td>'; 9516 } 9517 9518 var DAY_NUM_FORMAT = core.createFormatter({ day: 'numeric' }); 9519 var WEEK_NUM_FORMAT = core.createFormatter({ week: 'numeric' }); 9520 var DayGrid = /** @class */ (function (_super) { 9521 __extends(DayGrid, _super); 9522 function DayGrid(context, el, renderProps) { 9523 var _this = _super.call(this, context, el) || this; 9524 _this.bottomCoordPadding = 0; // hack for extending the hit area for the last row of the coordinate grid 9525 _this.isCellSizesDirty = false; 9526 var eventRenderer = _this.eventRenderer = new DayGridEventRenderer(_this); 9527 var fillRenderer = _this.fillRenderer = new DayGridFillRenderer(_this); 9528 _this.mirrorRenderer = new DayGridMirrorRenderer(_this); 9529 var renderCells = _this.renderCells = core.memoizeRendering(_this._renderCells, _this._unrenderCells); 9530 _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderCells]); 9531 _this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'), [renderCells]); 9532 _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderCells]); 9533 _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderCells]); 9534 _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); 9535 _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderCells]); 9536 _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderCells]); 9537 _this.renderProps = renderProps; 9538 return _this; 9539 } 9540 DayGrid.prototype.render = function (props) { 9541 var cells = props.cells; 9542 this.rowCnt = cells.length; 9543 this.colCnt = cells[0].length; 9544 this.renderCells(cells, props.isRigid); 9545 this.renderBusinessHours(props.businessHourSegs); 9546 this.renderDateSelection(props.dateSelectionSegs); 9547 this.renderBgEvents(props.bgEventSegs); 9548 this.renderFgEvents(props.fgEventSegs); 9549 this.renderEventSelection(props.eventSelection); 9550 this.renderEventDrag(props.eventDrag); 9551 this.renderEventResize(props.eventResize); 9552 if (this.segPopoverTile) { 9553 this.updateSegPopoverTile(); 9554 } 9555 }; 9556 DayGrid.prototype.destroy = function () { 9557 _super.prototype.destroy.call(this); 9558 this.renderCells.unrender(); // will unrender everything else 9559 }; 9560 DayGrid.prototype.getCellRange = function (row, col) { 9561 var start = this.props.cells[row][col].date; 9562 var end = core.addDays(start, 1); 9563 return { start: start, end: end }; 9564 }; 9565 DayGrid.prototype.updateSegPopoverTile = function (date, segs) { 9566 var ownProps = this.props; 9567 this.segPopoverTile.receiveProps({ 9568 date: date || this.segPopoverTile.props.date, 9569 fgSegs: segs || this.segPopoverTile.props.fgSegs, 9570 eventSelection: ownProps.eventSelection, 9571 eventDragInstances: ownProps.eventDrag ? ownProps.eventDrag.affectedInstances : null, 9572 eventResizeInstances: ownProps.eventResize ? ownProps.eventResize.affectedInstances : null 9573 }); 9574 }; 9575 /* Date Rendering 9576 ------------------------------------------------------------------------------------------------------------------*/ 9577 DayGrid.prototype._renderCells = function (cells, isRigid) { 9578 var _a = this, view = _a.view, dateEnv = _a.dateEnv; 9579 var _b = this, rowCnt = _b.rowCnt, colCnt = _b.colCnt; 9580 var html = ''; 9581 var row; 9582 var col; 9583 for (row = 0; row < rowCnt; row++) { 9584 html += this.renderDayRowHtml(row, isRigid); 9585 } 9586 this.el.innerHTML = html; 9587 this.rowEls = core.findElements(this.el, '.fc-row'); 9588 this.cellEls = core.findElements(this.el, '.fc-day, .fc-disabled-day'); 9589 if (this.isRtl) { 9590 this.cellEls.reverse(); 9591 } 9592 this.rowPositions = new core.PositionCache(this.el, this.rowEls, false, true // vertical 9593 ); 9594 this.colPositions = new core.PositionCache(this.el, this.cellEls.slice(0, colCnt), // only the first row 9595 true, false // horizontal 9596 ); 9597 // trigger dayRender with each cell's element 9598 for (row = 0; row < rowCnt; row++) { 9599 for (col = 0; col < colCnt; col++) { 9600 this.publiclyTrigger('dayRender', [ 9601 { 9602 date: dateEnv.toDate(cells[row][col].date), 9603 el: this.getCellEl(row, col), 9604 view: view 9605 } 9606 ]); 9607 } 9608 } 9609 this.isCellSizesDirty = true; 9610 }; 9611 DayGrid.prototype._unrenderCells = function () { 9612 this.removeSegPopover(); 9613 }; 9614 // Generates the HTML for a single row, which is a div that wraps a table. 9615 // `row` is the row number. 9616 DayGrid.prototype.renderDayRowHtml = function (row, isRigid) { 9617 var theme = this.theme; 9618 var classes = ['fc-row', 'fc-week', theme.getClass('dayRow')]; 9619 if (isRigid) { 9620 classes.push('fc-rigid'); 9621 } 9622 var bgRow = new DayBgRow(this.context); 9623 return '' + 9624 '<div class="' + classes.join(' ') + '">' + 9625 '<div class="fc-bg">' + 9626 '<table class="' + theme.getClass('tableGrid') + '">' + 9627 bgRow.renderHtml({ 9628 cells: this.props.cells[row], 9629 dateProfile: this.props.dateProfile, 9630 renderIntroHtml: this.renderProps.renderBgIntroHtml 9631 }) + 9632 '</table>' + 9633 '</div>' + 9634 '<div class="fc-content-skeleton">' + 9635 '<table>' + 9636 (this.getIsNumbersVisible() ? 9637 '<thead>' + 9638 this.renderNumberTrHtml(row) + 9639 '</thead>' : 9640 '') + 9641 '</table>' + 9642 '</div>' + 9643 '</div>'; 9644 }; 9645 DayGrid.prototype.getIsNumbersVisible = function () { 9646 return this.getIsDayNumbersVisible() || 9647 this.renderProps.cellWeekNumbersVisible || 9648 this.renderProps.colWeekNumbersVisible; 9649 }; 9650 DayGrid.prototype.getIsDayNumbersVisible = function () { 9651 return this.rowCnt > 1; 9652 }; 9653 /* Grid Number Rendering 9654 ------------------------------------------------------------------------------------------------------------------*/ 9655 DayGrid.prototype.renderNumberTrHtml = function (row) { 9656 var intro = this.renderProps.renderNumberIntroHtml(row, this); 9657 return '' + 9658 '<tr>' + 9659 (this.isRtl ? '' : intro) + 9660 this.renderNumberCellsHtml(row) + 9661 (this.isRtl ? intro : '') + 9662 '</tr>'; 9663 }; 9664 DayGrid.prototype.renderNumberCellsHtml = function (row) { 9665 var htmls = []; 9666 var col; 9667 var date; 9668 for (col = 0; col < this.colCnt; col++) { 9669 date = this.props.cells[row][col].date; 9670 htmls.push(this.renderNumberCellHtml(date)); 9671 } 9672 if (this.isRtl) { 9673 htmls.reverse(); 9674 } 9675 return htmls.join(''); 9676 }; 9677 // Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton. 9678 // The number row will only exist if either day numbers or week numbers are turned on. 9679 DayGrid.prototype.renderNumberCellHtml = function (date) { 9680 var _a = this, view = _a.view, dateEnv = _a.dateEnv; 9681 var html = ''; 9682 var isDateValid = core.rangeContainsMarker(this.props.dateProfile.activeRange, date); // TODO: called too frequently. cache somehow. 9683 var isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid; 9684 var classes; 9685 var weekCalcFirstDow; 9686 if (!isDayNumberVisible && !this.renderProps.cellWeekNumbersVisible) { 9687 // no numbers in day cell (week number must be along the side) 9688 return '<td></td>'; // will create an empty space above events :( 9689 } 9690 classes = core.getDayClasses(date, this.props.dateProfile, this.context); 9691 classes.unshift('fc-day-top'); 9692 if (this.renderProps.cellWeekNumbersVisible) { 9693 weekCalcFirstDow = dateEnv.weekDow; 9694 } 9695 html += '<td class="' + classes.join(' ') + '"' + 9696 (isDateValid ? 9697 ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : 9698 '') + 9699 '>'; 9700 if (this.renderProps.cellWeekNumbersVisible && (date.getUTCDay() === weekCalcFirstDow)) { 9701 html += core.buildGotoAnchorHtml(view, { date: date, type: 'week' }, { 'class': 'fc-week-number' }, dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML 9702 ); 9703 } 9704 if (isDayNumberVisible) { 9705 html += core.buildGotoAnchorHtml(view, date, { 'class': 'fc-day-number' }, dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML 9706 ); 9707 } 9708 html += '</td>'; 9709 return html; 9710 }; 9711 /* Sizing 9712 ------------------------------------------------------------------------------------------------------------------*/ 9713 DayGrid.prototype.updateSize = function (isResize) { 9714 var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; 9715 if (isResize || 9716 this.isCellSizesDirty || 9717 this.view.calendar.isEventsUpdated // hack 9718 ) { 9719 this.buildPositionCaches(); 9720 this.isCellSizesDirty = false;
9721 } 9722 fillRenderer.computeSizes(isResize); 9723 eventRenderer.computeSizes(isResize); 9724 mirrorRenderer.computeSizes(isResize); 9725 fillRenderer.assignSizes(isResize); 9726 eventRenderer.assignSizes(isResize); 9727 mirrorRenderer.assignSizes(isResize); 9728 }; 9729 DayGrid.prototype.buildPositionCaches = function () { 9730 this.buildColPositions(); 9731 this.buildRowPositions(); 9732 }; 9733 DayGrid.prototype.buildColPositions = function () { 9734 this.colPositions.build(); 9735 }; 9736 DayGrid.prototype.buildRowPositions = function () { 9737 this.rowPositions.build(); 9738 this.rowPositions.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack 9739 }; 9740 /* Hit System 9741 ------------------------------------------------------------------------------------------------------------------*/ 9742 DayGrid.prototype.positionToHit = function (leftPosition, topPosition) { 9743 var _a = this, colPositions = _a.colPositions, rowPositions = _a.rowPositions; 9744 var col = colPositions.leftToIndex(leftPosition); 9745 var row = rowPositions.topToIndex(topPosition); 9746 if (row != null && col != null) { 9747 return { 9748 row: row, 9749 col: col, 9750 dateSpan: { 9751 range: this.getCellRange(row, col), 9752 allDay: true 9753 }, 9754 dayEl: this.getCellEl(row, col), 9755 relativeRect: { 9756 left: colPositions.lefts[col], 9757 right: colPositions.rights[col], 9758 top: rowPositions.tops[row], 9759 bottom: rowPositions.bottoms[row] 9760 } 9761 }; 9762 } 9763 }; 9764 /* Cell System 9765 ------------------------------------------------------------------------------------------------------------------*/ 9766 // FYI: the first column is the leftmost column, regardless of date 9767 DayGrid.prototype.getCellEl = function (row, col) { 9768 return this.cellEls[row * this.colCnt + col]; 9769 }; 9770 /* Event Drag Visualization 9771 ------------------------------------------------------------------------------------------------------------------*/ 9772 DayGrid.prototype._renderEventDrag = function (state) { 9773 if (state) { 9774 this.eventRenderer.hideByHash(state.affectedInstances); 9775 this.fillRenderer.renderSegs('highlight', state.segs); 9776 } 9777 }; 9778 DayGrid.prototype._unrenderEventDrag = function (state) { 9779 if (state) { 9780 this.eventRenderer.showByHash(state.affectedInstances); 9781 this.fillRenderer.unrender('highlight'); 9782 } 9783 }; 9784 /* Event Resize Visualization 9785 ------------------------------------------------------------------------------------------------------------------*/ 9786 DayGrid.prototype._renderEventResize = function (state) { 9787 if (state) { 9788 this.eventRenderer.hideByHash(state.affectedInstances); 9789 this.fillRenderer.renderSegs('highlight', state.segs); 9790 this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); 9791 } 9792 }; 9793 DayGrid.prototype._unrenderEventResize = function (state) { 9794 if (state) { 9795 this.eventRenderer.showByHash(state.affectedInstances); 9796 this.fillRenderer.unrender('highlight'); 9797 this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); 9798 } 9799 }; 9800 /* More+ Link Popover 9801 ------------------------------------------------------------------------------------------------------------------*/ 9802 DayGrid.prototype.removeSegPopover = function () { 9803 if (this.segPopover) { 9804 this.segPopover.hide(); // in handler, will call segPopover's removeElement 9805 } 9806 }; 9807 // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid. 9808 // `levelLimit` can be false (don't limit), a number, or true (should be computed). 9809 DayGrid.prototype.limitRows = function (levelLimit) { 9810 var rowStructs = this.eventRenderer.rowStructs || []; 9811 var row; // row # 9812 var rowLevelLimit; 9813 for (row = 0; row < rowStructs.length; row++) { 9814 this.unlimitRow(row); 9815 if (!levelLimit) { 9816 rowLevelLimit = false;
9817 } 9818 else if (typeof levelLimit === 'number') { 9819 rowLevelLimit = levelLimit; 9820 } 9821 else { 9822 rowLevelLimit = this.computeRowLevelLimit(row); 9823 } 9824 if (rowLevelLimit !== false) { 9825 this.limitRow(row, rowLevelLimit); 9826 } 9827 } 9828 }; 9829 // Computes the number of levels a row will accomodate without going outside its bounds. 9830 // Assumes the row is "rigid" (maintains a constant height regardless of what is inside). 9831 // `row` is the row number. 9832 DayGrid.prototype.computeRowLevelLimit = function (row) { 9833 var rowEl = this.rowEls[row]; // the containing "fake" row div 9834 var rowBottom = rowEl.getBoundingClientRect().bottom; // relative to viewport! 9835 var trEls = core.findChildren(this.eventRenderer.rowStructs[row].tbodyEl); 9836 var i; 9837 var trEl; 9838 // Reveal one level <tr> at a time and stop when we find one out of bounds 9839 for (i = 0; i < trEls.length; i++) { 9840 trEl = trEls[i]; 9841 trEl.classList.remove('fc-limited'); // reset to original state (reveal) 9842 if (trEl.getBoundingClientRect().bottom > rowBottom) { 9843 return i; 9844 } 9845 } 9846 return false; // should not limit at all 9847 }; 9848 // Limits the given grid row to the maximum number of levels and injects "more" links if necessary. 9849 // `row` is the row number. 9850 // `levelLimit` is a number for the maximum (inclusive) number of levels allowed. 9851 DayGrid.prototype.limitRow = function (row, levelLimit) { 9852 var _this = this; 9853 var _a = this, colCnt = _a.colCnt, isRtl = _a.isRtl; 9854 var rowStruct = this.eventRenderer.rowStructs[row]; 9855 var moreNodes = []; // array of "more" <a> links and <td> DOM nodes 9856 var col = 0; // col #, left-to-right (not chronologically) 9857 var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right 9858 var cellMatrix; // a matrix (by level, then column) of all <td> elements in the row 9859 var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes 9860 var i; 9861 var seg; 9862 var segsBelow; // array of segment objects below `seg` in the current `col` 9863 var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies 9864 var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column) 9865 var td; 9866 var rowSpan; 9867 var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell 9868 var j; 9869 var moreTd; 9870 var moreWrap; 9871 var moreLink; 9872 // Iterates through empty level cells and places "more" links inside if need be 9873 var emptyCellsUntil = function (endCol) { 9874 while (col < endCol) { 9875 segsBelow = _this.getCellSegs(row, col, levelLimit); 9876 if (segsBelow.length) { 9877 td = cellMatrix[levelLimit - 1][col]; 9878 moreLink = _this.renderMoreLink(row, col, segsBelow); 9879 moreWrap = core.createElement('div', null, moreLink); 9880 td.appendChild(moreWrap); 9881 moreNodes.push(moreWrap); 9882 } 9883 col++; 9884 } 9885 }; 9886 if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit? 9887 levelSegs = rowStruct.segLevels[levelLimit - 1]; 9888 cellMatrix = rowStruct.cellMatrix; 9889 limitedNodes = core.findChildren(rowStruct.tbodyEl).slice(levelLimit); // get level <tr> elements past the limit 9890 limitedNodes.forEach(function (node) { 9891 node.classList.add('fc-limited'); // hide elements and get a simple DOM-nodes array 9892 }); 9893 // iterate though segments in the last allowable level 9894 for (i = 0; i < levelSegs.length; i++) { 9895 seg = levelSegs[i]; 9896 var leftCol = isRtl ? (colCnt - 1 - seg.lastCol) : seg.firstCol; 9897 var rightCol = isRtl ? (colCnt - 1 - seg.firstCol) : seg.lastCol; 9898 emptyCellsUntil(leftCol); // process empty cells before the segment 9899 // determine *all* segments below `seg` that occupy the same columns 9900 colSegsBelow = []; 9901 totalSegsBelow = 0; 9902 while (col <= rightCol) { 9903 segsBelow = this.getCellSegs(row, col, levelLimit); 9904 colSegsBelow.push(segsBelow); 9905 totalSegsBelow += segsBelow.length; 9906 col++; 9907 } 9908 if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links? 9909 td = cellMatrix[levelLimit - 1][leftCol]; // the segment's parent cell 9910 rowSpan = td.rowSpan || 1; 9911 segMoreNodes = []; 9912 // make a replacement <td> for each column the segment occupies. will be one for each colspan 9913 for (j = 0; j < colSegsBelow.length; j++) { 9914 moreTd = core.createElement('td', { className: 'fc-more-cell', rowSpan: rowSpan }); 9915 segsBelow = colSegsBelow[j]; 9916 moreLink = this.renderMoreLink(row, leftCol + j, [seg].concat(segsBelow) // count seg as hidden too 9917 ); 9918 moreWrap = core.createElement('div', null, moreLink); 9919 moreTd.appendChild(moreWrap); 9920 segMoreNodes.push(moreTd); 9921 moreNodes.push(moreTd); 9922 } 9923 td.classList.add('fc-limited'); 9924 core.insertAfterElement(td, segMoreNodes); 9925 limitedNodes.push(td); 9926 } 9927 } 9928 emptyCellsUntil(this.colCnt); // finish off the level 9929 rowStruct.moreEls = moreNodes; // for easy undoing later 9930 rowStruct.limitedEls = limitedNodes; // for easy undoing later 9931 } 9932 }; 9933 // Reveals all levels and removes all "more"-related elements for a grid's row. 9934 // `row` is a row number. 9935 DayGrid.prototype.unlimitRow = function (row) { 9936 var rowStruct = this.eventRenderer.rowStructs[row]; 9937 if (rowStruct.moreEls) {
9938 rowStruct.moreEls.forEach(core.removeElement); 9939 rowStruct.moreEls = null; 9940 } 9941 if (rowStruct.limitedEls) { 9942 rowStruct.limitedEls.forEach(function (limitedEl) { 9943 limitedEl.classList.remove('fc-limited'); 9944 }); 9945 rowStruct.limitedEls = null; 9946 } 9947 }; 9948 // Renders an <a> element that represents hidden event element for a cell. 9949 // Responsible for attaching click handler as well. 9950 DayGrid.prototype.renderMoreLink = function (row, col, hiddenSegs) { 9951 var _this = this; 9952 var _a = this, view = _a.view, dateEnv = _a.dateEnv; 9953 var a = core.createElement('a', { className: 'fc-more' }); 9954 a.innerText = this.getMoreLinkText(hiddenSegs.length); 9955 a.addEventListener('click', function (ev) { 9956 var clickOption = _this.opt('eventLimitClick'); 9957 var _col = _this.isRtl ? _this.colCnt - col - 1 : col; // HACK: props.cells has different dir system? 9958 var date = _this.props.cells[row][_col].date; 9959 var moreEl = ev.currentTarget; 9960 var dayEl = _this.getCellEl(row, col); 9961 var allSegs = _this.getCellSegs(row, col); 9962 // rescope the segments to be within the cell's date 9963 var reslicedAllSegs = _this.resliceDaySegs(allSegs, date); 9964 var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date); 9965 if (typeof clickOption === 'function') { 9966 // the returned value can be an atomic option 9967 clickOption = _this.publiclyTrigger('eventLimitClick', [ 9968 { 9969 date: dateEnv.toDate(date), 9970 allDay: true, 9971 dayEl: dayEl, 9972 moreEl: moreEl, 9973 segs: reslicedAllSegs, 9974 hiddenSegs: reslicedHiddenSegs, 9975 jsEvent: ev, 9976 view: view 9977 } 9978 ]); 9979 } 9980 if (clickOption === 'popover') { 9981 _this.showSegPopover(row, col, moreEl, reslicedAllSegs); 9982 } 9983 else if (typeof clickOption === 'string') { // a view name 9984 view.calendar.zoomTo(date, clickOption); 9985 } 9986 }); 9987 return a; 9988 }; 9989 // Reveals the popover that displays all events within a cell 9990 DayGrid.prototype.showSegPopover = function (row, col, moreLink, segs) { 9991 var _this = this; 9992 var _a = this, calendar = _a.calendar, view = _a.view, theme = _a.theme; 9993 var _col = this.isRtl ? this.colCnt - col - 1 : col; // HACK: props.cells has different dir system? 9994 var moreWrap = moreLink.parentNode; // the <div> wrapper around the <a> 9995 var topEl; // the element we want to match the top coordinate of 9996 var options; 9997 if (this.rowCnt === 1) { 9998 topEl = view.el; // will cause the popover to cover any sort of header 9999 } 10000 else { 10001 topEl = this.rowEls[row]; // will align with top of row 10002 } 10003 options = { 10004 className: 'fc-more-popover ' + theme.getClass('popover'), 10005 parentEl: view.el, 10006 top: core.computeRect(topEl).top, 10007 autoHide: true, 10008 content: function (el) { 10009 _this.segPopoverTile = new DayTile(_this.context, el); 10010 _this.updateSegPopoverTile(_this.props.cells[row][_col].date, segs); 10011 }, 10012 hide: function () { 10013 _this.segPopoverTile.destroy(); 10014 _this.segPopoverTile = null; 10015 _this.segPopover.destroy(); 10016 _this.segPopover = null; 10017 } 10018 }; 10019 // Determine horizontal coordinate. 10020 // We use the moreWrap instead of the <td> to avoid border confusion. 10021 if (this.isRtl) { 10022 options.right = core.computeRect(moreWrap).right + 1; // +1 to be over cell border 10023 } 10024 else { 10025 options.left = core.computeRect(moreWrap).left - 1; // -1 to be over cell border 10026 } 10027 this.segPopover = new Popover(options); 10028 this.segPopover.show(); 10029 calendar.releaseAfterSizingTriggers(); // hack for eventPositioned 10030 }; 10031 // Given the events within an array of segment objects, reslice them to be in a single day
10032 DayGrid.prototype.resliceDaySegs = function (segs, dayDate) { 10033 var dayStart = dayDate; 10034 var dayEnd = core.addDays(dayStart, 1); 10035 var dayRange = { start: dayStart, end: dayEnd }; 10036 var newSegs = []; 10037 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 10038 var seg = segs_1[_i]; 10039 var eventRange = seg.eventRange; 10040 var origRange = eventRange.range; 10041 var slicedRange = core.intersectRanges(origRange, dayRange); 10042 if (slicedRange) { 10043 newSegs.push(__assign({}, seg, { eventRange: { 10044 def: eventRange.def, 10045 ui: __assign({}, eventRange.ui, { durationEditable: false }), 10046 instance: eventRange.instance, 10047 range: slicedRange 10048 }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() })); 10049 } 10050 } 10051 return newSegs; 10052 }; 10053 // Generates the text that should be inside a "more" link, given the number of events it represents 10054 DayGrid.prototype.getMoreLinkText = function (num) { 10055 var opt = this.opt('eventLimitText'); 10056 if (typeof opt === 'function') { 10057 return opt(num); 10058 } 10059 else { 10060 return '+' + num + ' ' + opt; 10061 } 10062 }; 10063 // Returns segments within a given cell. 10064 // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs. 10065 DayGrid.prototype.getCellSegs = function (row, col, startLevel) { 10066 var segMatrix = this.eventRenderer.rowStructs[row].segMatrix; 10067 var level = startLevel || 0; 10068 var segs = []; 10069 var seg; 10070 while (level < segMatrix.length) { 10071 seg = segMatrix[level][col]; 10072 if (seg) { 10073 segs.push(seg); 10074 } 10075 level++; 10076 } 10077 return segs; 10078 }; 10079 return DayGrid; 10080 }(core.DateComponent)); 10081 10082 var WEEK_NUM_FORMAT$1 = core.createFormatter({ week: 'numeric' }); 10083 /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells. 10084 ----------------------------------------------------------------------------------------------------------------------*/ 10085 // It is a manager for a DayGrid subcomponent, which does most of the heavy lifting. 10086 // It is responsible for managing width/height. 10087 var DayGridView = /** @class */ (function (_super) { 10088 __extends(DayGridView, _super); 10089 function DayGridView(context, viewSpec, dateProfileGenerator, parentEl) { 10090 var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; 10091 /* Header Rendering 10092 ------------------------------------------------------------------------------------------------------------------*/ 10093 // Generates the HTML that will go before the day-of week header cells 10094 _this.renderHeadIntroHtml = function () { 10095 var theme = _this.theme; 10096 if (_this.colWeekNumbersVisible) { 10097 return '' + 10098 '<th class="fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.weekNumberStyleAttr() + '>' + 10099 '<span>' + // needed for matchCellWidths 10100 core.htmlEscape(_this.opt('weekLabel')) + 10101 '</span>' + 10102 '</th>'; 10103 } 10104 return ''; 10105 }; 10106 /* Day Grid Rendering 10107 ------------------------------------------------------------------------------------------------------------------*/ 10108 // Generates the HTML that will go before content-skeleton cells that display the day/week numbers 10109 _this.renderDayGridNumberIntroHtml = function (row, dayGrid) { 10110 var dateEnv = _this.dateEnv; 10111 var weekStart = dayGrid.props.cells[row][0].date; 10112 if (_this.colWeekNumbersVisible) { 10113 return '' + 10114 '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '>' + 10115 core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths 10116 _this, { date: weekStart, type: 'week', forceOff: dayGrid.colCnt === 1 }, dateEnv.format(weekStart, WEEK_NUM_FORMAT$1) // inner HTML 10117 ) + 10118 '</td>'; 10119 } 10120 return ''; 10121 }; 10122 // Generates the HTML that goes before the day bg cells for each day-row 10123 _this.renderDayGridBgIntroHtml = function () { 10124 var theme = _this.theme; 10125 if (_this.colWeekNumbersVisible) { 10126 return '<td class="fc-week-number ' + theme.getClass('widgetContent') + '" ' + _this.weekNumberStyleAttr() + '></td>'; 10127 } 10128 return ''; 10129 }; 10130 // Generates the HTML that goes before every other type of row generated by DayGrid. 10131 // Affects mirror-skeleton and highlight-skeleton rows. 10132 _this.renderDayGridIntroHtml = function () { 10133 if (_this.colWeekNumbersVisible) { 10134 return '<td class="fc-week-number" ' + _this.weekNumberStyleAttr() + '></td>'; 10135 } 10136 return ''; 10137 }; 10138 _this.el.classList.add('fc-dayGrid-view'); 10139 _this.el.innerHTML = _this.renderSkeletonHtml();
10140 _this.scroller = new core.ScrollComponent('hidden', // overflow x 10141 'auto' // overflow y 10142 ); 10143 var dayGridContainerEl = _this.scroller.el; 10144 _this.el.querySelector('.fc-body > tr > td').appendChild(dayGridContainerEl); 10145 dayGridContainerEl.classList.add('fc-day-grid-container'); 10146 var dayGridEl = core.createElement('div', { className: 'fc-day-grid' }); 10147 dayGridContainerEl.appendChild(dayGridEl); 10148 var cellWeekNumbersVisible; 10149 if (_this.opt('weekNumbers')) { 10150 if (_this.opt('weekNumbersWithinDays')) { 10151 cellWeekNumbersVisible = true; 10152 _this.colWeekNumbersVisible = false; 10153 } 10154 else { 10155 cellWeekNumbersVisible = false; 10156 _this.colWeekNumbersVisible = true; 10157 } 10158 } 10159 else { 10160 _this.colWeekNumbersVisible = false; 10161 cellWeekNumbersVisible = false; 10162 } 10163 _this.dayGrid = new DayGrid(_this.context, dayGridEl, { 10164 renderNumberIntroHtml: _this.renderDayGridNumberIntroHtml, 10165 renderBgIntroHtml: _this.renderDayGridBgIntroHtml, 10166 renderIntroHtml: _this.renderDayGridIntroHtml, 10167 colWeekNumbersVisible: _this.colWeekNumbersVisible, 10168 cellWeekNumbersVisible: cellWeekNumbersVisible 10169 }); 10170 return _this; 10171 } 10172 DayGridView.prototype.destroy = function () { 10173 _super.prototype.destroy.call(this); 10174 this.dayGrid.destroy(); 10175 this.scroller.destroy(); 10176 }; 10177 // Builds the HTML skeleton for the view. 10178 // The day-grid component will render inside of a container defined by this HTML. 10179 DayGridView.prototype.renderSkeletonHtml = function () { 10180 var theme = this.theme; 10181 return '' + 10182 '<table class="' + theme.getClass('tableGrid') + '">' + 10183 (this.opt('columnHeader') ? 10184 '<thead class="fc-head">' + 10185 '<tr>' + 10186 '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"> </td>' + 10187 '</tr>' + 10188 '</thead>' : 10189 '') + 10190 '<tbody class="fc-body">' + 10191 '<tr>' + 10192 '<td class="' + theme.getClass('widgetContent') + '"></td>' + 10193 '</tr>' + 10194 '</tbody>' + 10195 '</table>'; 10196 }; 10197 // Generates an HTML attribute string for setting the width of the week number column, if it is known 10198 DayGridView.prototype.weekNumberStyleAttr = function () { 10199 if (this.weekNumberWidth != null) { 10200 return 'style="width:' + this.weekNumberWidth + 'px"'; 10201 } 10202 return ''; 10203 }; 10204 // Determines whether each row should have a constant height 10205 DayGridView.prototype.hasRigidRows = function () { 10206 var eventLimit = this.opt('eventLimit'); 10207 return eventLimit && typeof eventLimit !== 'number'; 10208 }; 10209 /* Dimensions 10210 ------------------------------------------------------------------------------------------------------------------*/ 10211 DayGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) { 10212 _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first 10213 this.dayGrid.updateSize(isResize); 10214 }; 10215 // Refreshes the horizontal dimensions of the view 10216 DayGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { 10217 var dayGrid = this.dayGrid; 10218 var eventLimit = this.opt('eventLimit'); 10219 var headRowEl = this.header ? this.header.el : null; // HACK 10220 var scrollerHeight; 10221 var scrollbarWidths; 10222 // hack to give the view some height prior to dayGrid's columns being rendered 10223 // TODO: separate setting height from scroller VS dayGrid. 10224 if (!dayGrid.rowEls) { 10225 if (!isAuto) { 10226 scrollerHeight = this.computeScrollerHeight(viewHeight); 10227 this.scroller.setHeight(scrollerHeight); 10228 } 10229 return; 10230 } 10231 if (this.colWeekNumbersVisible) { 10232 // Make sure all week number cells running down the side have the same width. 10233 this.weekNumberWidth = core.matchCellWidths(core.findElements(this.el, '.fc-week-number')); 10234 } 10235 // reset all heights to be natural 10236 this.scroller.clear(); 10237 if (headRowEl) { 10238 core.uncompensateScroll(headRowEl); 10239 } 10240 dayGrid.removeSegPopover(); // kill the "more" popover if displayed 10241 // is the event limit a constant level number? 10242 if (eventLimit && typeof eventLimit === 'number') { 10243 dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after 10244 } 10245 // distribute the height to the rows 10246 // (viewHeight is a "recommended" value if isAuto) 10247 scrollerHeight = this.computeScrollerHeight(viewHeight); 10248 this.setGridHeight(scrollerHeight, isAuto); 10249 // is the event limit dynamically calculated? 10250 if (eventLimit && typeof eventLimit !== 'number') { 10251 dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set 10252 } 10253 if (!isAuto) { // should we force dimensions of the scroll container? 10254 this.scroller.setHeight(scrollerHeight);
10255 scrollbarWidths = this.scroller.getScrollbarWidths(); 10256 if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars? 10257 if (headRowEl) { 10258 core.compensateScroll(headRowEl, scrollbarWidths); 10259 } 10260 // doing the scrollbar compensation might have created text overflow which created more height. redo 10261 scrollerHeight = this.computeScrollerHeight(viewHeight); 10262 this.scroller.setHeight(scrollerHeight); 10263 } 10264 // guarantees the same scrollbar widths 10265 this.scroller.lockOverflow(scrollbarWidths); 10266 } 10267 }; 10268 // given a desired total height of the view, returns what the height of the scroller should be 10269 DayGridView.prototype.computeScrollerHeight = function (viewHeight) { 10270 return viewHeight - 10271 core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller 10272 }; 10273 // Sets the height of just the DayGrid component in this view 10274 DayGridView.prototype.setGridHeight = function (height, isAuto) { 10275 if (this.opt('monthMode')) { 10276 // if auto, make the height of each row the height that it would be if there were 6 weeks 10277 if (isAuto) { 10278 height *= this.dayGrid.rowCnt / 6; 10279 } 10280 core.distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows 10281 } 10282 else { 10283 if (isAuto) { 10284 core.undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding 10285 } 10286 else { 10287 core.distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows 10288 } 10289 } 10290 }; 10291 /* Scroll 10292 ------------------------------------------------------------------------------------------------------------------*/ 10293 DayGridView.prototype.computeDateScroll = function (timeMs) { 10294 return { top: 0 }; 10295 }; 10296 DayGridView.prototype.queryDateScroll = function () { 10297 return { top: this.scroller.getScrollTop() }; 10298 }; 10299 DayGridView.prototype.applyDateScroll = function (scroll) { 10300 if (scroll.top !== undefined) { 10301 this.scroller.setScrollTop(scroll.top); 10302 } 10303 }; 10304 return DayGridView; 10305 }(core.View)); 10306 DayGridView.prototype.dateProfileGeneratorClass = DayGridDateProfileGenerator; 10307 10308 var SimpleDayGrid = /** @class */ (function (_super) { 10309 __extends(SimpleDayGrid, _super); 10310 function SimpleDayGrid(context, dayGrid) { 10311 var _this = _super.call(this, context, dayGrid.el) || this; 10312 _this.slicer = new DayGridSlicer(); 10313 _this.dayGrid = dayGrid; 10314 context.calendar.registerInteractiveComponent(_this, { el: _this.dayGrid.el }); 10315 return _this; 10316 } 10317 SimpleDayGrid.prototype.destroy = function () { 10318 _super.prototype.destroy.call(this); 10319 this.calendar.unregisterInteractiveComponent(this); 10320 }; 10321 SimpleDayGrid.prototype.render = function (props) { 10322 var dayGrid = this.dayGrid; 10323 var dateProfile = props.dateProfile, dayTable = props.dayTable; 10324 dayGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, props.nextDayThreshold, dayGrid, dayTable), { dateProfile: dateProfile, cells: dayTable.cells, isRigid: props.isRigid })); 10325 }; 10326 SimpleDayGrid.prototype.buildPositionCaches = function () { 10327 this.dayGrid.buildPositionCaches(); 10328 }; 10329 SimpleDayGrid.prototype.queryHit = function (positionLeft, positionTop) { 10330 var rawHit = this.dayGrid.positionToHit(positionLeft, positionTop); 10331 if (rawHit) { 10332 return { 10333 component: this.dayGrid, 10334 dateSpan: rawHit.dateSpan, 10335 dayEl: rawHit.dayEl, 10336 rect: { 10337 left: rawHit.relativeRect.left, 10338 right: rawHit.relativeRect.right, 10339 top: rawHit.relativeRect.top, 10340 bottom: rawHit.relativeRect.bottom 10341 }, 10342 layer: 0 10343 }; 10344 } 10345 }; 10346 return SimpleDayGrid; 10347 }(core.DateComponent));
10348 var DayGridSlicer = /** @class */ (function (_super) { 10349 __extends(DayGridSlicer, _super); 10350 function DayGridSlicer() { 10351 return _super !== null && _super.apply(this, arguments) || this; 10352 } 10353 DayGridSlicer.prototype.sliceRange = function (dateRange, dayTable) { 10354 return dayTable.sliceRange(dateRange); 10355 }; 10356 return DayGridSlicer; 10357 }(core.Slicer)); 10358 10359 var DayGridView$1 = /** @class */ (function (_super) { 10360 __extends(DayGridView, _super); 10361 function DayGridView(_context, viewSpec, dateProfileGenerator, parentEl) { 10362 var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this; 10363 _this.buildDayTable = core.memoize(buildDayTable); 10364 if (_this.opt('columnHeader')) { 10365 _this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container')); 10366 } 10367 _this.simpleDayGrid = new SimpleDayGrid(_this.context, _this.dayGrid); 10368 return _this; 10369 } 10370 DayGridView.prototype.destroy = function () { 10371 _super.prototype.destroy.call(this); 10372 if (this.header) { 10373 this.header.destroy(); 10374 } 10375 this.simpleDayGrid.destroy(); 10376 }; 10377 DayGridView.prototype.render = function (props) { 10378 _super.prototype.render.call(this, props); 10379 var dateProfile = this.props.dateProfile; 10380 var dayTable = this.dayTable = 10381 this.buildDayTable(dateProfile, this.dateProfileGenerator); 10382 if (this.header) { 10383 this.header.receiveProps({ 10384 dateProfile: dateProfile, 10385 dates: dayTable.headerDates, 10386 datesRepDistinctDays: dayTable.rowCnt === 1, 10387 renderIntroHtml: this.renderHeadIntroHtml 10388 }); 10389 } 10390 this.simpleDayGrid.receiveProps({ 10391 dateProfile: dateProfile, 10392 dayTable: dayTable, 10393 businessHours: props.businessHours, 10394 dateSelection: props.dateSelection, 10395 eventStore: props.eventStore, 10396 eventUiBases: props.eventUiBases, 10397 eventSelection: props.eventSelection, 10398 eventDrag: props.eventDrag, 10399 eventResize: props.eventResize, 10400 isRigid: this.hasRigidRows(), 10401 nextDayThreshold: this.nextDayThreshold 10402 }); 10403 }; 10404 return DayGridView; 10405 }(DayGridView)); 10406 function buildDayTable(dateProfile, dateProfileGenerator) { 10407 var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator); 10408 return new core.DayTable(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit)); 10409 } 10410 10411 var main = core.createPlugin({ 10412 defaultView: 'dayGridMonth', 10413 views: { 10414 dayGrid: DayGridView$1, 10415 dayGridDay: { 10416 type: 'dayGrid', 10417 duration: { days: 1 } 10418 }, 10419 dayGridWeek: { 10420 type: 'dayGrid', 10421 duration: { weeks: 1 } 10422 }, 10423 dayGridMonth: { 10424 type: 'dayGrid', 10425 duration: { months: 1 }, 10426 monthMode: true, 10427 fixedWeekCount: true 10428 } 10429 } 10430 }); 10431 10432 exports.AbstractDayGridView = DayGridView; 10433 exports.DayBgRow = DayBgRow; 10434 exports.DayGrid = DayGrid; 10435 exports.DayGridSlicer = DayGridSlicer; 10436 exports.DayGridView = DayGridView$1; 10437 exports.SimpleDayGrid = SimpleDayGrid; 10438 exports.buildBasicDayTable = buildDayTable; 10439 exports.default = main; 10440 10441 Object.defineProperty(exports, '__esModule', { value: true }); 10442 10443})); 10444 10445/*! 10446FullCalendar Time Grid Plugin v4.1.0 10447Docs & License: https://fullcalendar.io/ 10448(c) 2019 Adam Shaw 10449*/ 10450(function (global, factory) { 10451 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core'), require('@fullcalendar/daygrid')) : 10452 typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/daygri
10452d'], factory) : 10453 (global = global || self, factory(global.FullCalendarTimeGrid = {}, global.FullCalendar, global.FullCalendarDayGrid)); 10454}(this, function (exports, core, daygrid) { 'use strict'; 10455 10456 /*! ***************************************************************************** 10457 Copyright (c) Microsoft Corporation. All rights reserved. 10458 Licensed under the Apache License, Version 2.0 (the "License"); you may not use 10459 this file except in compliance with the License. You may obtain a copy of the 10460 License at http://www.apache.org/licenses/LICENSE-2.0 10461 10462 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 10463 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 10464 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 10465 MERCHANTABLITY OR NON-INFRINGEMENT. 10466 10467 See the Apache Version 2.0 License for specific language governing permissions 10468 and limitations under the License. 10469 ***************************************************************************** */ 10470 /* global Reflect, Promise */ 10471 10472 var extendStatics = function(d, b) { 10473 extendStatics = Object.setPrototypeOf || 10474 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 10475 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 10476 return extendStatics(d, b); 10477 }; 10478 10479 function __extends(d, b) { 10480 extendStatics(d, b); 10481 function __() { this.constructor = d; } 10482 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 10483 } 10484 10485 var __assign = function() { 10486 __assign = Object.assign || function __assign(t) { 10487 for (var s, i = 1, n = arguments.length; i < n; i++) { 10488 s = arguments[i]; 10489 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 10490 } 10491 return t; 10492 }; 10493 return __assign.apply(this, arguments); 10494 }; 10495 10496 /* 10497 Only handles foreground segs. 10498 Does not own rendering. Use for low-level util methods by TimeGrid. 10499 */ 10500 var TimeGridEventRenderer = /** @class */ (function (_super) { 10501 __extends(TimeGridEventRenderer, _super); 10502 function TimeGridEventRenderer(timeGrid) { 10503 var _this = _super.call(this, timeGrid.context) || this; 10504 _this.timeGrid = timeGrid; 10505 _this.fullTimeFormat = core.createFormatter({ 10506 hour: 'numeric', 10507 minute: '2-digit', 10508 separator: _this.context.options.defaultRangeSeparator 10509 }); 10510 return _this; 10511 } 10512 // Given an array of foreground segments, render a DOM element for each, computes position, 10513 // and attaches to the column inner-container elements. 10514 TimeGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) { 10515 var segsByCol = this.timeGrid.groupSegsByCol(segs); 10516 // order the segs within each column 10517 // TODO: have groupSegsByCol do this? 10518 for (var col = 0; col < segsByCol.length; col++) { 10519 segsByCol[col] = this.sortEventSegs(segsByCol[col]); 10520 } 10521 this.segsByCol = segsByCol; 10522 this.timeGrid.attachSegsByCol(segsByCol, this.timeGrid.fgContainerEls); 10523 }; 10524 TimeGridEventRenderer.prototype.detachSegs = function (segs) { 10525 segs.forEach(function (seg) { 10526 core.removeElement(seg.el); 10527 }); 10528 this.segsByCol = null; 10529 }; 10530 TimeGridEventRenderer.prototype.computeSegSizes = function (allSegs) { 10531 var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol; 10532 var colCnt = timeGrid.colCnt; 10533 timeGrid.computeSegVerticals(allSegs); // horizontals relies on this 10534 if (segsByCol) { 10535 for (var col = 0; col < colCnt; col++) { 10536 this.computeSegHorizontals(segsByCol[col]); // compute horizontal coordinates, z-index's, and reorder the array 10537 } 10538 } 10539 }; 10540 TimeGridEventRenderer.prototype.assignSegSizes = function (allSegs) { 10541 var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol; 10542 var colCnt = timeGrid.colCnt; 10543 timeGrid.assignSegVerticals(allSegs); // horizontals relies on this 10544 if (segsByCol) { 10545 for (var col = 0; col < colCnt; col++) { 10546 this.assignSegCss(segsByCol[col]); 10547 } 10548 } 10549 }; 10550 // Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined 10551 TimeGridEventRenderer.prototype.computeEventTimeFormat = function () { 10552 return { 10553 hour: 'numeric', 10554 minute: '2-digit', 10555 meridiem: false 10556 }; 10557 }; 10558 // Computes a default `displayEventEnd` value if one is not expliclty defined 10559 TimeGridEventRenderer.prototype.computeDisplayEventEnd = function () { 10560 return true; 10561 }; 10562 // Renders the HTML for a single event segment's default rendering 10563 TimeGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) { 10564 var eventRange = seg.eventRange; 10565 var eventDef = eventRange.def; 10566 var eventUi = eventRange.ui; 10567 var allDay = eventDef.allDay; 10568 var isDraggable = eventUi.startEditable; 10569 var isResizableFromStart = seg.isStart && eventUi.durationEditable && this.context.options.eventResizableFromStart; 10570 var isResizableFromEnd = seg.isEnd && eventUi.durationEditable;
10571 var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo); 10572 var skinCss = core.cssToStr(this.getSkinCss(eventUi)); 10573 var timeText; 10574 var fullTimeText; // more verbose time text. for the print stylesheet 10575 var startTimeText; // just the start time text 10576 classes.unshift('fc-time-grid-event'); 10577 // if the event appears to span more than one day... 10578 if (core.isMultiDayRange(eventRange.range)) { 10579 // Don't display time text on segments that run entirely through a day. 10580 // That would appear as midnight-midnight and would look dumb. 10581 // Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am) 10582 if (seg.isStart || seg.isEnd) { 10583 var unzonedStart = seg.start; 10584 var unzonedEnd = seg.end; 10585 timeText = this._getTimeText(unzonedStart, unzonedEnd, allDay); // TODO: give the timezones 10586 fullTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, this.fullTimeFormat); 10587 startTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, null, false); // displayEnd=false 10588 } 10589 } 10590 else { 10591 // Display the normal time text for the *event's* times 10592 timeText = this.getTimeText(eventRange); 10593 fullTimeText = this.getTimeText(eventRange, this.fullTimeFormat); 10594 startTimeText = this.getTimeText(eventRange, null, false); // displayEnd=false 10595 } 10596 return '<a class="' + classes.join(' ') + '"' + 10597 (eventDef.url ? 10598 ' href="' + core.htmlEscape(eventDef.url) + '"' : 10599 '') + 10600 (skinCss ? 10601 ' style="' + skinCss + '"' : 10602 '') + 10603 '>' + 10604 '<div class="fc-content">' + 10605 (timeText ? 10606 '<div class="fc-time"' + 10607 ' data-start="' + core.htmlEscape(startTimeText) + '"' + 10608 ' data-full="' + core.htmlEscape(fullTimeText) + '"' + 10609 '>' + 10610 '<span>' + core.htmlEscape(timeText) + '</span>' + 10611 '</div>' : 10612 '') + 10613 (eventDef.title ? 10614 '<div class="fc-title">' + 10615 core.htmlEscape(eventDef.title) + 10616 '</div>' : 10617 '') + 10618 '</div>' + 10619 /* TODO: write CSS for this 10620 (isResizableFromStart ? 10621 '<div class="fc-resizer fc-start-resizer"></div>' : 10622 '' 10623 ) + 10624 */ 10625 (isResizableFromEnd ? 10626 '<div class="fc-resizer fc-end-resizer"></div>' : 10627 '') + 10628 '</a>'; 10629 }; 10630 // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each. 10631 // Assumed the segs are already ordered. 10632 // NOTE: Also reorders the given array by date! 10633 TimeGridEventRenderer.prototype.computeSegHorizontals = function (segs) { 10634 var levels; 10635 var level0; 10636 var i; 10637 levels = buildSlotSegLevels(segs); 10638 computeForwardSlotSegs(levels); 10639 if ((level0 = levels[0])) { 10640 for (i = 0; i < level0.length; i++) { 10641 computeSlotSegPressures(level0[i]); 10642 } 10643 for (i = 0; i < level0.length; i++) { 10644 this.computeSegForwardBack(level0[i], 0, 0); 10645 } 10646 } 10647 }; 10648 // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range 10649 // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and 10650 // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left. 10651 // 10652 // The segment might be part of a "series", which means consecutive segments with the same pressure 10653 // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of 10654 // segments behind this one in the current series, and `seriesBackwardCoord` is the starting 10655 // coordinate of the first segment in the series. 10656 TimeGridEventRenderer.prototype.computeSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) { 10657 var forwardSegs = seg.forwardSegs; 10658 var i; 10659 if (seg.forwardCoord === undefined) { // not already computed 10660 if (!forwardSegs.length) { 10661 // if there are no forward segments, this segment should butt up against the edge 10662 seg.forwardCoord = 1; 10663 } 10664 else { 10665 // sort highest pressure first 10666 this.sortForwardSegs(forwardSegs); 10667 // this segment's forwardCoord will be calculated from the backwardCoord of the 10668 // highest-pressure forward segment. 10669 this.computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord); 10670 seg.forwardCoord = forwardSegs[0].backwardCoord; 10671 } 10672 // calculate the backwardCoord from the forwardCoord. consider the series 10673 seg.backwardCoord = seg.forwardCoord - 10674 (seg.forwardCoord - seriesBackwardCoord) / // available width for series 10675 (seriesBackwardPressure + 1); // # of segments in the series
10676 // use this segment's coordinates to computed the coordinates of the less-pressurized 10677 // forward segments 10678 for (i = 0; i < forwardSegs.length; i++) { 10679 this.computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord); 10680 } 10681 } 10682 }; 10683 TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) { 10684 var objs = forwardSegs.map(buildTimeGridSegCompareObj); 10685 var specs = [ 10686 // put higher-pressure first 10687 { field: 'forwardPressure', order: -1 }, 10688 // put segments that are closer to initial edge first (and favor ones with no coords yet) 10689 { field: 'backwardCoord', order: 1 } 10690 ].concat(this.context.view.eventOrderSpecs); 10691 objs.sort(function (obj0, obj1) { 10692 return core.compareByFieldSpecs(obj0, obj1, specs); 10693 }); 10694 return objs.map(function (c) { 10695 return c._seg; 10696 }); 10697 }; 10698 // Given foreground event segments that have already had their position coordinates computed, 10699 // assigns position-related CSS values to their elements. 10700 TimeGridEventRenderer.prototype.assignSegCss = function (segs) { 10701 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 10702 var seg = segs_1[_i]; 10703 core.applyStyle(seg.el, this.generateSegCss(seg)); 10704 if (seg.level > 0) { 10705 seg.el.classList.add('fc-time-grid-event-inset'); 10706 } 10707 // if the event is short that the title will be cut off, 10708 // attach a className that condenses the title into the time area. 10709 if (seg.eventRange.def.title && seg.bottom - seg.top < 30) { 10710 seg.el.classList.add('fc-short'); // TODO: "condensed" is a better name 10711 } 10712 } 10713 }; 10714 // Generates an object with CSS properties/values that should be applied to an event segment element. 10715 // Contains important positioning-related properties that should be applied to any event element, customized or not. 10716 TimeGridEventRenderer.prototype.generateSegCss = function (seg) { 10717 var shouldOverlap = this.context.options.slotEventOverlap; 10718 var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point 10719 var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point 10720 var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first 10721 var isRtl = this.timeGrid.isRtl; 10722 var left; // amount of space from left edge, a fraction of the total width 10723 var right; // amount of space from right edge, a fraction of the total width 10724 if (shouldOverlap) { 10725 // double the width, but don't go beyond the maximum forward coordinate (1.0) 10726 forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2); 10727 } 10728 if (isRtl) { 10729 left = 1 - forwardCoord; 10730 right = backwardCoord; 10731 } 10732 else { 10733 left = backwardCoord; 10734 right = 1 - forwardCoord; 10735 } 10736 props.zIndex = seg.level + 1; // convert from 0-base to 1-based 10737 props.left = left * 100 + '%'; 10738 props.right = right * 100 + '%'; 10739 if (shouldOverlap && seg.forwardPressure) { 10740 // add padding to the edge so that forward stacked events don't cover the resizer's icon 10741 props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width 10742 } 10743 return props; 10744 }; 10745 return TimeGridEventRenderer; 10746 }(core.FgEventRenderer)); 10747 // Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is 10748 // left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date. 10749 function buildSlotSegLevels(segs) { 10750 var levels = []; 10751 var i; 10752 var seg; 10753 var j; 10754 for (i = 0; i < segs.length; i++) { 10755 seg = segs[i]; 10756 // go through all the levels and stop on the first level where there are no collisions 10757 for (j = 0; j < levels.length; j++) { 10758 if (!computeSlotSegCollisions(seg, levels[j]).length) { 10759 break; 10760 } 10761 } 10762 seg.level = j; 10763 (levels[j] || (levels[j] = [])).push(seg); 10764 } 10765 return levels; 10766 } 10767 // For every segment, figure out the other segments that are in subsequent 10768 // levels that also occupy the same vertical space. Accumulate in seg.forwardSegs 10769 function computeForwardSlotSegs(levels) { 10770 var i; 10771 var level; 10772 var j; 10773 var seg; 10774 var k; 10775 for (i = 0; i < levels.length; i++) { 10776 level = levels[i]; 10777 for (j = 0; j < level.length; j++) { 10778 seg = level[j]; 10779 seg.forwardSegs = []; 10780 for (k = i + 1; k < levels.length; k++) { 10781 computeSlotSegCollisions(seg, levels[k], seg.forwardSegs); 10782 } 10783 } 10784 } 10785 } 10786 // Figure out which path forward (via seg.forwardSegs) results in the longest path until 10787 // the furthest edge is reached. The number of segments in this path will be seg.forwardPressure 10788 function computeSlotSegPressures(seg) { 10789 var forwardSegs = seg.forwardSegs; 10790 var forwardPressure = 0; 10791 var i; 10792 var forwardSeg; 10793 if (seg.forwardPressure === undefined) { // not already computed 10794 for (i = 0; i < forwardSegs.length; i++) { 10795 forwardSeg = forwardSegs[i]; 10796 // figure out the child's maximum forward path 10797 computeSlotSegPressures(forwardSeg); 10798 // either use the existing maximum, or use the child's forward pressure 10799 // plus one (for the forwardSeg itself) 10800 forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure); 10801 } 10802 seg.forwardPressure = forwardPressure; 10803 } 10804 } 10805 // Find all the segments in `otherSegs` that vertically collide with `seg`. 10806 // Append into an optionally-supplied `results` array and return. 10807 function computeSlotSegCollisions(seg, otherSegs, results) { 10808 if (results === void 0) { results = []; } 10809 for (var i = 0; i < otherSegs.length; i++) { 10810 if (isSlotSegCollision(seg, otherSegs[i])) { 10811 results.push(otherSegs[i]); 10812 } 10813 } 10814 return results; 10815 } 10816 // Do these segments occupy the same vertical space? 10817 function isSlotSegCollision(seg1, seg2) { 10818 return seg1.bottom > seg2.top && seg1.top < seg2.bottom; 10819 } 10820 function buildTimeGridSegCompareObj(seg) { 10821 var obj = core.buildSegCompareObj(seg); 10822 obj.forwardPressure = seg.forwardPressure; 10823 obj.backwardCoord = seg.backwardCoord; 10824 return obj; 10825 } 10826 10827 var TimeGridMirrorRenderer = /** @class */ (function (_super) { 10828 __extends(TimeGridMirrorRenderer, _super); 10829 function TimeGridMirrorRenderer() { 10830 return _super !== null && _super.apply(this, arguments) || this; 10831 } 10832 TimeGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) { 10833 this.segsByCol = this.timeGrid.groupSegsByCol(segs); 10834 this.timeGrid.attachSegsByCol(this.segsByCol, this.timeGrid.mirrorContainerEls); 10835 this.sourceSeg = mirrorInfo.sourceSeg; 10836 }; 10837 TimeGridMirrorRenderer.prototype.generateSegCss = function (seg) { 10838 var props = _super.prototype.generateSegCss.call(this, seg); 10839 var sourceSeg = this.sourceSeg; 10840 if (sourceSeg && sourceSeg.col === seg.col) { 10841 var sourceSegProps = _super.prototype.generateSegCss.call(this, sourceSeg); 10842 props.left = sourceSegProps.left; 10843 props.right = sourceSegProps.right; 10844 props.marginLeft = sourceSegProps.marginLeft; 10845 props.marginRight = sourceSegProps.marginRight; 10846 } 10847 return props; 10848 }; 10849 return TimeGridMirrorRenderer; 10850 }(TimeGridEventRenderer)); 10851 10852 var TimeGridFillRenderer = /** @class */ (function (_super) { 10853 __extends(TimeGridFillRenderer, _super); 10854 function TimeGridFillRenderer(timeGrid) { 10855 var _this = _super.call(this, timeGrid.context) || this; 10856 _this.timeGrid = timeGrid; 10857 return _this; 10858 } 10859 TimeGridFillRenderer.prototype.attachSegs = function (type, segs) { 10860 var timeGrid = this.timeGrid; 10861 var containerEls; 10862 // TODO: more efficient lookup 10863 if (type === 'bgEvent') { 10864 containerEls = timeGrid.bgContainerEls; 10865 } 10866 else if (type === 'businessHours') { 10867 containerEls = timeGrid.businessContainerEls; 10868 } 10869 else if (type === 'highlight') { 10870 containerEls = timeGrid.highlightContainerEls; 10871 } 10872 timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls); 10873 return segs.map(function (seg) { 10874 return seg.el; 10875 }); 10876 }; 10877 TimeGridFillRenderer.prototype.computeSegSizes = function (segs) { 10878 this.timeGrid.computeSegVerticals(segs); 10879 }; 10880 TimeGridFillRenderer.prototype.assignSegSizes = function (segs) { 10881 this.timeGrid.assignSegVerticals(segs); 10882 }; 10883 return TimeGridFillRenderer; 10884 }(core.FillRenderer)); 10885 10886 /* A component that renders one or more columns of vertical time slots 10887 ----------------------------------------------------------------------------------------------------------------------*/ 10888 // potential nice values for the slot-duration and interval-duration 10889 // from largest to smallest 10890 var AGENDA_STOCK_SUB_DURATIONS = [ 10891 { hours: 1 }, 10892 { minutes: 30 }, 10893 { minutes: 15 }, 10894 { seconds: 30 }, 10895 { seconds: 15 } 10896 ]; 10897 var TimeGrid = /** @class */ (function (_super) { 10898 __extends(TimeGrid, _super); 10899 function TimeGrid(context, el, renderProps) { 10900 var _this = _super.call(this, context, el) || this; 10901 _this.isSlatSizesDirty = false;
10902 _this.isColSizesDirty = false; 10903 _this.renderSlats = core.memoizeRendering(_this._renderSlats); 10904 var eventRenderer = _this.eventRenderer = new TimeGridEventRenderer(_this); 10905 var fillRenderer = _this.fillRenderer = new TimeGridFillRenderer(_this); 10906 _this.mirrorRenderer = new TimeGridMirrorRenderer(_this); 10907 var renderColumns = _this.renderColumns = core.memoizeRendering(_this._renderColumns, _this._unrenderColumns); 10908 _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderColumns]); 10909 _this.renderDateSelection = core.memoizeRendering(_this._renderDateSelection, _this._unrenderDateSelection, [renderColumns]); 10910 _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderColumns]); 10911 _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderColumns]); 10912 _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]); 10913 _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderColumns]); 10914 _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderColumns]); 10915 _this.processOptions(); 10916 el.innerHTML = 10917 '<div class="fc-bg"></div>' + 10918 '<div class="fc-slats"></div>' + 10919 '<hr class="fc-divider ' + _this.theme.getClass('widgetHeader') + '" style="display:none" />'; 10920 _this.rootBgContainerEl = el.querySelector('.fc-bg'); 10921 _this.slatContainerEl = el.querySelector('.fc-slats'); 10922 _this.bottomRuleEl = el.querySelector('.fc-divider'); 10923 _this.renderProps = renderProps; 10924 return _this; 10925 } 10926 /* Options 10927 ------------------------------------------------------------------------------------------------------------------*/ 10928 // Parses various options into properties of this object 10929 TimeGrid.prototype.processOptions = function () { 10930 var slotDuration = this.opt('slotDuration'); 10931 var snapDuration = this.opt('snapDuration'); 10932 var snapsPerSlot; 10933 var input; 10934 slotDuration = core.createDuration(slotDuration); 10935 snapDuration = snapDuration ? core.createDuration(snapDuration) : slotDuration; 10936 snapsPerSlot = core.wholeDivideDurations(slotDuration, snapDuration); 10937 if (snapsPerSlot === null) { 10938 snapDuration = slotDuration; 10939 snapsPerSlot = 1; 10940 // TODO: say warning? 10941 } 10942 this.slotDuration = slotDuration; 10943 this.snapDuration = snapDuration; 10944 this.snapsPerSlot = snapsPerSlot; 10945 // might be an array value (for TimelineView). 10946 // if so, getting the most granular entry (the last one probably). 10947 input = this.opt('slotLabelFormat'); 10948 if (Array.isArray(input)) { 10949 input = input[input.length - 1]; 10950 } 10951 this.labelFormat = core.createFormatter(input || { 10952 hour: 'numeric', 10953 minute: '2-digit', 10954 omitZeroMinute: true, 10955 meridiem: 'short' 10956 }); 10957 input = this.opt('slotLabelInterval'); 10958 this.labelInterval = input ? 10959 core.createDuration(input) : 10960 this.computeLabelInterval(slotDuration); 10961 }; 10962 // Computes an automatic value for slotLabelInterval 10963 TimeGrid.prototype.computeLabelInterval = function (slotDuration) { 10964 var i; 10965 var labelInterval; 10966 var slotsPerLabel; 10967 // find the smallest stock label interval that results in more than one slots-per-label 10968 for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) { 10969 labelInterval = core.createDuration(AGENDA_STOCK_SUB_DURATIONS[i]);
10970 slotsPerLabel = core.wholeDivideDurations(labelInterval, slotDuration); 10971 if (slotsPerLabel !== null && slotsPerLabel > 1) { 10972 return labelInterval; 10973 } 10974 } 10975 return slotDuration; // fall back 10976 }; 10977 /* Rendering 10978 ------------------------------------------------------------------------------------------------------------------*/ 10979 TimeGrid.prototype.render = function (props) { 10980 var cells = props.cells; 10981 this.colCnt = cells.length; 10982 this.renderSlats(props.dateProfile); 10983 this.renderColumns(props.cells, props.dateProfile); 10984 this.renderBusinessHours(props.businessHourSegs); 10985 this.renderDateSelection(props.dateSelectionSegs); 10986 this.renderFgEvents(props.fgEventSegs); 10987 this.renderBgEvents(props.bgEventSegs); 10988 this.renderEventSelection(props.eventSelection); 10989 this.renderEventDrag(props.eventDrag); 10990 this.renderEventResize(props.eventResize); 10991 }; 10992 TimeGrid.prototype.destroy = function () { 10993 _super.prototype.destroy.call(this); 10994 // should unrender everything else too 10995 this.renderSlats.unrender(); 10996 this.renderColumns.unrender(); 10997 }; 10998 TimeGrid.prototype.updateSize = function (isResize) { 10999 var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer; 11000 if (isResize || this.isSlatSizesDirty) { 11001 this.buildSlatPositions(); 11002 this.isSlatSizesDirty = false; 11003 } 11004 if (isResize || this.isColSizesDirty) { 11005 this.buildColPositions(); 11006 this.isColSizesDirty = false; 11007 } 11008 fillRenderer.computeSizes(isResize); 11009 eventRenderer.computeSizes(isResize); 11010 mirrorRenderer.computeSizes(isResize); 11011 fillRenderer.assignSizes(isResize); 11012 eventRenderer.assignSizes(isResize); 11013 mirrorRenderer.assignSizes(isResize); 11014 }; 11015 TimeGrid.prototype._renderSlats = function (dateProfile) { 11016 var theme = this.theme; 11017 this.slatContainerEl.innerHTML = 11018 '<table class="' + theme.getClass('tableGrid') + '">' + 11019 this.renderSlatRowHtml(dateProfile) + 11020 '</table>'; 11021 this.slatEls = core.findElements(this.slatContainerEl, 'tr'); 11022 this.slatPositions = new core.PositionCache(this.el, this.slatEls, false, true // vertical 11023 ); 11024 this.isSlatSizesDirty = true; 11025 }; 11026 // Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL. 11027 TimeGrid.prototype.renderSlatRowHtml = function (dateProfile) { 11028 var _a = this, dateEnv = _a.dateEnv, theme = _a.theme, isRtl = _a.isRtl; 11029 var html = ''; 11030 var dayStart = core.startOfDay(dateProfile.renderRange.start); 11031 var slotTime = dateProfile.minTime; 11032 var slotIterator = core.createDuration(0); 11033 var slotDate; // will be on the view's first day, but we only care about its time 11034 var isLabeled; 11035 var axisHtml; 11036 // Calculate the time for each slot 11037 while (core.asRoughMs(slotTime) < core.asRoughMs(dateProfile.maxTime)) { 11038 slotDate = dateEnv.add(dayStart, slotTime); 11039 isLabeled = core.wholeDivideDurations(slotIterator, this.labelInterval) !== null; 11040 axisHtml = 11041 '<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '">' + 11042 (isLabeled ? 11043 '<span>' + // for matchCellWidths 11044 core.htmlEscape(dateEnv.format(slotDate, this.labelFormat)) + 11045 '</span>' : 11046 '') + 11047 '</td>'; 11048 html += 11049 '<tr data-time="' + core.formatIsoTimeString(slotDate) + '"' + 11050 (isLabeled ? '' : ' class="fc-minor"') + 11051 '>' + 11052 (!isRtl ? axisHtml : '') + 11053 '<td class="' + theme.getClass('widgetContent') + '"></td>' + 11054 (isRtl ? axisHtml : '') + 11055 '</tr>'; 11056 slotTime = core.addDurations(slotTime, this.slotDuration); 11057 slotIterator = core.addDurations(slotIterator, this.slotDuration); 11058 } 11059 return html; 11060 }; 11061 TimeGrid.prototype._renderColumns = function (cells, dateProfile) { 11062 var _a = this, theme = _a.theme, dateEnv = _a.dateEnv, view = _a.view; 11063 var bgRow = new daygrid.DayBgRow(this.context);
11064 this.rootBgContainerEl.innerHTML = 11065 '<table class="' + theme.getClass('tableGrid') + '">' + 11066 bgRow.renderHtml({ 11067 cells: cells, 11068 dateProfile: dateProfile, 11069 renderIntroHtml: this.renderProps.renderBgIntroHtml 11070 }) + 11071 '</table>'; 11072 this.colEls = core.findElements(this.el, '.fc-day, .fc-disabled-day'); 11073 for (var col = 0; col < this.colCnt; col++) { 11074 this.publiclyTrigger('dayRender', [ 11075 { 11076 date: dateEnv.toDate(cells[col].date), 11077 el: this.colEls[col], 11078 view: view 11079 } 11080 ]); 11081 } 11082 if (this.isRtl) { 11083 this.colEls.reverse(); 11084 } 11085 this.colPositions = new core.PositionCache(this.el, this.colEls, true, // horizontal 11086 false); 11087 this.renderContentSkeleton(); 11088 this.isColSizesDirty = true; 11089 }; 11090 TimeGrid.prototype._unrenderColumns = function () { 11091 this.unrenderContentSkeleton(); 11092 }; 11093 /* Content Skeleton 11094 ------------------------------------------------------------------------------------------------------------------*/ 11095 // Renders the DOM that the view's content will live in 11096 TimeGrid.prototype.renderContentSkeleton = function () { 11097 var parts = []; 11098 var skeletonEl; 11099 parts.push(this.renderProps.renderIntroHtml()); 11100 for (var i = 0; i < this.colCnt; i++) { 11101 parts.push('<td>' + 11102 '<div class="fc-content-col">' + 11103 '<div class="fc-event-container fc-mirror-container"></div>' + 11104 '<div class="fc-event-container"></div>' + 11105 '<div class="fc-highlight-container"></div>' + 11106 '<div class="fc-bgevent-container"></div>' + 11107 '<div class="fc-business-container"></div>' + 11108 '</div>' + 11109 '</td>'); 11110 } 11111 if (this.isRtl) { 11112 parts.reverse(); 11113 } 11114 skeletonEl = this.contentSkeletonEl = core.htmlToElement('<div class="fc-content-skeleton">' + 11115 '<table>' + 11116 '<tr>' + parts.join('') + '</tr>' + 11117 '</table>' + 11118 '</div>'); 11119 this.colContainerEls = core.findElements(skeletonEl, '.fc-content-col'); 11120 this.mirrorContainerEls = core.findElements(skeletonEl, '.fc-mirror-container'); 11121 this.fgContainerEls = core.findElements(skeletonEl, '.fc-event-container:not(.fc-mirror-container)'); 11122 this.bgContainerEls = core.findElements(skeletonEl, '.fc-bgevent-container'); 11123 this.highlightContainerEls = core.findElements(skeletonEl, '.fc-highlight-container'); 11124 this.businessContainerEls = core.findElements(skeletonEl, '.fc-business-container'); 11125 if (this.isRtl) { 11126 this.colContainerEls.reverse(); 11127 this.mirrorContainerEls.reverse(); 11128 this.fgContainerEls.reverse(); 11129 this.bgContainerEls.reverse(); 11130 this.highlightContainerEls.reverse(); 11131 this.businessContainerEls.reverse(); 11132 } 11133 this.el.appendChild(skeletonEl); 11134 }; 11135 TimeGrid.prototype.unrenderContentSkeleton = function () { 11136 core.removeElement(this.contentSkeletonEl); 11137 }; 11138 // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col 11139 TimeGrid.prototype.groupSegsByCol = function (segs) { 11140 var segsByCol = []; 11141 var i; 11142 for (i = 0; i < this.colCnt; i++) { 11143 segsByCol.push([]); 11144 } 11145 for (i = 0; i < segs.length; i++) { 11146 segsByCol[segs[i].col].push(segs[i]); 11147 } 11148 return segsByCol; 11149 }; 11150 // Given segments grouped by column, insert the segments' elements into a parallel array of container 11151 // elements, each living within a column. 11152 TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) { 11153 var col; 11154 var segs; 11155 var i; 11156 for (col = 0; col < this.colCnt; col++) { // iterate each column grouping 11157 segs = segsByCol[col]; 11158 for (i = 0; i < segs.length; i++) { 11159 containerEls[col].appendChild(segs[i].el); 11160 } 11161 } 11162 }; 11163 /* Now Indicator 11164 ------------------------------------------------------------------------------------------------------------------*/ 11165 TimeGrid.prototype.getNowIndicatorUnit = function () { 11166 return 'minute'; // will refresh on the minute 11167 }; 11168 TimeGrid.prototype.renderNowIndicator = function (segs, date) { 11169 // HACK: if date columns not ready for some reason (scheduler) 11170 if (!this.colContainerEls) { 11171 return; 11172 } 11173 var top = this.computeDateTop(date); 11174 var nodes = []; 11175 var i; 11176 // render lines within the columns 11177 for (i = 0; i < segs.length; i++) { 11178 var lineEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-line' }); 11179 lineEl.style.top = top + 'px'; 11180 this.colContainerEls[segs[i].col].appendChild(lineEl); 11181 nodes.push(lineEl); 11182 } 11183 // render an arrow over the axis 11184 if (segs.length > 0) { // is the current time in view? 11185 var arrowEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' }); 11186 arrowEl.style.top = top + 'px'; 11187 this.contentSkeletonEl.appendChild(arrowEl); 11188 nodes.push(arrowEl); 11189 } 11190 this.nowIndicatorEls = nodes; 11191 }; 11192 TimeGrid.prototype.unrenderNowIndicator = function () { 11193 if (this.nowIndicatorEls) {
11194 this.nowIndicatorEls.forEach(core.removeElement); 11195 this.nowIndicatorEls = null; 11196 } 11197 }; 11198 /* Coordinates 11199 ------------------------------------------------------------------------------------------------------------------*/ 11200 TimeGrid.prototype.getTotalSlatHeight = function () { 11201 return this.slatContainerEl.offsetHeight; 11202 }; 11203 // Computes the top coordinate, relative to the bounds of the grid, of the given date. 11204 // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight. 11205 TimeGrid.prototype.computeDateTop = function (when, startOfDayDate) { 11206 if (!startOfDayDate) { 11207 startOfDayDate = core.startOfDay(when); 11208 } 11209 return this.computeTimeTop(when.valueOf() - startOfDayDate.valueOf()); 11210 }; 11211 // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration). 11212 TimeGrid.prototype.computeTimeTop = function (timeMs) { 11213 var len = this.slatEls.length; 11214 var dateProfile = this.props.dateProfile; 11215 var slatCoverage = (timeMs - core.asRoughMs(dateProfile.minTime)) / core.asRoughMs(this.slotDuration); // floating-point value of # of slots covered 11216 var slatIndex; 11217 var slatRemainder; 11218 // compute a floating-point number for how many slats should be progressed through. 11219 // from 0 to number of slats (inclusive) 11220 // constrained because minTime/maxTime might be customized. 11221 slatCoverage = Math.max(0, slatCoverage); 11222 slatCoverage = Math.min(len, slatCoverage); 11223 // an integer index of the furthest whole slat 11224 // from 0 to number slats (*exclusive*, so len-1) 11225 slatIndex = Math.floor(slatCoverage); 11226 slatIndex = Math.min(slatIndex, len - 1); 11227 // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition. 11228 // could be 1.0 if slatCoverage is covering *all* the slots 11229 slatRemainder = slatCoverage - slatIndex; 11230 return this.slatPositions.tops[slatIndex] + 11231 this.slatPositions.getHeight(slatIndex) * slatRemainder; 11232 }; 11233 // For each segment in an array, computes and assigns its top and bottom properties 11234 TimeGrid.prototype.computeSegVerticals = function (segs) { 11235 var eventMinHeight = this.opt('timeGridEventMinHeight'); 11236 var i; 11237 var seg; 11238 var dayDate; 11239 for (i = 0; i < segs.length; i++) { 11240 seg = segs[i]; 11241 dayDate = this.props.cells[seg.col].date; 11242 seg.top = this.computeDateTop(seg.start, dayDate); 11243 seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.end, dayDate)); 11244 } 11245 }; 11246 // Given segments that already have their top/bottom properties computed, applies those values to 11247 // the segments' elements. 11248 TimeGrid.prototype.assignSegVerticals = function (segs) { 11249 var i; 11250 var seg; 11251 for (i = 0; i < segs.length; i++) { 11252 seg = segs[i]; 11253 core.applyStyle(seg.el, this.generateSegVerticalCss(seg)); 11254 } 11255 }; 11256 // Generates an object with CSS properties for the top/bottom coordinates of a segment element 11257 TimeGrid.prototype.generateSegVerticalCss = function (seg) { 11258 return { 11259 top: seg.top, 11260 bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container 11261 }; 11262 }; 11263 /* Sizing 11264 ------------------------------------------------------------------------------------------------------------------*/ 11265 TimeGrid.prototype.buildPositionCaches = function () { 11266 this.buildColPositions(); 11267 this.buildSlatPositions(); 11268 }; 11269 TimeGrid.prototype.buildColPositions = function () { 11270 this.colPositions.build(); 11271 }; 11272 TimeGrid.prototype.buildSlatPositions = function () { 11273 this.slatPositions.build(); 11274 }; 11275 /* Hit System 11276 ------------------------------------------------------------------------------------------------------------------*/ 11277 TimeGrid.prototype.positionToHit = function (positionLeft, positionTop) { 11278 var _a = this, dateEnv = _a.dateEnv, snapsPerSlot = _a.snapsPerSlot, slatPositions = _a.slatPositions, colPositions = _a.colPositions; 11279 var colIndex = colPositions.leftToIndex(positionLeft); 11280 var slatIndex = slatPositions.topToIndex(positionTop); 11281 if (colIndex != null && slatIndex != null) { 11282 var slatTop = slatPositions.tops[slatIndex]; 11283 var slatHeight = slatPositions.getHeight(slatIndex); 11284 var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1 11285 var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat 11286 var snapIndex = slatIndex * snapsPerSlot + localSnapIndex; 11287 var dayDate = this.props.cells[colIndex].date; 11288 var time = core.addDurations(this.props.dateProfile.minTime, core.multiplyDuration(this.snapDuration, snapIndex)); 11289 var start = dateEnv.add(dayDate, time); 11290 var end = dateEnv.add(start, this.snapDuration); 11291 return { 11292 col: colIndex, 11293 dateSpan: { 11294 range: { start: start, end: end }, 11295 allDay: false 11296 }, 11297 dayEl: this.colEls[colIndex], 11298 relativeRect: { 11299 left: colPositions.lefts[colIndex], 11300 right: colPositions.rights[colIndex], 11301 top: slatTop, 11302 bottom: slatTop + slatHeight 11303 } 11304 }; 11305 } 11306 }; 11307 /* Event Drag Visualization 11308 ------------------------------------------------------------------------------------------------------------------*/ 11309 TimeGrid.prototype._renderEventDrag = function (state) { 11310 if (state) { 11311 this.eventRenderer.hideByHash(state.affectedInstances); 11312 if (state.isEvent) { 11313 this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); 11314 } 11315 else { 11316 this.fillRenderer.renderSegs('highlight', state.segs); 11317 } 11318 } 11319 }; 11320 TimeGrid.prototype._unrenderEventDrag = function (state) { 11321 if (state) { 11322 this.eventRenderer.showByHash(state.affectedInstances); 11323 this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg }); 11324 this.fillRenderer.unrender('highlight'); 11325 } 11326 }; 11327 /* Event Resize Visualization 11328 ------------------------------------------------------------------------------------------------------------------*/ 11329 TimeGrid.prototype._renderEventResize = function (state) { 11330 if (state) { 11331 this.eventRenderer.hideByHash(state.affectedInstances); 11332 this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); 11333 } 11334 }; 11335 TimeGrid.prototype._unrenderEventResize = function (state) { 11336 if (state) { 11337 this.eventRenderer.showByHash(state.affectedInstances); 11338 this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg }); 11339 } 11340 }; 11341 /* Selection 11342 ------------------------------------------------------------------------------------------------------------------*/ 11343 // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight. 11344 TimeGrid.prototype._renderDateSelection = function (segs) { 11345 if (segs) { 11346 if (this.opt('selectMirror')) { 11347 this.mirrorRenderer.renderSegs(segs, { isSelecting: true }); 11348 } 11349 else { 11350 this.fillRenderer.renderSegs('highlight', segs); 11351 } 11352 } 11353 }; 11354 TimeGrid.prototype._unrenderDateSelection = function (segs) { 11355 this.mirrorRenderer.unrender(segs, { isSelecting: true }); 11356 this.fillRenderer.unrender('highlight'); 11357 }; 11358 return TimeGrid; 11359 }(core.DateComponent)); 11360 11361 var AllDaySplitter = /** @class */ (function (_super) { 11362 __extends(AllDaySplitter, _super); 11363 function AllDaySplitter() { 11364 return _super !== null && _super.apply(this, arguments) || this; 11365 } 11366 AllDaySplitter.prototype.getKeyInfo = function () { 11367 return { 11368 allDay: {}, 11369 timed: {} 11370 }; 11371 }; 11372 AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) { 11373 if (dateSpan.allDay) { 11374 return ['allDay']; 11375 } 11376 else {
11377 return ['timed']; 11378 } 11379 }; 11380 AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) { 11381 if (!eventDef.allDay) { 11382 return ['timed']; 11383 } 11384 else if (core.hasBgRendering(eventDef)) { 11385 return ['timed', 'allDay']; 11386 } 11387 else { 11388 return ['allDay']; 11389 } 11390 }; 11391 return AllDaySplitter; 11392 }(core.Splitter)); 11393 11394 var TIMEGRID_ALL_DAY_EVENT_LIMIT = 5; 11395 var WEEK_HEADER_FORMAT = core.createFormatter({ week: 'short' }); 11396 /* An abstract class for all timegrid-related views. Displays one more columns with time slots running vertically. 11397 ----------------------------------------------------------------------------------------------------------------------*/ 11398 // Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on). 11399 // Responsible for managing width/height. 11400 var TimeGridView = /** @class */ (function (_super) { 11401 __extends(TimeGridView, _super); 11402 function TimeGridView(context, viewSpec, dateProfileGenerator, parentEl) { 11403 var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; 11404 _this.splitter = new AllDaySplitter(); 11405 /* Header Render Methods 11406 ------------------------------------------------------------------------------------------------------------------*/ 11407 // Generates the HTML that will go before the day-of week header cells 11408 _this.renderHeadIntroHtml = function () { 11409 var _a = _this, theme = _a.theme, dateEnv = _a.dateEnv; 11410 var range = _this.props.dateProfile.renderRange; 11411 var dayCnt = core.diffDays(range.start, range.end); 11412 var weekText; 11413 if (_this.opt('weekNumbers')) { 11414 weekText = dateEnv.format(range.start, WEEK_HEADER_FORMAT); 11415 return '' + 11416 '<th class="fc-axis fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '>' + 11417 core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths 11418 _this, { date: range.start, type: 'week', forceOff: dayCnt > 1 }, core.htmlEscape(weekText) // inner HTML 11419 ) + 11420 '</th>'; 11421 } 11422 else { 11423 return '<th class="fc-axis ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '></th>'; 11424 } 11425 }; 11426 /* Time Grid Render Methods 11427 ------------------------------------------------------------------------------------------------------------------*/ 11428 // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column. 11429 _this.renderTimeGridBgIntroHtml = function () { 11430 var theme = _this.theme; 11431 return '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '></td>'; 11432 }; 11433 // Generates the HTML that goes before all other types of cells. 11434 // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid. 11435 _this.renderTimeGridIntroHtml = function () { 11436 return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>'; 11437 }; 11438 /* Day Grid Render Methods 11439 ------------------------------------------------------------------------------------------------------------------*/ 11440 // Generates the HTML that goes before the all-day cells 11441 _this.renderDayGridBgIntroHtml = function () { 11442 var theme = _this.theme; 11443 return '' + 11444 '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '>' + 11445 '<span>' + // needed for matchCellWidths 11446 core.getAllDayHtml(_this) + 11447 '</span>' + 11448 '</td>'; 11449 }; 11450 // Generates the HTML that goes before all other types of cells. 11451 // Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid. 11452 _this.renderDayGridIntroHtml = function () { 11453 return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>'; 11454 }; 11455 _this.el.classList.add('fc-timeGrid-view'); 11456 _this.el.innerHTML = _this.renderSkeletonHtml();
11457 _this.scroller = new core.ScrollComponent('hidden', // overflow x 11458 'auto' // overflow y 11459 ); 11460 var timeGridWrapEl = _this.scroller.el; 11461 _this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl); 11462 timeGridWrapEl.classList.add('fc-time-grid-container'); 11463 var timeGridEl = core.createElement('div', { className: 'fc-time-grid' }); 11464 timeGridWrapEl.appendChild(timeGridEl); 11465 _this.timeGrid = new TimeGrid(_this.context, timeGridEl, { 11466 renderBgIntroHtml: _this.renderTimeGridBgIntroHtml, 11467 renderIntroHtml: _this.renderTimeGridIntroHtml 11468 }); 11469 if (_this.opt('allDaySlot')) { // should we display the "all-day" area? 11470 _this.dayGrid = new daygrid.DayGrid(// the all-day subcomponent of this view 11471 _this.context, _this.el.querySelector('.fc-day-grid'), { 11472 renderNumberIntroHtml: _this.renderDayGridIntroHtml, 11473 renderBgIntroHtml: _this.renderDayGridBgIntroHtml, 11474 renderIntroHtml: _this.renderDayGridIntroHtml, 11475 colWeekNumbersVisible: false, 11476 cellWeekNumbersVisible: false 11477 }); 11478 // have the day-grid extend it's coordinate area over the <hr> dividing the two grids 11479 _this.dayGrid.bottomCoordPadding = _this.el.querySelector('.fc-divider').offsetHeight; 11480 } 11481 return _this; 11482 } 11483 TimeGridView.prototype.destroy = function () { 11484 _super.prototype.destroy.call(this); 11485 this.timeGrid.destroy(); 11486 if (this.dayGrid) { 11487 this.dayGrid.destroy(); 11488 } 11489 this.scroller.destroy(); 11490 }; 11491 /* Rendering 11492 ------------------------------------------------------------------------------------------------------------------*/ 11493 // Builds the HTML skeleton for the view. 11494 // The day-grid and time-grid components will render inside containers defined by this HTML. 11495 TimeGridView.prototype.renderSkeletonHtml = function () { 11496 var theme = this.theme; 11497 return '' + 11498 '<table class="' + theme.getClass('tableGrid') + '">' + 11499 (this.opt('columnHeader') ? 11500 '<thead class="fc-head">' + 11501 '<tr>' + 11502 '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"> </td>' + 11503 '</tr>' + 11504 '</thead>' : 11505 '') + 11506 '<tbody class="fc-body">' + 11507 '<tr>' + 11508 '<td class="' + theme.getClass('widgetContent') + '">' + 11509 (this.opt('allDaySlot') ? 11510 '<div class="fc-day-grid"></div>' + 11511 '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" />' : 11512 '') + 11513 '</td>' + 11514 '</tr>' + 11515 '</tbody>' + 11516 '</table>'; 11517 }; 11518 /* Now Indicator 11519 ------------------------------------------------------------------------------------------------------------------*/ 11520 TimeGridView.prototype.getNowIndicatorUnit = function () { 11521 return this.timeGrid.getNowIndicatorUnit(); 11522 }; 11523 // subclasses should implement 11524 // renderNowIndicator(date: DateMarker) { 11525 // } 11526 TimeGridView.prototype.unrenderNowIndicator = function () { 11527 this.timeGrid.unrenderNowIndicator(); 11528 }; 11529 /* Dimensions 11530 ------------------------------------------------------------------------------------------------------------------*/ 11531 TimeGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) { 11532 _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first 11533 this.timeGrid.updateSize(isResize); 11534 if (this.dayGrid) { 11535 this.dayGrid.updateSize(isResize); 11536 } 11537 }; 11538 // Adjusts the vertical dimensions of the view to the specified values 11539 TimeGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { 11540 var _this = this; 11541 var eventLimit; 11542 var scrollerHeight; 11543 var scrollbarWidths; 11544 // make all axis cells line up 11545 this.axisWidth = core.matchCellWidths(core.findElements(this.el, '.fc-axis')); 11546 // hack to give the view some height prior to timeGrid's columns being rendered 11547 // TODO: separate setting height from scroller VS timeGrid. 11548 if (!this.timeGrid.colEls) { 11549 if (!isAuto) { 11550 scrollerHeight = this.computeScrollerHeight(viewHeight); 11551 this.scroller.setHeight(scrollerHeight); 11552 } 11553 return; 11554 } 11555 // set of fake row elements that must compensate when scroller has scrollbars 11556 var noScrollRowEls = core.findElements(this.el, '.fc-row').filter(function (node) { 11557 return !_this.scroller.el.contains(node); 11558 }); 11559 // reset all dimensions back to the original state 11560 this.timeGrid.bottomRuleEl.style.display = 'none'; // will be shown later if this <hr> is necessary 11561 this.scroller.clear(); // sets height to 'auto' and clears overflow
11562 noScrollRowEls.forEach(core.uncompensateScroll); 11563 // limit number of events in the all-day area 11564 if (this.dayGrid) { 11565 this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed 11566 eventLimit = this.opt('eventLimit'); 11567 if (eventLimit && typeof eventLimit !== 'number') { 11568 eventLimit = TIMEGRID_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number 11569 } 11570 if (eventLimit) { 11571 this.dayGrid.limitRows(eventLimit); 11572 } 11573 } 11574 if (!isAuto) { // should we force dimensions of the scroll container? 11575 scrollerHeight = this.computeScrollerHeight(viewHeight); 11576 this.scroller.setHeight(scrollerHeight); 11577 scrollbarWidths = this.scroller.getScrollbarWidths(); 11578 if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars? 11579 // make the all-day and header rows lines up 11580 noScrollRowEls.forEach(function (rowEl) { 11581 core.compensateScroll(rowEl, scrollbarWidths); 11582 }); 11583 // the scrollbar compensation might have changed text flow, which might affect height, so recalculate 11584 // and reapply the desired height to the scroller. 11585 scrollerHeight = this.computeScrollerHeight(viewHeight); 11586 this.scroller.setHeight(scrollerHeight); 11587 } 11588 // guarantees the same scrollbar widths 11589 this.scroller.lockOverflow(scrollbarWidths); 11590 // if there's any space below the slats, show the horizontal rule. 11591 // this won't cause any new overflow, because lockOverflow already called. 11592 if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) { 11593 this.timeGrid.bottomRuleEl.style.display = ''; 11594 } 11595 } 11596 }; 11597 // given a desired total height of the view, returns what the height of the scroller should be 11598 TimeGridView.prototype.computeScrollerHeight = function (viewHeight) { 11599 return viewHeight - 11600 core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller 11601 }; 11602 /* Scroll 11603 ------------------------------------------------------------------------------------------------------------------*/ 11604 // Computes the initial pre-configured scroll state prior to allowing the user to change it 11605 TimeGridView.prototype.computeDateScroll = function (timeMs) { 11606 var top = this.timeGrid.computeTimeTop(timeMs); 11607 // zoom can give weird floating-point values. rather scroll a little bit further 11608 top = Math.ceil(top); 11609 if (top) { 11610 top++; // to overcome top border that slots beyond the first have. looks better 11611 } 11612 return { top: top }; 11613 }; 11614 TimeGridView.prototype.queryDateScroll = function () { 11615 return { top: this.scroller.getScrollTop() }; 11616 }; 11617 TimeGridView.prototype.applyDateScroll = function (scroll) { 11618 if (scroll.top !== undefined) { 11619 this.scroller.setScrollTop(scroll.top); 11620 } 11621 }; 11622 // Generates an HTML attribute string for setting the width of the axis, if it is known 11623 TimeGridView.prototype.axisStyleAttr = function () { 11624 if (this.axisWidth != null) { 11625 return 'style="width:' + this.axisWidth + 'px"'; 11626 } 11627 return ''; 11628 }; 11629 return TimeGridView; 11630 }(core.View)); 11631 TimeGridView.prototype.usesMinMaxTime = true; // indicates that minTime/maxTime affects rendering 11632 11633 var SimpleTimeGrid = /** @class */ (function (_super) { 11634 __extends(SimpleTimeGrid, _super); 11635 function SimpleTimeGrid(context, timeGrid) { 11636 var _this = _super.call(this, context, timeGrid.el) || this; 11637 _this.buildDayRanges = core.memoize(buildDayRanges); 11638 _this.slicer = new TimeGridSlicer(); 11639 _this.timeGrid = timeGrid; 11640 context.calendar.registerInteractiveComponent(_this, { 11641 el: _this.timeGrid.el 11642 }); 11643 return _this; 11644 } 11645 SimpleTimeGrid.prototype.destroy = function () { 11646 _super.prototype.destroy.call(this); 11647 this.calendar.unregisterInteractiveComponent(this); 11648 }; 11649 SimpleTimeGrid.prototype.render = function (props) { 11650 var dateProfile = props.dateProfile, dayTable = props.dayTable; 11651 var dayRanges = this.dayRanges = this.buildDayRanges(dayTable, dateProfile, this.dateEnv); 11652 this.timeGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, null, this.timeGrid, dayRanges), { dateProfile: dateProfile, cells: dayTable.cells[0] })); 11653 }; 11654 SimpleTimeGrid.prototype.renderNowIndicator = function (date) { 11655 this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(date, this.timeGrid, this.dayRanges), date); 11656 }; 11657 SimpleTimeGrid.prototype.buildPositionCaches = function () { 11658 this.timeGrid.buildPositionCaches(); 11659 }; 11660 SimpleTimeGrid.prototype.queryHit = function (positionLeft, positionTop) { 11661 var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop); 11662 if (rawHit) { 11663 return { 11664 component: this.timeGrid, 11665 dateSpan: rawHit.dateSpan, 11666 dayEl: rawHit.dayEl, 11667 rect: { 11668 left: rawHit.relativeRect.left, 11669 right: rawHit.relativeRect.right, 11670 top: rawHit.relativeRect.top, 11671 bottom: rawHit.relativeRect.bottom 11672 }, 11673 layer: 0 11674 }; 11675 } 11676 }; 11677 return SimpleTimeGrid; 11678 }(core.DateComponent)); 11679 function buildDayRanges(dayTable, dateProfile, dateEnv) { 11680 var ranges = []; 11681 for (var _i = 0, _a = dayTable.headerDates; _i < _a.length; _i++) { 11682 var date = _a[_i]; 11683 ranges.push({ 11684 start: dateEnv.add(date, dateProfile.minTime), 11685 end: dateEnv.add(date, dateProfile.maxTime) 11686 }); 11687 } 11688 return ranges; 11689 } 11690 var TimeGridSlicer = /** @class */ (function (_super) { 11691 __extends(TimeGridSlicer, _super); 11692 function TimeGridSlicer() { 11693 return _super !== null && _super.apply(this, arguments) || this; 11694 } 11695 TimeGridSlicer.prototype.sliceRange = function (range, dayRanges) { 11696 var segs = []; 11697 for (var col = 0; col < dayRanges.length; col++) { 11698 var segRange = core.intersectRanges(range, dayRanges[col]); 11699 if (segRange) { 11700 segs.push({ 11701 start: segRange.start, 11702 end: segRange.end, 11703 isStart: segRange.start.valueOf() === range.start.valueOf(), 11704 isEnd: segRange.end.valueOf() === range.end.valueOf(), 11705 col: col 11706 }); 11707 } 11708 } 11709 return segs; 11710 }; 11711 return TimeGridSlicer; 11712 }(core.Slicer)); 11713 11714 var TimeGridView$1 = /** @class */ (function (_super) { 11715 __extends(TimeGridView, _super); 11716 function TimeGridView(_context, viewSpec, dateProfileGenerator, parentEl) { 11717 var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this; 11718 _this.buildDayTable = core.memoize(buildDayTable); 11719 if (_this.opt('columnHeader')) { 11720 _this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container')); 11721 } 11722 _this.simpleTimeGrid = new SimpleTimeGrid(_this.context, _this.timeGrid); 11723 if (_this.dayGrid) { 11724 _this.simpleDayGrid = new daygrid.SimpleDayGrid(_this.context, _this.dayGrid); 11725 } 11726 return _this; 11727 } 11728 TimeGridView.prototype.destroy = function () { 11729 _super.prototype.destroy.call(this); 11730 if (this.header) { 11731 this.header.destroy(); 11732 } 11733 this.simpleTimeGrid.destroy(); 11734 if (this.simpleDayGrid) { 11735 this.simpleDayGrid.destroy(); 11736 } 11737 }; 11738 TimeGridView.prototype.render = function (props) { 11739 _super.prototype.render.call(this, props); // for flags for updateSize 11740 var dateProfile = this.props.dateProfile; 11741 var dayTable = this.buildDayTable(dateProfile, this.dateProfileGenerator); 11742 var splitProps = this.splitter.splitProps(props); 11743 if (this.header) { 11744 this.header.receiveProps({ 11745 dateProfile: dateProfile, 11746 dates: dayTable.headerDates, 11747 datesRepDistinctDays: true, 11748 renderIntroHtml: this.renderHeadIntroHtml 11749 }); 11750 } 11751 this.simpleTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: dateProfile, 11752 dayTable: dayTable })); 11753 if (this.simpleDayGrid) { 11754 this.simpleDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: dateProfile, 11755 dayTable: dayTable, nextDayThreshold: this.nextDayThreshold, isRigid: false })); 11756 } 11757 }; 11758 TimeGridView.prototype.renderNowIndicator = function (date) { 11759 this.simpleTimeGrid.renderNowIndicator(date); 11760 }; 11761 return TimeGridView; 11762 }(TimeGridView)); 11763 function buildDayTable(dateProfile, dateProfileGenerator) { 11764 var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator); 11765 return new core.DayTable(daySeries, false); 11766 } 11767 11768 var main = core.createPlugin({ 11769 defaultView: 'timeGridWeek', 11770 views: { 11771 timeGrid: { 11772 class: TimeGridView$1, 11773 allDaySlot: true, 11774 slotDuration: '00:30:00', 11775 slotEventOverlap: true // a bad name. confused with overlap/constraint system 11776 }, 11777 timeGridDay: { 11778 type: 'timeGrid', 11779 duration: { days: 1 } 11780 }, 11781 timeGridWeek: { 11782 type: 'timeGrid', 11783 duration: { weeks: 1 } 11784 } 11785 } 11786 }); 11787 11788 exports.AbstractTimeGridView = TimeGridView; 11789 exports.TimeGrid = TimeGrid; 11790 exports.TimeGridSlicer = TimeGridSlicer; 11791 exports.TimeGridView = TimeGridView$1; 11792 exports.buildDayRanges = buildDayRanges; 11793 exports.buildDayTable = buildDayTable; 11794 exports.default = main; 11795 11796 Object.defineProperty(exports, '__esModule', { value: true }); 11797 11798})); 11799 11800/*!
11801FullCalendar List View Plugin v4.1.0 11802Docs & License: https://fullcalendar.io/ 11803(c) 2019 Adam Shaw 11804*/ 11805(function (global, factory) { 11806 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) : 11807 typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) : 11808 (global = global || self, factory(global.FullCalendarList = {}, global.FullCalendar)); 11809}(this, function (exports, core) { 'use strict'; 11810 11811 /*! ***************************************************************************** 11812 Copyright (c) Microsoft Corporation. All rights reserved. 11813 Licensed under the Apache License, Version 2.0 (the "License"); you may not use 11814 this file except in compliance with the License. You may obtain a copy of the 11815 License at http://www.apache.org/licenses/LICENSE-2.0 11816 11817 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11818 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 11819 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 11820 MERCHANTABLITY OR NON-INFRINGEMENT. 11821 11822 See the Apache Version 2.0 License for specific language governing permissions 11823 and limitations under the License. 11824 ***************************************************************************** */ 11825 /* global Reflect, Promise */ 11826 11827 var extendStatics = function(d, b) { 11828 extendStatics = Object.setPrototypeOf || 11829 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 11830 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 11831 return extendStatics(d, b); 11832 }; 11833 11834 function __extends(d, b) { 11835 extendStatics(d, b); 11836 function __() { this.constructor = d; } 11837 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 11838 } 11839 11840 var ListEventRenderer = /** @class */ (function (_super) { 11841 __extends(ListEventRenderer, _super); 11842 function ListEventRenderer(listView) { 11843 var _this = _super.call(this, listView.context) || this; 11844 _this.listView = listView; 11845 return _this; 11846 } 11847 ListEventRenderer.prototype.attachSegs = function (segs) { 11848 if (!segs.length) { 11849 this.listView.renderEmptyMessage(); 11850 } 11851 else { 11852 this.listView.renderSegList(segs); 11853 } 11854 }; 11855 ListEventRenderer.prototype.detachSegs = function () { 11856 }; 11857 // generates the HTML for a single event row 11858 ListEventRenderer.prototype.renderSegHtml = function (seg) { 11859 var _a = this.context, view = _a.view, theme = _a.theme; 11860 var eventRange = seg.eventRange; 11861 var eventDef = eventRange.def; 11862 var eventInstance = eventRange.instance; 11863 var eventUi = eventRange.ui; 11864 var url = eventDef.url; 11865 var classes = ['fc-list-item'].concat(eventUi.classNames); 11866 var bgColor = eventUi.backgroundColor; 11867 var timeHtml; 11868 if (eventDef.allDay) { 11869 timeHtml = core.getAllDayHtml(view); 11870 } 11871 else if (core.isMultiDayRange(eventRange.range)) { 11872 if (seg.isStart) { 11873 timeHtml = core.htmlEscape(this._getTimeText(eventInstance.range.start, seg.end, false // allDay 11874 )); 11875 } 11876 else if (seg.isEnd) { 11877 timeHtml = core.htmlEscape(this._getTimeText(seg.start, eventInstance.range.end, false // allDay 11878 )); 11879 } 11880 else { // inner segment that lasts the whole day 11881 timeHtml = core.getAllDayHtml(view); 11882 } 11883 } 11884 else { 11885 // Display the normal time text for the *event's* times 11886 timeHtml = core.htmlEscape(this.getTimeText(eventRange)); 11887 } 11888 if (url) { 11889 classes.push('fc-has-url'); 11890 } 11891 return '<tr class="' + classes.join(' ') + '">' + 11892 (this.displayEventTime ? 11893 '<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' + 11894 (timeHtml || '') + 11895 '</td>' : 11896 '') + 11897 '<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' + 11898 '<span class="fc-event-dot"' + 11899 (bgColor ? 11900 ' style="background-color:' + bgColor + '"' : 11901 '') + 11902 '></span>' + 11903 '</td>' + 11904 '<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' + 11905 '<a' + (url ? ' href="' + core.htmlEscape(url) + '"' : '') + '>
11905' + 11906 core.htmlEscape(eventDef.title || '') + 11907 '</a>' + 11908 '</td>' + 11909 '</tr>'; 11910 }; 11911 // like "4:00am" 11912 ListEventRenderer.prototype.computeEventTimeFormat = function () { 11913 return { 11914 hour: 'numeric', 11915 minute: '2-digit', 11916 meridiem: 'short' 11917 }; 11918 }; 11919 return ListEventRenderer; 11920 }(core.FgEventRenderer)); 11921 11922 /* 11923 Responsible for the scroller, and forwarding event-related actions into the "grid". 11924 */ 11925 var ListView = /** @class */ (function (_super) { 11926 __extends(ListView, _super); 11927 function ListView(context, viewSpec, dateProfileGenerator, parentEl) { 11928 var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this; 11929 _this.computeDateVars = core.memoize(computeDateVars); 11930 _this.eventStoreToSegs = core.memoize(_this._eventStoreToSegs); 11931 var eventRenderer = _this.eventRenderer = new ListEventRenderer(_this); 11932 _this.renderContent = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer)); 11933 _this.el.classList.add('fc-list-view'); 11934 var listViewClassNames = (_this.theme.getClass('listView') || '').split(' '); // wish we didn't have to do this 11935 for (var _i = 0, listViewClassNames_1 = listViewClassNames; _i < listViewClassNames_1.length; _i++) { 11936 var listViewClassName = listViewClassNames_1[_i]; 11937 if (listViewClassName) { // in case input was empty string 11938 _this.el.classList.add(listViewClassName); 11939 } 11940 } 11941 _this.scroller = new core.ScrollComponent('hidden', // overflow x 11942 'auto' // overflow y 11943 ); 11944 _this.el.appendChild(_this.scroller.el); 11945 _this.contentEl = _this.scroller.el; // shortcut 11946 context.calendar.registerInteractiveComponent(_this, { 11947 el: _this.el 11948 // TODO: make aware that it doesn't do Hits 11949 }); 11950 return _this; 11951 } 11952 ListView.prototype.render = function (props) { 11953 var _a = this.computeDateVars(props.dateProfile), dayDates = _a.dayDates, dayRanges = _a.dayRanges; 11954 this.dayDates = dayDates; 11955 this.renderContent(this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges)); 11956 }; 11957 ListView.prototype.destroy = function () { 11958 _super.prototype.destroy.call(this); 11959 this.scroller.destroy(); // will remove the Grid too 11960 this.calendar.unregisterInteractiveComponent(this); 11961 }; 11962 ListView.prototype.updateSize = function (isResize, viewHeight, isAuto) { 11963 _super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); 11964 this.eventRenderer.computeSizes(isResize); 11965 this.eventRenderer.assignSizes(isResize); 11966 this.scroller.clear(); // sets height to 'auto' and clears overflow 11967 if (!isAuto) { 11968 this.scroller.setHeight(this.computeScrollerHeight(viewHeight)); 11969 } 11970 }; 11971 ListView.prototype.computeScrollerHeight = function (viewHeight) { 11972 return viewHeight - 11973 core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller 11974 }; 11975 ListView.prototype._eventStoreToSegs = function (eventStore, eventUiBases, dayRanges) { 11976 return this.eventRangesToSegs(core.sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.nextDayThreshold).fg, dayRanges); 11977 }; 11978 ListView.prototype.eventRangesToSegs = function (eventRanges, dayRanges) { 11979 var segs = []; 11980 for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { 11981 var eventRange = eventRanges_1[_i]; 11982 segs.push.apply(segs, this.eventRangeToSegs(eventRange, dayRanges)); 11983 } 11984 return segs; 11985 }; 11986 ListView.prototype.eventRangeToSegs = function (eventRange, dayRanges) { 11987 var _a = this, dateEnv = _a.dateEnv, nextDayThreshold = _a.nextDayThreshold; 11988 var range = eventRange.range; 11989 var allDay = eventRange.def.allDay; 11990 var dayIndex; 11991 var segRange; 11992 var seg; 11993 var segs = []; 11994 for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) { 11995 segRange = core.intersectRanges(range, dayRanges[dayIndex]); 11996 if (segRange) { 11997 seg = { 11998 component: this, 11999 eventRange: eventRange, 12000 start: segRange.start, 12001 end: segRange.end, 12002 isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(), 12003 isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(), 12004 dayIndex: dayIndex 12005 }; 12006 segs.push(seg); 12007 // detect when range won't go fully into the next day, 12008 // and mutate the latest seg to the be the end. 12009 if (!seg.isEnd && !allDay && 12010 dayIndex + 1 < dayRanges.length && 12011 range.end < 12012 dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) { 12013 seg.end = range.end; 12014 seg.isEnd = true; 12015 break; 12016 } 12017 } 12018 } 12019 return segs; 12020 }; 12021 ListView.prototype.renderEmptyMessage = function () { 12022 this.contentEl.innerHTML = 12023 '<div class="fc-list-empty-wrap2">' + // TODO: try less wraps 12024 '<div class="fc-list-empty-wrap1">' + 12025 '<div class="fc-list-empty">' + 12026 core.htmlEscape(this.opt('noEventsMessage')) + 12027 '</div>' + 12028 '</div>' + 12029 '</div>'; 12030 }; 12031 // called by ListEventRenderer 12032 ListView.prototype.renderSegList = function (allSegs) { 12033 var segsByDay = this.groupSegsByDay(allSegs); // sparse array 12034 var dayIndex; 12035 var daySegs; 12036 var i; 12037 var tableEl = core.htmlToElement('<table class="fc-list-table ' + this.calendar.theme.getClass('tableList') + '"><tbody></tbody></table>'); 12038 var tbodyEl = tableEl.querySelector('tbody'); 12039 for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) { 12040 daySegs = segsByDay[dayIndex]; 12041 if (daySegs) { // sparse array, so might be undefined 12042 // append a day header 12043 tbodyEl.appendChild(this.buildDayHeaderRow(this.dayDates[dayIndex])); 12044 daySegs = this.eventRenderer.sortEventSegs(daySegs); 12045 for (i = 0;
12045 i < daySegs.length; i++) { 12046 tbodyEl.appendChild(daySegs[i].el); // append event row 12047 } 12048 } 12049 } 12050 this.contentEl.innerHTML = ''; 12051 this.contentEl.appendChild(tableEl); 12052 }; 12053 // Returns a sparse array of arrays, segs grouped by their dayIndex 12054 ListView.prototype.groupSegsByDay = function (segs) { 12055 var segsByDay = []; // sparse array 12056 var i; 12057 var seg; 12058 for (i = 0; i < segs.length; i++) { 12059 seg = segs[i]; 12060 (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = [])) 12061 .push(seg); 12062 } 12063 return segsByDay; 12064 }; 12065 // generates the HTML for the day headers that live amongst the event rows 12066 ListView.prototype.buildDayHeaderRow = function (dayDate) { 12067 var dateEnv = this.dateEnv; 12068 var mainFormat = core.createFormatter(this.opt('listDayFormat')); // TODO: cache 12069 var altFormat = core.createFormatter(this.opt('listDayAltFormat')); // TODO: cache 12070 return core.createElement('tr', { 12071 className: 'fc-list-heading', 12072 'data-date': dateEnv.formatIso(dayDate, { omitTime: true }) 12073 }, '<td class="' + (this.calendar.theme.getClass('tableListHeading') || 12074 this.calendar.theme.getClass('widgetHeader')) + '" colspan="3">' + 12075 (mainFormat ? 12076 core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-main' }, core.htmlEscape(dateEnv.format(dayDate, mainFormat)) // inner HTML 12077 ) : 12078 '') + 12079 (altFormat ? 12080 core.buildGotoAnchorHtml(this, dayDate, { 'class': 'fc-list-heading-alt' }, core.htmlEscape(dateEnv.format(dayDate, altFormat)) // inner HTML 12081 ) : 12082 '') + 12083 '</td>'); 12084 }; 12085 return ListView; 12086 }(core.View)); 12087 ListView.prototype.fgSegSelector = '.fc-list-item'; // which elements accept event actions 12088 function computeDateVars(dateProfile) { 12089 var dayStart = core.startOfDay(dateProfile.renderRange.start); 12090 var viewEnd = dateProfile.renderRange.end; 12091 var dayDates = []; 12092 var dayRanges = []; 12093 while (dayStart < viewEnd) { 12094 dayDates.push(dayStart); 12095 dayRanges.push({ 12096 start: dayStart, 12097 end: core.addDays(dayStart, 1) 12098 }); 12099 dayStart = core.addDays(dayStart, 1); 12100 } 12101 return { dayDates: dayDates, dayRanges: dayRanges }; 12102 } 12103 12104 var main = core.createPlugin({ 12105 views: { 12106 list: { 12107 class: ListView, 12108 buttonTextKey: 'list', 12109 listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016" 12110 }, 12111 listDay: { 12112 type: 'list', 12113 duration: { days: 1 }, 12114 listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header 12115 }, 12116 listWeek: { 12117 type: 'list', 12118 duration: { weeks: 1 }, 12119 listDayFormat: { weekday: 'long' }, 12120 listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' } 12121 }, 12122 listMonth: { 12123 type: 'list', 12124 duration: { month: 1 }, 12125 listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have 12126 }, 12127 listYear: { 12128 type: 'list', 12129 duration: { year: 1 }, 12130 listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have 12131 } 12132 } 12133 }); 12134 12135 exports.ListView = ListView; 12136 exports.default = main; 12137 12138 Object.defineProperty(exports, '__esModule', { value: true }); 12139 12140}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.