1/*! 2FullCalendar Core Package v4.2.0 3Docs & License: https://fullcalendar.io/ 4(c) 2019 Adam Shaw 5*/ 6(function (global, factory) { 7 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 8 typeof define === 'function' && define.amd ? define(['exports'], factory) : 9 (global = global || self, factory(global.FullCalendar = {})); 10}(this, function (exports) { 'use strict'; 11 12 // Creating 13 // ---------------------------------------------------------------------------------------------------------------- 14 var elementPropHash = { 15 className: true, 16 colSpan: true, 17 rowSpan: true 18 }; 19 var containerTagHash = { 20 '<tr': 'tbody', 21 '<td': 'tr' 22 }; 23 function createElement(tagName, attrs, content) { 24 var el = document.createElement(tagName); 25 if (attrs) { 26 for (var attrName in attrs) { 27 if (attrName === 'style') { 28 applyStyle(el, attrs[attrName]); 29 } 30 else if (elementPropHash[attrName]) { 31 el[attrName] = attrs[attrName]; 32 } 33 else { 34 el.setAttribute(attrName, attrs[attrName]); 35 } 36 } 37 } 38 if (typeof content === 'string') { 39 el.innerHTML = content; // shortcut. no need to process HTML in any way 40 } 41 else if (content != null) { 42 appendToElement(el, content); 43 } 44 return el; 45 } 46 function htmlToElement(html) { 47 html = html.trim(); 48 var container = document.createElement(computeContainerTag(html)); 49 container.innerHTML = html; 50 return container.firstChild; 51 } 52 function htmlToElements(html) { 53 return Array.prototype.slice.call(htmlToNodeList(html)); 54 } 55 function htmlToNodeList(html) { 56 html = html.trim(); 57 var container = document.createElement(computeContainerTag(html)); 58 container.innerHTML = html; 59 return container.childNodes; 60 } 61 // assumes html already trimmed and tag names are lowercase 62 function computeContainerTag(html) { 63 return containerTagHash[html.substr(0, 3) // faster than using regex 64 ] || 'div'; 65 } 66 function appendToElement(el, content) { 67 var childNodes = normalizeContent(content); 68 for (var i = 0; i < childNodes.length; i++) { 69 el.appendChild(childNodes[i]); 70 } 71 } 72 function prependToElement(parent, content) { 73 var newEls = normalizeContent(content); 74 var afterEl = parent.firstChild || null; // if no firstChild, will append to end, but that's okay, b/c there were no children 75 for (var i = 0; i < newEls.length; i++) { 76 parent.insertBefore(newEls[i], afterEl); 77 } 78 } 79 function insertAfterElement(refEl, content) { 80 var newEls = normalizeContent(content); 81 var afterEl = refEl.nextSibling || null; 82 for (var i = 0; i < newEls.length; i++) { 83 refEl.parentNode.insertBefore(newEls[i], afterEl); 84 } 85 } 86 function normalizeContent(content) { 87 var els; 88 if (typeof content === 'string') { 89 els = htmlToElements(content); 90 } 91 else if (content instanceof Node) { 92 els = [content]; 93 } 94 else { // Node[] or NodeList 95 els = Array.prototype.slice.call(content); 96 } 97 return els; 98 } 99 function removeElement(el) { 100 if (el.parentNode) { 101 el.parentNode.removeChild(el); 102 } 103 } 104 // Querying 105 // ---------------------------------------------------------------------------------------------------------------- 106 // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest 107 var matchesMethod = Element.prototype.matches || 108 Element.prototype.matchesSelector || 109 Element.prototype.msMatchesSelector; 110 var closestMethod = Element.prototype.closest || function (selector) { 111 // polyfill 112 var el = this; 113 if (!document.documentElement.contains(el)) { 114 return null; 115 } 116 do { 117 if (elementMatches(el, selector)) { 118 return el; 119 } 120 el = el.parentElement || el.parentNode; 121 } while (el !== null && el.nodeType === 1); 122 return null; 123 }; 124 function elementClosest(el, selector) { 125 return closestMethod.call(el, selector); 126 } 127 function elementMatches(el, selector) { 128 return matchesMethod.call(el, selector); 129 } 130 // accepts multiple subject els 131 // returns a real array. good for methods like forEach 132 function findElements(container, selector) { 133 var containers = container instanceof HTMLElement ? [container] : container; 134 var allMatches = []; 135 for (var i = 0; i < containers.length; i++) { 136 var matches = containers[i].querySelectorAll(selector); 137 for (var j = 0; j < matches.length; j++) { 138 allMatches.push(matches[j]); 139 } 140 } 141 return allMatches; 142 } 143 // accepts multiple subject els 144 // only queries direct child elements 145 function findChildren(parent, selector) { 146 var parents = parent instanceof HTMLElement ? [parent] : parent; 147 var allMatches = []; 148 for (var i = 0; i < parents.length; i++) { 149 var childNodes = parents[i].children; // only ever elements 150 for (var j = 0; j < childNodes.length; j++) { 151 var childNode = childNodes[j]; 152 if (!selector || elementMatches(childNode, selector)) { 153 allMatches.push(childNode); 154 } 155 } 156 } 157 return allMatches; 158 } 159 // Attributes 160 // ---------------------------------------------------------------------------------------------------------------- 161 function forceClassName(el, className, bool) { 162 if (bool) { 163 el.classList.add(className); 164 } 165 else { 166 el.classList.remove(className); 167 } 168 } 169 // Style 170 // ---------------------------------------------------------------------------------------------------------------- 171 var PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i; 172 function applyStyle(el, props) { 173 for (var propName in props) { 174 applyStyleProp(el, propName, props[propName]); 175 } 176 } 177 function applyStyleProp(el, name, val) { 178 if (val == null) { 179 el.style[name] = ''; 180 } 181 else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) { 182 el.style[name] = val + 'px'; 183 } 184 else { 185 el.style[name] = val; 186 } 187 } 188 189 function pointInsideRect(point, rect) { 190 return point.left >= rect.left && 191 point.left < rect.right && 192 point.top >
192= rect.top && 193 point.top < rect.bottom; 194 } 195 // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false 196 function intersectRects(rect1, rect2) { 197 var res = { 198 left: Math.max(rect1.left, rect2.left), 199 right: Math.min(rect1.right, rect2.right), 200 top: Math.max(rect1.top, rect2.top), 201 bottom: Math.min(rect1.bottom, rect2.bottom) 202 }; 203 if (res.left < res.right && res.top < res.bottom) { 204 return res; 205 } 206 return false; 207 } 208 function translateRect(rect, deltaX, deltaY) { 209 return { 210 left: rect.left + deltaX, 211 right: rect.right + deltaX, 212 top: rect.top + deltaY, 213 bottom: rect.bottom + deltaY 214 }; 215 } 216 // Returns a new point that will have been moved to reside within the given rectangle 217 function constrainPoint(point, rect) { 218 return { 219 left: Math.min(Math.max(point.left, rect.left), rect.right), 220 top: Math.min(Math.max(point.top, rect.top), rect.bottom) 221 }; 222 } 223 // Returns a point that is the center of the given rectangle 224 function getRectCenter(rect) { 225 return { 226 left: (rect.left + rect.right) / 2, 227 top: (rect.top + rect.bottom) / 2 228 }; 229 } 230 // Subtracts point2's coordinates from point1's coordinates, returning a delta 231 function diffPoints(point1, point2) { 232 return { 233 left: point1.left - point2.left, 234 top: point1.top - point2.top 235 }; 236 } 237 238 // Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side 239 var isRtlScrollbarOnLeft = null; 240 function getIsRtlScrollbarOnLeft() { 241 if (isRtlScrollbarOnLeft === null) { 242 isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft(); 243 } 244 return isRtlScrollbarOnLeft; 245 } 246 function computeIsRtlScrollbarOnLeft() { 247 var outerEl = createElement('div', { 248 style: { 249 position: 'absolute', 250 top: -1000, 251 left: 0, 252 border: 0, 253 padding: 0, 254 overflow: 'scroll', 255 direction: 'rtl' 256 } 257 }, '<div></div>'); 258 document.body.appendChild(outerEl); 259 var innerEl = outerEl.firstChild; 260 var res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left; 261 removeElement(outerEl); 262 return res; 263 } 264 // The scrollbar width computations in computeEdges are sometimes flawed when it comes to 265 // retina displays, rounding, and IE11. Massage them into a usable value. 266 function sanitizeScrollbarWidth(width) { 267 width = Math.max(0, width); // no negatives 268 width = Math.round(width); 269 return width; 270 } 271 272 function computeEdges(el, getPadding) { 273 if (getPadding === void 0) { getPadding = false; } 274 var computedStyle = window.getComputedStyle(el); 275 var borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0; 276 var borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0; 277 var borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0; 278 var borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; 279 var scrollbarLeftRight = sanitizeScrollbarWidth(el.offsetWidth - el.clientWidth - borderLeft - borderRight); 280 var scrollbarBottom = sanitizeScrollbarWidth(el.offsetHeight - el.clientHeight - borderTop - borderBottom); 281 var res = { 282 borderLeft: borderLeft, 283 borderRight: borderRight, 284 borderTop: borderTop, 285 borderBottom: borderBottom, 286 scrollbarBottom: scrollbarBottom, 287 scrollbarLeft: 0, 288 scrollbarRight: 0 289 }; 290 if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side? 291 res.scrollbarLeft = scrollbarLeftRight; 292 } 293 else { 294 res.scrollbarRight = scrollbarLeftRight; 295 } 296 if (getPadding) { 297 res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0; 298 res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0; 299 res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0; 300 res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0; 301 } 302 return res; 303 } 304 function computeInnerRect(el, goWithinPadding) { 305 if (goWithinPadding === void 0) { goWithinPadding = false; } 306 var outerRect = computeRect(el); 307 var edges = computeEdges(el, goWithinPadding); 308 var res = { 309 left: outerRect.left + edges.borderLeft + edges.scrollbarLeft, 310 right: outerRect.right - edges.borderRight - edges.scrollbarRight, 311 top: outerRect.top + edges.borderTop, 312 bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom 313 }; 314 if (goWithinPadding) { 315 res.left += edges.paddingLeft; 316 res.right -= edges.paddingRight; 317 res.top += edges.paddingTop; 318 res.bottom -= edges.paddingBottom; 319 } 320 return res; 321 } 322 function computeRect(el) { 323 var rect = el.getBoundingClientRect(); 324 return { 325 left: rect.left + window.pageXOffset, 326 top: rect.top + window.pageYOffset, 327 right: rect.right + window.pageXOffset, 328 bottom: rect.bottom + window.pageYOffset 329 }; 330 } 331 function computeViewportRect() { 332 return { 333 left: window.pageXOffset, 334 right: window.pageXOffset + document.documentElement.clientWidth, 335 top: window.pageYOffset, 336 bottom: window.pageYOffset + document.documentElement.clientHeight 337 }; 338 } 339 function computeHeightAndMargins(el) { 340 var computed = window.getComputedStyle(el); 341 return el.getBoundingClientRect().height + 342 parseInt(computed.marginTop, 10) + 343 parseInt(computed.marginBottom, 10); 344 } 345 // does not return window 346 function getClippingParents(el) { 347 var parents = []; 348 while (el instanceof HTMLElement) { // will stop when gets to document or null 349 var computedStyle = window.getComputedStyle(el); 350 if (computedStyle.position === 'fixed') { 351 break; 352 } 353 if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) { 354 parents.push(el); 355 } 356 el = el.parentNode; 357 } 358 return parents; 359 }
360 function computeClippingRect(el) { 361 return getClippingParents(el) 362 .map(function (el) { 363 return computeInnerRect(el); 364 }) 365 .concat(computeViewportRect()) 366 .reduce(function (rect0, rect1) { 367 return intersectRects(rect0, rect1) || rect1; // should always intersect 368 }); 369 } 370 371 // Stops a mouse/touch event from doing it's native browser action 372 function preventDefault(ev) { 373 ev.preventDefault(); 374 } 375 // Event Delegation 376 // ---------------------------------------------------------------------------------------------------------------- 377 function listenBySelector(container, eventType, selector, handler) { 378 function realHandler(ev) { 379 var matchedChild = elementClosest(ev.target, selector); 380 if (matchedChild) { 381 handler.call(matchedChild, ev, matchedChild); 382 } 383 } 384 container.addEventListener(eventType, realHandler); 385 return function () { 386 container.removeEventListener(eventType, realHandler); 387 }; 388 } 389 function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) { 390 var currentMatchedChild; 391 return listenBySelector(container, 'mouseover', selector, function (ev, matchedChild) { 392 if (matchedChild !== currentMatchedChild) { 393 currentMatchedChild = matchedChild; 394 onMouseEnter(ev, matchedChild); 395 var realOnMouseLeave_1 = function (ev) { 396 currentMatchedChild = null; 397 onMouseLeave(ev, matchedChild); 398 matchedChild.removeEventListener('mouseleave', realOnMouseLeave_1); 399 }; 400 // listen to the next mouseleave, and then unattach 401 matchedChild.addEventListener('mouseleave', realOnMouseLeave_1); 402 } 403 }); 404 } 405 // Animation 406 // ---------------------------------------------------------------------------------------------------------------- 407 var transitionEventNames = [ 408 'webkitTransitionEnd', 409 'otransitionend', 410 'oTransitionEnd', 411 'msTransitionEnd', 412 'transitionend' 413 ]; 414 // triggered only when the next single subsequent transition finishes 415 function whenTransitionDone(el, callback) { 416 var realCallback = function (ev) { 417 callback(ev); 418 transitionEventNames.forEach(function (eventName) { 419 el.removeEventListener(eventName, realCallback); 420 }); 421 }; 422 transitionEventNames.forEach(function (eventName) { 423 el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes 424 }); 425 } 426 427 var DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; 428 // Adding 429 function addWeeks(m, n) { 430 var a = dateToUtcArray(m); 431 a[2] += n * 7; 432 return arrayToUtcDate(a); 433 } 434 function addDays(m, n) { 435 var a = dateToUtcArray(m); 436 a[2] += n; 437 return arrayToUtcDate(a); 438 } 439 function addMs(m, n) { 440 var a = dateToUtcArray(m); 441 a[6] += n; 442 return arrayToUtcDate(a); 443 } 444 // Diffing (all return floats) 445 function diffWeeks(m0, m1) { 446 return diffDays(m0, m1) / 7; 447 } 448 function diffDays(m0, m1) { 449 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24); 450 } 451 function diffHours(m0, m1) { 452 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60); 453 } 454 function diffMinutes(m0, m1) { 455 return (m1.valueOf() - m0.valueOf()) / (1000 * 60); 456 } 457 function diffSeconds(m0, m1) { 458 return (m1.valueOf() - m0.valueOf()) / 1000; 459 } 460 function diffDayAndTime(m0, m1) { 461 var m0day = startOfDay(m0); 462 var m1day = startOfDay(m1); 463 return { 464 years: 0, 465 months: 0, 466 days: Math.round(diffDays(m0day, m1day)), 467 milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()) 468 }; 469 } 470 // Diffing Whole Units 471 function diffWholeWeeks(m0, m1) { 472 var d = diffWholeDays(m0, m1); 473 if (d !== null && d % 7 === 0) { 474 return d / 7; 475 } 476 return null; 477 } 478 function diffWholeDays(m0, m1) { 479 if (timeAsMs(m0) === timeAsMs(m1)) { 480 return Math.round(diffDays(m0, m1)); 481 } 482 return null; 483 } 484 // Start-Of 485 function startOfDay(m) { 486 return arrayToUtcDate([ 487 m.getUTCFullYear(), 488 m.getUTCMonth(), 489 m.getUTCDate() 490 ]); 491 } 492 function startOfHour(m) { 493 return arrayToUtcDate([ 494 m.getUTCFullYear(), 495 m.getUTCMonth(), 496 m.getUTCDate(), 497 m.getUTCHours() 498 ]); 499 } 500 function startOfMinute(m) { 501 return arrayToUtcDate([ 502 m.getUTCFullYear(), 503 m.getUTCMonth(), 504 m.getUTCDate(), 505 m.getUTCHours(), 506 m.getUTCMinutes() 507 ]); 508 } 509 function startOfSecond(m) { 510 return arrayToUtcDate([ 511 m.getUTCFullYear(), 512 m.getUTCMonth(), 513 m.getUTCDate(), 514 m.getUTCHours(), 515 m.getUTCMinutes(), 516 m.getUTCSeconds() 517 ]); 518 } 519 // Week Computation 520 function weekOfYear(marker, dow, doy) { 521 var y = marker.getUTCFullYear(); 522 var w = weekOfGivenYear(marker, y, dow, doy); 523 if (w < 1) { 524 return weekOfGivenYear(marker, y - 1, dow, doy); 525 } 526 var nextW = weekOfGivenYear(marker, y + 1, dow, doy); 527 if (nextW >= 1) { 528 return Math.min(w, nextW); 529 } 530 return w; 531 } 532 function weekOfGivenYear(marker, year, dow, doy) { 533 var firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]); 534 var dayStart = startOfDay(marker); 535 var days = Math.round(diffDays(firstWeekStart, dayStart)); 536 return Math.floor(days / 7) + 1; // zero-indexed 537 } 538 // start-of-first-week - start-of-year 539 function firstWeekOffset(year, dow, doy) { 540 // first-week day -- which january is always in the first week (4 for iso, 1 for other) 541 var fwd = 7 + dow - doy; 542 // first-week day local weekday -- which local weekday is fwd 543 var fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7; 544 return -fwdlw + fwd - 1; 545 } 546 // Array Conversion 547 function dateToLocalArray(date) { 548 return [ 549 date.getFullYear(), 550 date.getMonth(), 551 date.getDate(), 552 date.getHours(), 553 date.getMinutes(), 554 date.getSeconds(), 555 date.getMilliseconds() 556 ]; 557 } 558 function arrayToLocalDate(a) { 559 return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month 560 a[3] || 0, a[4] || 0, a[5] || 0); 561 } 562 function dateToUtcArray(date) { 563 return [ 564 date.getUTCFullYear(), 565 date.getUTCMonth(), 566 date.getUTCDate(), 567 date.getUTCHours(), 568 date.getUTCMinutes(), 569 date.getUTCSeconds(), 570 date.getUTCMilliseconds() 571 ]; 572 } 573 function arrayToUtcDate(a) { 574 // according to web standards (and Safari), a month index is required. 575 // massage if only given a year. 576 if (a.length === 1) { 577 a = a.concat([0]); 578 } 579 return new Date(Date.UTC.apply(Date, a)); 580 } 581 // Other Utils 582 function isValidDate(m) { 583 return !isNaN(m.valueOf()); 584 } 585 function timeAsMs(m) { 586 return m.getUTCHours() * 1000 * 60 * 60 + 587 m.getUTCMinutes() * 1000 * 60 + 588 m.getUTCSeconds() * 1000 + 589 m.getUTCMilliseconds(); 590 } 591 592 var INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
593 var PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/; 594 // Parsing and Creation 595 function createDuration(input, unit) { 596 var _a; 597 if (typeof input === 'string') { 598 return parseString(input); 599 } 600 else if (typeof input === 'object' && input) { // non-null object 601 return normalizeObject(input); 602 } 603 else if (typeof input === 'number') { 604 return normalizeObject((_a = {}, _a[unit || 'milliseconds'] = input, _a)); 605 } 606 else { 607 return null; 608 } 609 } 610 function parseString(s) { 611 var m = PARSE_RE.exec(s); 612 if (m) { 613 var sign = m[1] ? -1 : 1; 614 return { 615 years: 0, 616 months: 0, 617 days: sign * (m[2] ? parseInt(m[2], 10) : 0), 618 milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours 619 (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes 620 (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds 621 (m[6] ? parseInt(m[6], 10) : 0) // ms 622 ) 623 }; 624 } 625 return null; 626 } 627 function normalizeObject(obj) { 628 return { 629 years: obj.years || obj.year || 0, 630 months: obj.months || obj.month || 0, 631 days: (obj.days || obj.day || 0) + 632 getWeeksFromInput(obj) * 7, 633 milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours 634 (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes 635 (obj.seconds || obj.second || 0) * 1000 + // seconds 636 (obj.milliseconds || obj.millisecond || obj.ms || 0) // ms 637 }; 638 } 639 function getWeeksFromInput(obj) { 640 return obj.weeks || obj.week || 0; 641 } 642 // Equality 643 function durationsEqual(d0, d1) { 644 return d0.years === d1.years && 645 d0.months === d1.months && 646 d0.days === d1.days && 647 d0.milliseconds === d1.milliseconds; 648 } 649 function isSingleDay(dur) { 650 return dur.years === 0 && dur.months === 0 && dur.days === 1 && dur.milliseconds === 0; 651 } 652 // Simple Math 653 function addDurations(d0, d1) { 654 return { 655 years: d0.years + d1.years, 656 months: d0.months + d1.months, 657 days: d0.days + d1.days, 658 milliseconds: d0.milliseconds + d1.milliseconds 659 }; 660 } 661 function subtractDurations(d1, d0) { 662 return { 663 years: d1.years - d0.years, 664 months: d1.months - d0.months, 665 days: d1.days - d0.days, 666 milliseconds: d1.milliseconds - d0.milliseconds 667 }; 668 } 669 function multiplyDuration(d, n) { 670 return { 671 years: d.years * n, 672 months: d.months * n, 673 days: d.days * n, 674 milliseconds: d.milliseconds * n 675 }; 676 } 677 // Conversions 678 // "Rough" because they are based on average-case Gregorian months/years 679 function asRoughYears(dur) { 680 return asRoughDays(dur) / 365; 681 } 682 function asRoughMonths(dur) { 683 return asRoughDays(dur) / 30; 684 } 685 function asRoughDays(dur) { 686 return asRoughMs(dur) / 864e5; 687 } 688 function asRoughMinutes(dur) { 689 return asRoughMs(dur) / (1000 * 60); 690 } 691 function asRoughSeconds(dur) { 692 return asRoughMs(dur) / 1000; 693 } 694 function asRoughMs(dur) { 695 return dur.years * (365 * 864e5) + 696 dur.months * (30 * 864e5) + 697 dur.days * 864e5 + 698 dur.milliseconds; 699 } 700 // Advanced Math 701 function wholeDivideDurations(numerator, denominator) { 702 var res = null; 703 for (var i = 0; i < INTERNAL_UNITS.length; i++) { 704 var unit = INTERNAL_UNITS[i]; 705 if (denominator[unit]) { 706 var localRes = numerator[unit] / denominator[unit]; 707 if (!isInt(localRes) || (res !== null && res !== localRes)) { 708 return null; 709 } 710 res = localRes; 711 } 712 else if (numerator[unit]) { 713 // needs to divide by something but can't! 714 return null; 715 } 716 } 717 return res; 718 } 719 function greatestDurationDenominator(dur, dontReturnWeeks) { 720 var ms = dur.milliseconds; 721 if (ms) { 722 if (ms % 1000 !== 0) { 723 return { unit: 'millisecond', value: ms }; 724 } 725 if (ms % (1000 * 60) !== 0) { 726 return { unit: 'second', value: ms / 1000 }; 727 } 728 if (ms % (1000 * 60 * 60) !== 0) { 729 return { unit: 'minute', value: ms / (1000 * 60) }; 730 } 731 if (ms) { 732 return { unit: 'hour', value: ms / (1000 * 60 * 60) }; 733 } 734 } 735 if (dur.days) { 736 if (!dontReturnWeeks && dur.days % 7 === 0) { 737 return { unit: 'week', value: dur.days / 7 }; 738 } 739 return { unit: 'day', value: dur.days }; 740 } 741 if (dur.months) { 742 return { unit: 'month', value: dur.months }; 743 } 744 if (dur.years) { 745 return { unit: 'year', value: dur.years }; 746 } 747 return { unit: 'millisecond', value: 0 }; 748 } 749 750 /* FullCalendar-specific DOM Utilities 751 ----------------------------------------------------------------------------------------------------------------------*/ 752 // Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left 753 // and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that. 754 function compensateScroll(rowEl, scrollbarWidths) { 755 if (scrollbarWidths.left) { 756 applyStyle(rowEl, { 757 borderLeftWidth: 1, 758 marginLeft: scrollbarWidths.left - 1 759 }); 760 } 761 if (scrollbarWidths.right) { 762 applyStyle(rowEl, { 763 borderRightWidth: 1, 764 marginRight: scrollbarWidths.right - 1 765 }); 766 } 767 } 768 // Undoes compensateScroll and restores all borders/margins 769 function uncompensateScroll(rowEl) { 770 applyStyle(rowEl, { 771 marginLeft: '', 772 marginRight: '', 773 borderLeftWidth: '', 774 borderRightWidth: '' 775 }); 776 }
777 // Make the mouse cursor express that an event is not allowed in the current area 778 function disableCursor() { 779 document.body.classList.add('fc-not-allowed'); 780 } 781 // Returns the mouse cursor to its original look 782 function enableCursor() { 783 document.body.classList.remove('fc-not-allowed'); 784 } 785 // Given a total available height to fill, have `els` (essentially child rows) expand to accomodate. 786 // By default, all elements that are shorter than the recommended height are expanded uniformly, not considering 787 // any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and 788 // reduces the available height. 789 function distributeHeight(els, availableHeight, shouldRedistribute) { 790 // *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions, 791 // and it is better to be shorter than taller, to avoid creating unnecessary scrollbars. 792 var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element 793 var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE* 794 var flexEls = []; // elements that are allowed to expand. array of DOM nodes 795 var flexOffsets = []; // amount of vertical space it takes up 796 var flexHeights = []; // actual css height 797 var usedHeight = 0; 798 undistributeHeight(els); // give all elements their natural height 799 // find elements that are below the recommended height (expandable). 800 // important to query for heights in a single first pass (to avoid reflow oscillation). 801 els.forEach(function (el, i) { 802 var minOffset = i === els.length - 1 ? minOffset2 : minOffset1; 803 var naturalOffset = computeHeightAndMargins(el); 804 if (naturalOffset < minOffset) { 805 flexEls.push(el); 806 flexOffsets.push(naturalOffset); 807 flexHeights.push(el.offsetHeight); 808 } 809 else { 810 // this element stretches past recommended height (non-expandable). mark the space as occupied. 811 usedHeight += naturalOffset; 812 } 813 }); 814 // readjust the recommended height to only consider the height available to non-maxed-out rows. 815 if (shouldRedistribute) { 816 availableHeight -= usedHeight; 817 minOffset1 = Math.floor(availableHeight / flexEls.length); 818 minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE* 819 } 820 // assign heights to all expandable elements 821 flexEls.forEach(function (el, i) { 822 var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1; 823 var naturalOffset = flexOffsets[i]; 824 var naturalHeight = flexHeights[i]; 825 var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding 826 if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things 827 el.style.height = newHeight + 'px'; 828 } 829 }); 830 } 831 // Undoes distrubuteHeight, restoring all els to their natural height 832 function undistributeHeight(els) { 833 els.forEach(function (el) { 834 el.style.height = ''; 835 }); 836 } 837 // Given `els`, a set of <td> cells, find the cell with the largest natural width and set the widths of all the 838 // cells to be that width. 839 // PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline 840 function matchCellWidths(els) { 841 var maxInnerWidth = 0; 842 els.forEach(function (el) { 843 var innerEl = el.firstChild; // hopefully an element 844 if (innerEl instanceof HTMLElement) { 845 var innerWidth_1 = innerEl.offsetWidth; 846 if (innerWidth_1 > maxInnerWidth) { 847 maxInnerWidth = innerWidth_1; 848 } 849 } 850 }); 851 maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance
852 els.forEach(function (el) { 853 el.style.width = maxInnerWidth + 'px'; 854 }); 855 return maxInnerWidth; 856 } 857 // Given one element that resides inside another, 858 // Subtracts the height of the inner element from the outer element. 859 function subtractInnerElHeight(outerEl, innerEl) { 860 // effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked 861 var reflowStyleProps = { 862 position: 'relative', 863 left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll 864 }; 865 applyStyle(outerEl, reflowStyleProps); 866 applyStyle(innerEl, reflowStyleProps); 867 var diff = outerEl.offsetHeight - innerEl.offsetHeight; // grab the dimensions 868 // undo hack 869 var resetStyleProps = { position: '', left: '' }; 870 applyStyle(outerEl, resetStyleProps); 871 applyStyle(innerEl, resetStyleProps); 872 return diff; 873 } 874 /* Selection 875 ----------------------------------------------------------------------------------------------------------------------*/ 876 function preventSelection(el) { 877 el.classList.add('fc-unselectable'); 878 el.addEventListener('selectstart', preventDefault); 879 } 880 function allowSelection(el) { 881 el.classList.remove('fc-unselectable'); 882 el.removeEventListener('selectstart', preventDefault); 883 } 884 /* Context Menu 885 ----------------------------------------------------------------------------------------------------------------------*/ 886 function preventContextMenu(el) { 887 el.addEventListener('contextmenu', preventDefault); 888 } 889 function allowContextMenu(el) { 890 el.removeEventListener('contextmenu', preventDefault); 891 } 892 /* Object Ordering by Field 893 ----------------------------------------------------------------------------------------------------------------------*/ 894 function parseFieldSpecs(input) { 895 var specs = []; 896 var tokens = []; 897 var i; 898 var token; 899 if (typeof input === 'string') { 900 tokens = input.split(/\s*,\s*/); 901 } 902 else if (typeof input === 'function') { 903 tokens = [input]; 904 } 905 else if (Array.isArray(input)) { 906 tokens = input; 907 } 908 for (i = 0; i < tokens.length; i++) { 909 token = tokens[i]; 910 if (typeof token === 'string') { 911 specs.push(token.charAt(0) === '-' ? 912 { field: token.substring(1), order: -1 } : 913 { field: token, order: 1 }); 914 } 915 else if (typeof token === 'function') { 916 specs.push({ func: token }); 917 } 918 } 919 return specs; 920 } 921 function compareByFieldSpecs(obj0, obj1, fieldSpecs) { 922 var i; 923 var cmp; 924 for (i = 0; i < fieldSpecs.length; i++) { 925 cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]); 926 if (cmp) { 927 return cmp; 928 } 929 } 930 return 0; 931 } 932 function compareByFieldSpec(obj0, obj1, fieldSpec) { 933 if (fieldSpec.func) { 934 return fieldSpec.func(obj0, obj1); 935 } 936 return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) 937 * (fieldSpec.order || 1); 938 } 939 function flexibleCompare(a, b) { 940 if (!a && !b) { 941 return 0; 942 } 943 if (b == null) { 944 return -1; 945 } 946 if (a == null) { 947 return 1; 948 } 949 if (typeof a === 'string' || typeof b === 'string') { 950 return String(a).localeCompare(String(b)); 951 } 952 return a - b; 953 } 954 /* String Utilities 955 ----------------------------------------------------------------------------------------------------------------------*/ 956 function capitaliseFirstLetter(str) { 957 return str.charAt(0).toUpperCase() + str.slice(1); 958 } 959 function padStart(val, len) { 960 var s = String(val); 961 return '000'.substr(0, len - s.length) + s; 962 } 963 /* Number Utilities 964 ----------------------------------------------------------------------------------------------------------------------*/ 965 function compareNumbers(a, b) { 966 return a - b; 967 } 968 function isInt(n) { 969 return n % 1 === 0; 970 } 971 /* Weird Utilities 972 ----------------------------------------------------------------------------------------------------------------------*/ 973 function applyAll(functions, thisObj, args) { 974 if (typeof functions === 'function') { // supplied a single function 975 functions = [functions]; 976 } 977 if (functions) { 978 var i = void 0; 979 var ret = void 0; 980 for (i = 0; i < functions.length; i++) { 981 ret = functions[i].apply(thisObj, args) || ret; 982 } 983 return ret; 984 } 985 } 986 function firstDefined() { 987 var args = []; 988 for (var _i = 0; _i < arguments.length; _i++) { 989 args[_i] = arguments[_i]; 990 } 991 for (var i = 0; i < args.length; i++) { 992 if (args[i] !== undefined) { 993 return args[i]; 994 } 995 } 996 } 997 // Returns a function, that, as long as it continues to be invoked, will not 998 // be triggered. The function will be called after it stops being called for 999 // N milliseconds. If `immediate` is passed, trigger the function on the 1000 // leading edge, instead of the trailing. 1001 // https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714 1002 function debounce(func, wait) { 1003 var timeout; 1004 var args; 1005 var context; 1006 var timestamp; 1007 var result; 1008 var later = function () { 1009 var last = new Date().valueOf() - timestamp; 1010 if (last < wait) { 1011 timeout = setTimeout(later, wait - last); 1012 } 1013 else { 1014 timeout = null;
1015 result = func.apply(context, args); 1016 context = args = null; 1017 } 1018 }; 1019 return function () { 1020 context = this; 1021 args = arguments; 1022 timestamp = new Date().valueOf(); 1023 if (!timeout) { 1024 timeout = setTimeout(later, wait); 1025 } 1026 return result; 1027 }; 1028 } 1029 // Number and Boolean are only types that defaults or not computed for 1030 // TODO: write more comments 1031 function refineProps(rawProps, processors, defaults, leftoverProps) { 1032 if (defaults === void 0) { defaults = {}; } 1033 var refined = {}; 1034 for (var key in processors) { 1035 var processor = processors[key]; 1036 if (rawProps[key] !== undefined) { 1037 // found 1038 if (processor === Function) { 1039 refined[key] = typeof rawProps[key] === 'function' ? rawProps[key] : null; 1040 } 1041 else if (processor) { // a refining function? 1042 refined[key] = processor(rawProps[key]); 1043 } 1044 else { 1045 refined[key] = rawProps[key]; 1046 } 1047 } 1048 else if (defaults[key] !== undefined) { 1049 // there's an explicit default 1050 refined[key] = defaults[key]; 1051 } 1052 else { 1053 // must compute a default 1054 if (processor === String) { 1055 refined[key] = ''; // empty string is default for String 1056 } 1057 else if (!processor || processor === Number || processor === Boolean || processor === Function) { 1058 refined[key] = null; // assign null for other non-custom processor funcs 1059 } 1060 else { 1061 refined[key] = processor(null); // run the custom processor func 1062 } 1063 } 1064 } 1065 if (leftoverProps) { 1066 for (var key in rawProps) { 1067 if (processors[key] === undefined) { 1068 leftoverProps[key] = rawProps[key]; 1069 } 1070 } 1071 } 1072 return refined; 1073 } 1074 /* Date stuff that doesn't belong in datelib core 1075 ----------------------------------------------------------------------------------------------------------------------*/ 1076 // given a timed range, computes an all-day range that has the same exact duration, 1077 // but whose start time is aligned with the start of the day. 1078 function computeAlignedDayRange(timedRange) { 1079 var dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1; 1080 var start = startOfDay(timedRange.start); 1081 var end = addDays(start, dayCnt); 1082 return { start: start, end: end }; 1083 } 1084 // given a timed range, computes an all-day range based on how for the end date bleeds into the next day 1085 // TODO: give nextDayThreshold a default arg 1086 function computeVisibleDayRange(timedRange, nextDayThreshold) { 1087 if (nextDayThreshold === void 0) { nextDayThreshold = createDuration(0); } 1088 var startDay = null; 1089 var endDay = null; 1090 if (timedRange.end) { 1091 endDay = startOfDay(timedRange.end); 1092 var endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay` 1093 // If the end time is actually inclusively part of the next day and is equal to or 1094 // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`. 1095 // Otherwise, leaving it as inclusive will cause it to exclude `endDay`. 1096 if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) { 1097 endDay = addDays(endDay, 1); 1098 } 1099 } 1100 if (timedRange.start) { 1101 startDay = startOfDay(timedRange.start); // the beginning of the day the range starts 1102 // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day. 1103 if (endDay && endDay <= startDay) { 1104 endDay = addDays(startDay, 1); 1105 } 1106 } 1107 return { start: startDay, end: endDay }; 1108 } 1109 // spans from one day into another? 1110 function isMultiDayRange(range) { 1111 var visibleRange = computeVisibleDayRange(range); 1112 return diffDays(visibleRange.start, visibleRange.end) > 1; 1113 } 1114 function diffDates(date0, date1, dateEnv, largeUnit) { 1115 if (largeUnit === 'year') { 1116 return createDuration(dateEnv.diffWholeYears(date0, date1), 'year'); 1117 } 1118 else if (largeUnit === 'month') { 1119 return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month'); 1120 } 1121 else { 1122 return diffDayAndTime(date0, date1); // returns a duration 1123 } 1124 } 1125 1126 /*! ***************************************************************************** 1127 Copyright (c) Microsoft Corporation. All rights reserved. 1128 Licensed under the Apache License, Version 2.0 (the "License");
1128 you may not use 1129 this file except in compliance with the License. You may obtain a copy of the 1130 License at http://www.apache.org/licenses/LICENSE-2.0 1131 1132 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1133 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 1134 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 1135 MERCHANTABLITY OR NON-INFRINGEMENT. 1136 1137 See the Apache Version 2.0 License for specific language governing permissions 1138 and limitations under the License. 1139 ***************************************************************************** */ 1140 /* global Reflect, Promise */ 1141 1142 var extendStatics = function(d, b) { 1143 extendStatics = Object.setPrototypeOf || 1144 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 1145 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 1146 return extendStatics(d, b); 1147 }; 1148 1149 function __extends(d, b) { 1150 extendStatics(d, b); 1151 function __() { this.constructor = d; } 1152 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 1153 } 1154 1155 var __assign = function() { 1156 __assign = Object.assign || function __assign(t) { 1157 for (var s, i = 1, n = arguments.length; i < n; i++) { 1158 s = arguments[i]; 1159 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 1160 } 1161 return t; 1162 }; 1163 return __assign.apply(this, arguments); 1164 }; 1165 1166 function parseRecurring(eventInput, allDayDefault, dateEnv, recurringTypes, leftovers) { 1167 for (var i = 0; i < recurringTypes.length; i++) { 1168 var localLeftovers = {}; 1169 var parsed = recurringTypes[i].parse(eventInput, localLeftovers, dateEnv); 1170 if (parsed) { 1171 var allDay = localLeftovers.allDay; 1172 delete localLeftovers.allDay; // remove from leftovers 1173 if (allDay == null) { 1174 allDay = allDayDefault; 1175 if (allDay == null) { 1176 allDay = parsed.allDayGuess; 1177 if (allDay == null) { 1178 allDay = false; 1179 } 1180 } 1181 } 1182 __assign(leftovers, localLeftovers); 1183 return { 1184 allDay: allDay, 1185 duration: parsed.duration, 1186 typeData: parsed.typeData, 1187 typeId: i 1188 }; 1189 } 1190 } 1191 return null; 1192 } 1193 /* 1194 Event MUST have a recurringDef 1195 */ 1196 function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) { 1197 var typeDef = recurringTypes[eventDef.recurringDef.typeId]; 1198 var markers = typeDef.expand(eventDef.recurringDef.typeData, { 1199 start: dateEnv.subtract(framingRange.start, duration), 1200 end: framingRange.end 1201 }, dateEnv); 1202 // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to 1203 if (eventDef.allDay) { 1204 markers = markers.map(startOfDay); 1205 } 1206 return markers; 1207 } 1208 1209 var hasOwnProperty = Object.prototype.hasOwnProperty; 1210 // Merges an array of objects into a single object. 1211 // The second argument allows for an array of property names who's object values will be merged together. 1212 function mergeProps(propObjs, complexProps) { 1213 var dest = {}; 1214 var i; 1215 var name; 1216 var complexObjs; 1217 var j; 1218 var val; 1219 var props; 1220 if (complexProps) { 1221 for (i = 0; i < complexProps.length; i++) { 1222 name = complexProps[i]; 1223 complexObjs = []; 1224 // collect the trailing object values, stopping when a non-object is discovered 1225 for (j = propObjs.length - 1; j >= 0; j--) { 1226 val = propObjs[j][name]; 1227 if (typeof val === 'object' && val) { // non-null object 1228 complexObjs.unshift(val); 1229 } 1230 else if (val !== undefined) { 1231 dest[name] = val; // if there were no objects, this value will be used 1232 break; 1233 } 1234 } 1235 // if the trailing values were objects, use the merged value 1236 if (complexObjs.length) { 1237 dest[name] = mergeProps(complexObjs); 1238 } 1239 } 1240 } 1241 // copy values into the destination, going from last to first 1242 for (i = propObjs.length - 1; i >= 0; i--) { 1243 props = propObjs[i]; 1244 for (name in props) { 1245 if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign 1246 dest[name] = props[name]; 1247 } 1248 } 1249 } 1250 return dest; 1251 } 1252 function filterHash(hash, func) { 1253 var filtered = {}; 1254 for (var key in hash) { 1255 if (func(hash[key], key)) { 1256 filtered[key] = hash[key]; 1257 } 1258 } 1259 return filtered; 1260 } 1261 function mapHash(hash, func) { 1262 var newHash = {}; 1263 for (var key in hash) { 1264 newHash[key] = func(hash[key], key); 1265 } 1266 return newHash; 1267 } 1268 function arrayToHash(a) { 1269 var hash = {}; 1270 for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { 1271 var item = a_1[_i]; 1272 hash[item] = true; 1273 } 1274 return hash; 1275 } 1276 function hashValuesToArray(obj) { 1277 var a = []; 1278 for (var key in obj) { 1279 a.push(obj[key]); 1280 } 1281 return a; 1282 } 1283 function isPropsEqual(obj0, obj1) { 1284 for (var key in obj0) { 1285 if (hasOwnProperty.call(obj0, key)) { 1286 if (!(key in obj1)) { 1287 return false;
1288 } 1289 } 1290 } 1291 for (var key in obj1) { 1292 if (hasOwnProperty.call(obj1, key)) { 1293 if (obj0[key] !== obj1[key]) { 1294 return false; 1295 } 1296 } 1297 } 1298 return true; 1299 } 1300 1301 function parseEvents(rawEvents, sourceId, calendar, allowOpenRange) { 1302 var eventStore = createEmptyEventStore(); 1303 for (var _i = 0, rawEvents_1 = rawEvents; _i < rawEvents_1.length; _i++) { 1304 var rawEvent = rawEvents_1[_i]; 1305 var tuple = parseEvent(rawEvent, sourceId, calendar, allowOpenRange); 1306 if (tuple) { 1307 eventTupleToStore(tuple, eventStore); 1308 } 1309 } 1310 return eventStore; 1311 } 1312 function eventTupleToStore(tuple, eventStore) { 1313 if (eventStore === void 0) { eventStore = createEmptyEventStore(); } 1314 eventStore.defs[tuple.def.defId] = tuple.def; 1315 if (tuple.instance) { 1316 eventStore.instances[tuple.instance.instanceId] = tuple.instance; 1317 } 1318 return eventStore; 1319 } 1320 function expandRecurring(eventStore, framingRange, calendar) { 1321 var dateEnv = calendar.dateEnv; 1322 var defs = eventStore.defs, instances = eventStore.instances; 1323 // remove existing recurring instances 1324 instances = filterHash(instances, function (instance) { 1325 return !defs[instance.defId].recurringDef; 1326 }); 1327 for (var defId in defs) { 1328 var def = defs[defId]; 1329 if (def.recurringDef) { 1330 var duration = def.recurringDef.duration; 1331 if (!duration) { 1332 duration = def.allDay ? 1333 calendar.defaultAllDayEventDuration : 1334 calendar.defaultTimedEventDuration; 1335 } 1336 var starts = expandRecurringRanges(def, duration, framingRange, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes); 1337 for (var _i = 0, starts_1 = starts; _i < starts_1.length; _i++) { 1338 var start = starts_1[_i]; 1339 var instance = createEventInstance(defId, { 1340 start: start, 1341 end: dateEnv.add(start, duration) 1342 }); 1343 instances[instance.instanceId] = instance; 1344 } 1345 } 1346 } 1347 return { defs: defs, instances: instances }; 1348 } 1349 // retrieves events that have the same groupId as the instance specified by `instanceId` 1350 // or they are the same as the instance. 1351 // why might instanceId not be in the store? an event from another calendar? 1352 function getRelevantEvents(eventStore, instanceId) { 1353 var instance = eventStore.instances[instanceId]; 1354 if (instance) { 1355 var def_1 = eventStore.defs[instance.defId]; 1356 // get events/instances with same group 1357 var newStore = filterEventStoreDefs(eventStore, function (lookDef) { 1358 return isEventDefsGrouped(def_1, lookDef); 1359 }); 1360 // add the original 1361 // TODO: wish we could use eventTupleToStore or something like it 1362 newStore.defs[def_1.defId] = def_1; 1363 newStore.instances[instance.instanceId] = instance; 1364 return newStore; 1365 } 1366 return createEmptyEventStore(); 1367 } 1368 function isEventDefsGrouped(def0, def1) { 1369 return Boolean(def0.groupId && def0.groupId === def1.groupId); 1370 } 1371 function transformRawEvents(rawEvents, eventSource, calendar) { 1372 var calEachTransform = calendar.opt('eventDataTransform'); 1373 var sourceEachTransform = eventSource ? eventSource.eventDataTransform : null; 1374 if (sourceEachTransform) { 1375 rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform); 1376 } 1377 if (calEachTransform) { 1378 rawEvents = transformEachRawEvent(rawEvents, calEachTransform); 1379 } 1380 return rawEvents; 1381 } 1382 function transformEachRawEvent(rawEvents, func) { 1383 var refinedEvents; 1384 if (!func) { 1385 refinedEvents = rawEvents; 1386 } 1387 else { 1388 refinedEvents = []; 1389 for (var _i = 0, rawEvents_2 = rawEvents; _i < rawEvents_2.length; _i++) { 1390 var rawEvent = rawEvents_2[_i]; 1391 var refinedEvent = func(rawEvent); 1392 if (refinedEvent) { 1393 refinedEvents.push(refinedEvent); 1394 } 1395 else if (refinedEvent == null) { 1396 refinedEvents.push(rawEvent); 1397 } // if a different falsy value, do nothing 1398 } 1399 } 1400 return refinedEvents; 1401 } 1402 function createEmptyEventStore() { 1403 return { defs: {}, instances: {} }; 1404 } 1405 function mergeEventStores(store0, store1) { 1406 return { 1407 defs: __assign({}, store0.defs, store1.defs), 1408 instances: __assign({}, store0.instances, store1.instances) 1409 }; 1410 } 1411 function filterEventStoreDefs(eventStore, filterFunc) { 1412 var defs = filterHash(eventStore.defs, filterFunc); 1413 var instances = filterHash(eventStore.instances, function (instance) { 1414 return defs[instance.defId]; // still exists? 1415 }); 1416 return { defs: defs, instances: instances }; 1417 } 1418 1419 function parseRange(input, dateEnv) { 1420 var start = null; 1421 var end = null; 1422 if (input.start) { 1423 start = dateEnv.createMarker(input.start); 1424 } 1425 if (input.end) { 1426 end = dateEnv.createMarker(input.end); 1427 } 1428 if (!start && !end) { 1429 return null; 1430 } 1431 if (start && end && end < start) { 1432 return null; 1433 } 1434 return { start: start, end: end }; 1435 } 1436 // SIDE-EFFECT: will mutate ranges. 1437 // Will return a new array result. 1438 function invertRanges(ranges, constraintRange) { 1439 var invertedRanges = []; 1440 var start = constraintRange.start; // the end of the previous range. the start of the new range 1441 var i; 1442 var dateRange; 1443 // ranges need to be in order. required for our date-walking algorithm 1444 ranges.sort(compareRanges); 1445 for (i = 0; i < ranges.length; i++) { 1446 dateRange = ranges[i]; 1447 // add the span of time before the event (if there is any) 1448 if (dateRange.start > start) { // compare millisecond time (skip any ambig logic) 1449 invertedRanges.push({ start: start, end: dateRange.start }); 1450 } 1451 if (dateRange.end > start) { 1452 start = dateRange.end; 1453 } 1454 } 1455 // add the span of time after the last event (if there is any) 1456 if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic) 1457 invertedRanges.push({ start: start, end: constraintRange.end }); 1458 } 1459 return invertedRanges; 1460 } 1461 function compareRanges(range0, range1) { 1462 return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first 1463 } 1464 function intersectRanges(range0, range1) { 1465 var start = range0.start; 1466 var end = range0.end; 1467 var newRange = null; 1468 if (range1.start !== null) { 1469 if (start === null) { 1470 start = range1.start; 1471 } 1472 else { 1473 start = new Date(Math.max(start.valueOf(), range1.start.valueOf())); 1474 } 1475 } 1476 if (range1.end != null) { 1477 if (end === null) { 1478 end = range1.end; 1479 } 1480 else { 1481 end = new Date(Math.min(end.valueOf(), range1.end.valueOf())); 1482 } 1483 } 1484 if (start === null || end === null || start < end) { 1485 newRange = { start: start, end: end }; 1486 } 1487 return newRange; 1488 } 1489 function rangesEqual(range0, range1) { 1490 return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) && 1491 (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf()); 1492 } 1493 function rangesIntersect(range0, range1) { 1494 return (range0.end === null || range1.start === null || range0.end > range1.start) && 1495 (range0.start === null || range1.end === null || range0.start < range1.end); 1496 } 1497 function rangeContainsRange(outerRange, innerRange) { 1498 return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) && 1499 (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end)); 1500 } 1501 function rangeContainsMarker(range, date) { 1502 return (range.start === null || date >= range.start) && 1503 (range.end === null || date < range.end); 1504 } 1505 // If the given date is not within the given range, move it inside. 1506 // (If it's past the end, make it one millisecond before the end). 1507 function constrainMarkerToRange(date, range) { 1508 if (range.start != null && date < range.start) { 1509 return range.start; 1510 } 1511 if (range.end != null && date >= range.end) { 1512 return new Date(range.end.valueOf() - 1); 1513 } 1514 return date; 1515 } 1516 1517 function removeExact(array, exactVal) { 1518 var removeCnt = 0; 1519 var i = 0; 1520 while (i < array.length) { 1521 if (array[i] === exactVal) { 1522 array.splice(i, 1); 1523 removeCnt++; 1524 } 1525 else { 1526 i++; 1527 } 1528 } 1529 return removeCnt; 1530 } 1531 function isArraysEqual(a0, a1) { 1532 var len = a0.length; 1533 var i; 1534 if (len !== a1.length) { // not array? or not same length? 1535 return false;
1536 } 1537 for (i = 0; i < len; i++) { 1538 if (a0[i] !== a1[i]) { 1539 return false; 1540 } 1541 } 1542 return true; 1543 } 1544 1545 function memoize(workerFunc) { 1546 var args; 1547 var res; 1548 return function () { 1549 if (!args || !isArraysEqual(args, arguments)) { 1550 args = arguments; 1551 res = workerFunc.apply(this, arguments); 1552 } 1553 return res; 1554 }; 1555 } 1556 /* 1557 always executes the workerFunc, but if the result is equal to the previous result, 1558 return the previous result instead. 1559 */ 1560 function memoizeOutput(workerFunc, equalityFunc) { 1561 var cachedRes = null; 1562 return function () { 1563 var newRes = workerFunc.apply(this, arguments); 1564 if (cachedRes === null || !(cachedRes === newRes || equalityFunc(cachedRes, newRes))) { 1565 cachedRes = newRes; 1566 } 1567 return cachedRes; 1568 }; 1569 } 1570 1571 var EXTENDED_SETTINGS_AND_SEVERITIES = { 1572 week: 3, 1573 separator: 0, 1574 omitZeroMinute: 0, 1575 meridiem: 0, 1576 omitCommas: 0 1577 }; 1578 var STANDARD_DATE_PROP_SEVERITIES = { 1579 timeZoneName: 7, 1580 era: 6, 1581 year: 5, 1582 month: 4, 1583 day: 2, 1584 weekday: 2, 1585 hour: 1, 1586 minute: 1, 1587 second: 1 1588 }; 1589 var MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too 1590 var COMMA_RE = /,/g; // we need re for globalness 1591 var MULTI_SPACE_RE = /\s+/g; 1592 var LTR_RE = /\u200e/g; // control character 1593 var UTC_RE = /UTC|GMT/; 1594 var NativeFormatter = /** @class */ (function () { 1595 function NativeFormatter(formatSettings) { 1596 var standardDateProps = {}; 1597 var extendedSettings = {}; 1598 var severity = 0; 1599 for (var name_1 in formatSettings) { 1600 if (name_1 in EXTENDED_SETTINGS_AND_SEVERITIES) { 1601 extendedSettings[name_1] = formatSettings[name_1]; 1602 severity = Math.max(EXTENDED_SETTINGS_AND_SEVERITIES[name_1], severity); 1603 } 1604 else { 1605 standardDateProps[name_1] = formatSettings[name_1]; 1606 if (name_1 in STANDARD_DATE_PROP_SEVERITIES) { 1607 severity = Math.max(STANDARD_DATE_PROP_SEVERITIES[name_1], severity); 1608 } 1609 } 1610 } 1611 this.standardDateProps = standardDateProps; 1612 this.extendedSettings = extendedSettings; 1613 this.severity = severity; 1614 this.buildFormattingFunc = memoize(buildFormattingFunc); 1615 } 1616 NativeFormatter.prototype.format = function (date, context) { 1617 return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date); 1618 }; 1619 NativeFormatter.prototype.formatRange = function (start, end, context) { 1620 var _a = this, standardDateProps = _a.standardDateProps, extendedSettings = _a.extendedSettings; 1621 var diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem); 1622 if (!diffSeverity) { 1623 return this.format(start, context); 1624 } 1625 var biggestUnitForPartial = diffSeverity; 1626 if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time 1627 (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') && 1628 (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') && 1629 (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) { 1630 biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time 1631 } 1632 var full0 = this.format(start, context); 1633 var full1 = this.format(end, context); 1634 if (full0 === full1) { 1635 return full0; 1636 } 1637 var partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForParti
1637al); 1638 var partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context); 1639 var partial0 = partialFormattingFunc(start); 1640 var partial1 = partialFormattingFunc(end); 1641 var insertion = findCommonInsertion(full0, partial0, full1, partial1); 1642 var separator = extendedSettings.separator || ''; 1643 if (insertion) { 1644 return insertion.before + partial0 + separator + partial1 + insertion.after; 1645 } 1646 return full0 + separator + full1; 1647 }; 1648 NativeFormatter.prototype.getLargestUnit = function () { 1649 switch (this.severity) { 1650 case 7: 1651 case 6: 1652 case 5: 1653 return 'year'; 1654 case 4: 1655 return 'month'; 1656 case 3: 1657 return 'week'; 1658 default: 1659 return 'day'; 1660 } 1661 }; 1662 return NativeFormatter; 1663 }()); 1664 function buildFormattingFunc(standardDateProps, extendedSettings, context) { 1665 var standardDatePropCnt = Object.keys(standardDateProps).length; 1666 if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') { 1667 return function (date) { 1668 return formatTimeZoneOffset(date.timeZoneOffset); 1669 }; 1670 } 1671 if (standardDatePropCnt === 0 && extendedSettings.week) { 1672 return function (date) { 1673 return formatWeekNumber(context.computeWeekNumber(date.marker), context.weekLabel, context.locale, extendedSettings.week); 1674 }; 1675 } 1676 return buildNativeFormattingFunc(standardDateProps, extendedSettings, context); 1677 } 1678 function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) { 1679 standardDateProps = __assign({}, standardDateProps); // copy 1680 extendedSettings = __assign({}, extendedSettings); // copy 1681 sanitizeSettings(standardDateProps, extendedSettings); 1682 standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers 1683 var normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps); 1684 var zeroFormat; // needed? 1685 if (extendedSettings.omitZeroMinute) { 1686 var zeroProps = __assign({}, standardDateProps); 1687 delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings 1688 zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps); 1689 } 1690 return function (date) { 1691 var marker = date.marker; 1692 var format; 1693 if (zeroFormat && !marker.getUTCMinutes()) { 1694 format = zeroFormat; 1695 } 1696 else { 1697 format = normalFormat; 1698 } 1699 var s = format.format(marker); 1700 return postProcess(s, date, standardDateProps, extendedSettings, context); 1701 }; 1702 } 1703 function sanitizeSettings(standardDateProps, extendedSettings) { 1704 // deal with a browser inconsistency where formatting the timezone 1705 // requires that the hour/minute be present. 1706 if (standardDateProps.timeZoneName) { 1707 if (!standardDateProps.hour) { 1708 standardDateProps.hour = '2-digit'; 1709 } 1710 if (!standardDateProps.minute) { 1711 standardDateProps.minute = '2-digit'; 1712 } 1713 } 1714 // only support short timezone names 1715 if (standardDateProps.timeZoneName === 'long') { 1716 standardDateProps.timeZoneName = 'short'; 1717 } 1718 // if requesting to display seconds, MUST display minutes 1719 if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) { 1720 delete extendedSettings.omitZeroMinute; 1721 } 1722 } 1723 function postProcess(s, date, standardDateProps, extendedSettings, context) { 1724 s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes 1725 if (standardDateProps.timeZoneName === 'short') { 1726 s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ? 1727 'UTC' : // important to normalize for IE, which does "GMT" 1728 formatTimeZoneOffset(date.timeZoneOffset)); 1729 } 1730 if (extendedSettings.omitCommas) { 1731 s = s.replace(COMMA_RE, '').trim(); 1732 } 1733 if (extendedSettings.omitZeroMinute) { 1734 s = s.replace(':00', ''); // zeroFormat doesn't always achieve this 1735 } 1736 // ^ do anything that might create adjacent spaces before this point,
1737 // because MERIDIEM_RE likes to eat up loading spaces 1738 if (extendedSettings.meridiem === false) { 1739 s = s.replace(MERIDIEM_RE, '').trim(); 1740 } 1741 else if (extendedSettings.meridiem === 'narrow') { // a/p 1742 s = s.replace(MERIDIEM_RE, function (m0, m1) { 1743 return m1.toLocaleLowerCase(); 1744 }); 1745 } 1746 else if (extendedSettings.meridiem === 'short') { // am/pm 1747 s = s.replace(MERIDIEM_RE, function (m0, m1) { 1748 return m1.toLocaleLowerCase() + 'm'; 1749 }); 1750 } 1751 else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase 1752 s = s.replace(MERIDIEM_RE, function (m0) { 1753 return m0.toLocaleLowerCase(); 1754 }); 1755 } 1756 s = s.replace(MULTI_SPACE_RE, ' '); 1757 s = s.trim(); 1758 return s; 1759 } 1760 function injectTzoStr(s, tzoStr) { 1761 var replaced = false; 1762 s = s.replace(UTC_RE, function () { 1763 replaced = true; 1764 return tzoStr; 1765 }); 1766 // IE11 doesn't include UTC/GMT in the original string, so append to end 1767 if (!replaced) { 1768 s += ' ' + tzoStr; 1769 } 1770 return s; 1771 } 1772 function formatWeekNumber(num, weekLabel, locale, display) { 1773 var parts = []; 1774 if (display === 'narrow') { 1775 parts.push(weekLabel); 1776 } 1777 else if (display === 'short') { 1778 parts.push(weekLabel, ' '); 1779 } 1780 // otherwise, considered 'numeric' 1781 parts.push(locale.simpleNumberFormat.format(num)); 1782 if (locale.options.isRtl) { // TODO: use control characters instead? 1783 parts.reverse(); 1784 } 1785 return parts.join(''); 1786 } 1787 // Range Formatting Utils 1788 // 0 = exactly the same 1789 // 1 = different by time 1790 // and bigger 1791 function computeMarkerDiffSeverity(d0, d1, ca) { 1792 if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) { 1793 return 5; 1794 } 1795 if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) { 1796 return 4; 1797 } 1798 if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) { 1799 return 2; 1800 } 1801 if (timeAsMs(d0) !== timeAsMs(d1)) { 1802 return 1; 1803 } 1804 return 0; 1805 } 1806 function computePartialFormattingOptions(options, biggestUnit) { 1807 var partialOptions = {}; 1808 for (var name_2 in options) { 1809 if (!(name_2 in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone) 1810 STANDARD_DATE_PROP_SEVERITIES[name_2] <= biggestUnit) { 1811 partialOptions[name_2] = options[name_2]; 1812 } 1813 } 1814 return partialOptions; 1815 } 1816 function findCommonInsertion(full0, partial0, full1, partial1) { 1817 var i0 = 0; 1818 while (i0 < full0.length) { 1819 var found0 = full0.indexOf(partial0, i0); 1820 if (found0 === -1) { 1821 break; 1822 } 1823 var before0 = full0.substr(0, found0); 1824 i0 = found0 + partial0.length; 1825 var after0 = full0.substr(i0); 1826 var i1 = 0; 1827 while (i1 < full1.length) { 1828 var found1 = full1.indexOf(partial1, i1); 1829 if (found1 === -1) { 1830 break; 1831 } 1832 var before1 = full1.substr(0, found1); 1833 i1 = found1 + partial1.length; 1834 var after1 = full1.substr(i1); 1835 if (before0 === before1 && after0 === after1) { 1836 return { 1837 before: before0, 1838 after: after0 1839 }; 1840 } 1841 } 1842 } 1843 return null; 1844 } 1845 1846 /* 1847 TODO: fix the terminology of "formatter" vs "formatting func" 1848 */ 1849 /* 1850 At the time of instantiation, this object does not know which cmd-formatting system it will use. 1851 It receives this at the time of formatting, as a setting. 1852 */ 1853 var CmdFormatter = /** @class */ (function () { 1854 function CmdFormatter(cmdStr, separator) { 1855 this.cmdStr = cmdStr; 1856 this.separator = separator; 1857 } 1858 CmdFormatter.prototype.format = function (date, context) { 1859 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, this.separator)); 1860 }; 1861 CmdFormatter.prototype.formatRange = function (start, end, context) { 1862 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, this.separator)); 1863 }; 1864 return CmdFormatter; 1865 }()); 1866 1867 var FuncFormatter = /** @class */ (function () { 1868 function FuncFormatter(func) { 1869 this.func = func; 1870 } 1871 FuncFormatter.prototype.format = function (date, context) { 1872 return this.func(createVerboseFormattingArg(date, null, context)); 1873 }; 1874 FuncFormatter.prototype.formatRange = function (start, end, context) { 1875 return this.func(createVerboseFormattingArg(start, end, context)); 1876 }; 1877 return FuncFormatter; 1878 }()); 1879 1880 // Formatter Object Creation 1881 function createFormatter(input, defaultSeparator) { 1882 if (typeof input === 'object' && input) { // non-null object 1883 if (typeof defaultSeparator === 'string') { 1884 input = __assign({ separator: defaultSeparator }, input); 1885 } 1886 return new NativeFormatter(input); 1887 } 1888 else if (typeof input === 'string') { 1889 return new CmdFormatter(input, defaultSeparator); 1890 } 1891 else if (typeof input === 'function') { 1892 return new FuncFormatter(input); 1893 } 1894 } 1895 // String Utils 1896 // timeZoneOffset is in minutes 1897 function buildIsoString(marker, timeZoneOffset, stripZeroTime) { 1898 if (stripZeroTime === void 0) { stripZeroTime = false; } 1899 var s = marker.toISOString(); 1900 s = s.replace('.000', ''); 1901 if (stripZeroTime) { 1902 s = s.replace('T00:00:00Z', ''); 1903 } 1904 if (s.length > 10) { // time part wasn't stripped, can add timezone info 1905 if (timeZoneOffset == null) { 1906 s = s.replace('Z', ''); 1907 } 1908 else if (timeZoneOffset !== 0) { 1909 s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true)); 1910 } 1911 // otherwise, its UTC-0 and we want to keep the Z 1912 } 1913 return s; 1914 } 1915 function formatIsoTimeString(marker) { 1916 return padStart(marker.getUTCHours(), 2) + ':' + 1917 padStart(marker.getUTCMinutes(), 2) + ':' + 1918 padStart(marker.getUTCSeconds(), 2); 1919 } 1920 function formatTimeZoneOffset(minutes, doIso) { 1921 if (doIso === void 0) { doIso = false; } 1922 var sign = minutes < 0 ? '-' : '+'; 1923 var abs = Math.abs(minutes); 1924 var hours = Math.floor(abs / 60); 1925 var mins = Math.round(abs % 60); 1926 if (doIso) { 1927 return sign + padStart(hours, 2) + ':' + padStart(mins, 2); 1928 } 1929 else { 1930 return 'GMT' + sign + hours + (mins ? ':' + padStart(mins, 2) : ''); 1931 } 1932 } 1933 // Arg Utils 1934 function createVerboseFormattingArg(start, end, context, separator) { 1935 var startInfo = expandZonedMarker(start, context.calendarSystem); 1936 var endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null; 1937 return { 1938 date: startInfo, 1939 start: startInfo, 1940 end: endInfo, 1941 timeZone: context.timeZone, 1942 localeCodes: context.locale.codes, 1943 separator: separator 1944 }; 1945 } 1946 function expandZonedMarker(dateInfo, calendarSystem) { 1947 var a = calendarSystem.markerToArray(dateInfo.marker); 1948 return { 1949 marker: dateInfo.marker, 1950 timeZoneOffset: dateInfo.timeZoneOffset, 1951 array: a, 1952 year: a[0], 1953 month: a[1], 1954 day: a[2], 1955 hour: a[3], 1956 minute: a[4], 1957 second: a[5], 1958 millisecond: a[6] 1959 }; 1960 } 1961 1962 var EventSourceApi = /** @class */ (function () { 1963 function EventSourceApi(calendar, internalEventSource) { 1964 this.calendar = calendar; 1965 this.internalEventSource = internalEventSource; 1966 } 1967 EventSourceApi.prototype.remove = function () { 1968 this.calendar.dispatch({
1969 type: 'REMOVE_EVENT_SOURCE', 1970 sourceId: this.internalEventSource.sourceId 1971 }); 1972 }; 1973 EventSourceApi.prototype.refetch = function () { 1974 this.calendar.dispatch({ 1975 type: 'FETCH_EVENT_SOURCES', 1976 sourceIds: [this.internalEventSource.sourceId] 1977 }); 1978 }; 1979 Object.defineProperty(EventSourceApi.prototype, "id", { 1980 get: function () { 1981 return this.internalEventSource.publicId; 1982 }, 1983 enumerable: true, 1984 configurable: true 1985 }); 1986 Object.defineProperty(EventSourceApi.prototype, "url", { 1987 // only relevant to json-feed event sources 1988 get: function () { 1989 return this.internalEventSource.meta.url; 1990 }, 1991 enumerable: true, 1992 configurable: true 1993 }); 1994 return EventSourceApi; 1995 }()); 1996 1997 var EventApi = /** @class */ (function () { 1998 function EventApi(calendar, def, instance) { 1999 this._calendar = calendar; 2000 this._def = def; 2001 this._instance = instance || null; 2002 } 2003 /* 2004 TODO: make event struct more responsible for this 2005 */ 2006 EventApi.prototype.setProp = function (name, val) { 2007 var _a, _b; 2008 if (name in DATE_PROPS) ; 2009 else if (name in NON_DATE_PROPS) { 2010 if (typeof NON_DATE_PROPS[name] === 'function') { 2011 val = NON_DATE_PROPS[name](val); 2012 } 2013 this.mutate({ 2014 standardProps: (_a = {}, _a[name] = val, _a) 2015 }); 2016 } 2017 else if (name in UNSCOPED_EVENT_UI_PROPS) { 2018 var ui = void 0; 2019 if (typeof UNSCOPED_EVENT_UI_PROPS[name] === 'function') { 2020 val = UNSCOPED_EVENT_UI_PROPS[name](val); 2021 } 2022 if (name === 'color') { 2023 ui = { backgroundColor: val, borderColor: val }; 2024 } 2025 else if (name === 'editable') { 2026 ui = { startEditable: val, durationEditable: val }; 2027 } 2028 else { 2029 ui = (_b = {}, _b[name] = val, _b); 2030 } 2031 this.mutate({ 2032 standardProps: { ui: ui } 2033 }); 2034 } 2035 }; 2036 EventApi.prototype.setExtendedProp = function (name, val) { 2037 var _a; 2038 this.mutate({ 2039 extendedProps: (_a = {}, _a[name] = val, _a) 2040 }); 2041 }; 2042 EventApi.prototype.setStart = function (startInput, options) { 2043 if (options === void 0) { options = {}; } 2044 var dateEnv = this._calendar.dateEnv; 2045 var start = dateEnv.createMarker(startInput); 2046 if (start && this._instance) { // TODO: warning if parsed bad 2047 var instanceRange = this._instance.range; 2048 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!? 2049 var endDelta = null; 2050 if (options.maintainDuration) { 2051 var origDuration = diffDates(instanceRange.start, instanceRange.end, dateEnv, options.granularity); 2052 var newDuration = diffDates(start, instanceRange.end, dateEnv, options.granularity); 2053 endDelta = subtractDurations(origDuration, newDuration); 2054 } 2055 this.mutate({ startDelta: startDelta, endDelta: endDelta }); 2056 } 2057 }; 2058 EventApi.prototype.setEnd = function (endInput, options) { 2059 if (options === void 0) { options = {}; } 2060 var dateEnv = this._calendar.dateEnv; 2061 var end; 2062 if (endInput != null) { 2063 end = dateEnv.createMarker(endInput); 2064 if (!end) { 2065 return; // TODO: warning if parsed bad 2066 } 2067 } 2068 if (this._instance) { 2069 if (end) { 2070 var endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity); 2071 this.mutate({ endDelta: endDelta }); 2072 } 2073 else { 2074 this.mutate({ standardProps: { hasEnd: false } }); 2075 } 2076 } 2077 }; 2078 EventApi.prototype.setDates = function (startInput, endInput, options) { 2079 if (options === void 0) { options = {}; } 2080 var dateEnv = this._calendar.dateEnv; 2081 var standardProps = { allDay: options.allDay }; 2082 var start = dateEnv.createMarker(startInput); 2083 var end; 2084 if (!start) { 2085 return; // TODO: warning if parsed bad 2086 } 2087 if (endInput != null) { 2088 end = dateEnv.createMarker(endInput); 2089 if (!end) { // TODO: warning if parsed bad 2090 return; 2091 } 2092 } 2093 if (this._instance) { 2094 var instanceRange = this._instance.range; 2095 // when computing the diff for an event being converted to all-day, 2096 // compute diff off of the all-day values the way event-mutation does. 2097 if (options.allDay === true) { 2098 instanceRange = computeAlignedDayRange(instanceRange); 2099 } 2100 var startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); 2101 if (end) { 2102 var endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity); 2103 this.mutate({ startDelta: startDelta, endDelta: endDelta, standardProps: standardProps }); 2104 } 2105 else { 2106 standardProps.hasEnd = false;
2107 this.mutate({ startDelta: startDelta, standardProps: standardProps }); 2108 } 2109 } 2110 }; 2111 EventApi.prototype.moveStart = function (deltaInput) { 2112 var delta = createDuration(deltaInput); 2113 if (delta) { // TODO: warning if parsed bad 2114 this.mutate({ startDelta: delta }); 2115 } 2116 }; 2117 EventApi.prototype.moveEnd = function (deltaInput) { 2118 var delta = createDuration(deltaInput); 2119 if (delta) { // TODO: warning if parsed bad 2120 this.mutate({ endDelta: delta }); 2121 } 2122 }; 2123 EventApi.prototype.moveDates = function (deltaInput) { 2124 var delta = createDuration(deltaInput); 2125 if (delta) { // TODO: warning if parsed bad 2126 this.mutate({ startDelta: delta, endDelta: delta }); 2127 } 2128 }; 2129 EventApi.prototype.setAllDay = function (allDay, options) { 2130 if (options === void 0) { options = {}; } 2131 var standardProps = { allDay: allDay }; 2132 var maintainDuration = options.maintainDuration; 2133 if (maintainDuration == null) { 2134 maintainDuration = this._calendar.opt('allDayMaintainDuration'); 2135 } 2136 if (this._def.allDay !== allDay) { 2137 standardProps.hasEnd = maintainDuration; 2138 } 2139 this.mutate({ standardProps: standardProps }); 2140 }; 2141 EventApi.prototype.formatRange = function (formatInput) { 2142 var dateEnv = this._calendar.dateEnv; 2143 var instance = this._instance; 2144 var formatter = createFormatter(formatInput, this._calendar.opt('defaultRangeSeparator')); 2145 if (this._def.hasEnd) { 2146 return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, { 2147 forcedStartTzo: instance.forcedStartTzo, 2148 forcedEndTzo: instance.forcedEndTzo 2149 }); 2150 } 2151 else { 2152 return dateEnv.format(instance.range.start, formatter, { 2153 forcedTzo: instance.forcedStartTzo 2154 }); 2155 } 2156 }; 2157 EventApi.prototype.mutate = function (mutation) { 2158 var def = this._def; 2159 var instance = this._instance; 2160 if (instance) { 2161 this._calendar.dispatch({ 2162 type: 'MUTATE_EVENTS', 2163 instanceId: instance.instanceId, 2164 mutation: mutation, 2165 fromApi: true 2166 }); 2167 var eventStore = this._calendar.state.eventStore; 2168 this._def = eventStore.defs[def.defId]; 2169 this._instance = eventStore.instances[instance.instanceId]; 2170 } 2171 }; 2172 EventApi.prototype.remove = function () { 2173 this._calendar.dispatch({ 2174 type: 'REMOVE_EVENT_DEF', 2175 defId: this._def.defId 2176 }); 2177 }; 2178 Object.defineProperty(EventApi.prototype, "source", { 2179 get: function () { 2180 var sourceId = this._def.sourceId; 2181 if (sourceId) { 2182 return new EventSourceApi(this._calendar, this._calendar.state.eventSources[sourceId]); 2183 } 2184 return null; 2185 }, 2186 enumerable: true, 2187 configurable: true 2188 }); 2189 Object.defineProperty(EventApi.prototype, "start", { 2190 get: function () { 2191 return this._instance ? 2192 this._calendar.dateEnv.toDate(this._instance.range.start) : 2193 null; 2194 }, 2195 enumerable: true, 2196 configurable: true 2197 }); 2198 Object.defineProperty(EventApi.prototype, "end", { 2199 get: function () { 2200 return (this._instance && this._def.hasEnd) ? 2201 this._calendar.dateEnv.toDate(this._instance.range.end) : 2202 null; 2203 }, 2204 enumerable: true, 2205 configurable: true 2206 }); 2207 Object.defineProperty(EventApi.prototype, "id", { 2208 // computable props that all access the def
2209 // TODO: find a TypeScript-compatible way to do this at scale 2210 get: function () { return this._def.publicId; }, 2211 enumerable: true, 2212 configurable: true 2213 }); 2214 Object.defineProperty(EventApi.prototype, "groupId", { 2215 get: function () { return this._def.groupId; }, 2216 enumerable: true, 2217 configurable: true 2218 }); 2219 Object.defineProperty(EventApi.prototype, "allDay", { 2220 get: function () { return this._def.allDay; }, 2221 enumerable: true, 2222 configurable: true 2223 }); 2224 Object.defineProperty(EventApi.prototype, "title", { 2225 get: function () { return this._def.title; }, 2226 enumerable: true, 2227 configurable: true 2228 }); 2229 Object.defineProperty(EventApi.prototype, "url", { 2230 get: function () { return this._def.url; }, 2231 enumerable: true, 2232 configurable: true 2233 }); 2234 Object.defineProperty(EventApi.prototype, "rendering", { 2235 get: function () { return this._def.rendering; }, 2236 enumerable: true, 2237 configurable: true 2238 }); 2239 Object.defineProperty(EventApi.prototype, "startEditable", { 2240 get: function () { return this._def.ui.startEditable; }, 2241 enumerable: true, 2242 configurable: true 2243 }); 2244 Object.defineProperty(EventApi.prototype, "durationEditable", { 2245 get: function () { return this._def.ui.durationEditable; }, 2246 enumerable: true, 2247 configurable: true 2248 }); 2249 Object.defineProperty(EventApi.prototype, "constraint", { 2250 get: function () { return this._def.ui.constraints[0] || null; }, 2251 enumerable: true, 2252 configurable: true 2253 }); 2254 Object.defineProperty(EventApi.prototype, "overlap", { 2255 get: function () { return this._def.ui.overlap; }, 2256 enumerable: true, 2257 configurable: true 2258 }); 2259 Object.defineProperty(EventApi.prototype, "allow", { 2260 get: function () { return this._def.ui.allows[0] || null; }, 2261 enumerable: true, 2262 configurable: true 2263 }); 2264 Object.defineProperty(EventApi.prototype, "backgroundColor", { 2265 get: function () { return this._def.ui.backgroundColor; }, 2266 enumerable: true, 2267 configurable: true 2268 }); 2269 Object.defineProperty(EventApi.prototype, "borderColor", { 2270 get: function () { return this._def.ui.borderColor; }, 2271 enumerable: true, 2272 configurable: true 2273 }); 2274 Object.defineProperty(EventApi.prototype, "textColor", { 2275 get: function () { return this._def.ui.textColor; }, 2276 enumerable: true, 2277 configurable: true 2278 }); 2279 Object.defineProperty(EventApi.prototype, "classNames", { 2280 // NOTE: user can't modify these because Object.freeze was called in event-def parsing 2281 get: function () { return this._def.ui.classNames; }, 2282 enumerable: true, 2283 configurable: true 2284 }); 2285 Object.defineProperty(EventApi.prototype, "extendedProps", { 2286 get: function () { return this._def.extendedProps; }, 2287 enumerable: true, 2288 configurable: true 2289 }); 2290 return EventApi; 2291 }()); 2292 2293 /* 2294 Specifying nextDayThreshold signals that all-day ranges should be sliced. 2295 */ 2296 function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) { 2297 var inverseBgByGroupId = {}; 2298 var inverseBgByDefId = {}; 2299 var defByGroupId = {}; 2300 var bgRanges = []; 2301 var fgRanges = []; 2302 var eventUis = compileEventUis(eventStore.defs, eventUiBases); 2303 for (var defId in eventStore.defs) { 2304 var def = eventStore.defs[defId]; 2305 if (def.rendering === 'inverse-background') { 2306 if (def.groupId) { 2307 inverseBgByGroupId[def.groupId] = []; 2308 if (!defByGroupId[def.groupId]) { 2309 defByGroupId[def.groupId] = def; 2310 } 2311 } 2312 else { 2313 inverseBgByDefId[defId] = []; 2314 } 2315 } 2316 } 2317 for (var instanceId in eventStore.instances) { 2318 var instance = eventStore.instances[instanceId]; 2319 var def = eventStore.defs[instance.defId]; 2320 var ui = eventUis[def.defId]; 2321 var origRange = instance.range; 2322 var normalRange = (!def.allDay && nextDayThreshold) ? 2323 computeVisibleDayRange(origRange, nextDayThreshold) : 2324 origRange; 2325 var slicedRange = intersectRanges(normalRange, framingRange); 2326 if (slicedRange) { 2327 if (def.rendering === 'inverse-background') { 2328 if (def.groupId) { 2329 inverseBgByGroupId[def.groupId].push(slicedRange); 2330 } 2331 else { 2332 inverseBgByDefId[instance.defId].push(slicedRange); 2333 } 2334 } 2335 else { 2336 (def.rendering === 'background' ? bgRanges : fgRanges).push({ 2337 def: def, 2338 ui: ui, 2339 instance: instance, 2340 range: slicedRange, 2341 isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(), 2342 isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf() 2343 }); 2344 } 2345 } 2346 } 2347 for (var groupId in inverseBgByGroupId) { // BY GROUP 2348 var ranges = inverseBgByGroupId[groupId]; 2349 var invertedRanges = invertRanges(ranges, framingRange); 2350 for (var _i = 0, invertedRanges_1 = invertedRanges; _i < invertedRanges_1.length; _i++) { 2351 var invertedRange = invertedRanges_1[_i]; 2352 var def = defByGroupId[groupId]; 2353 var ui = eventUis[def.defId]; 2354 bgRanges.push({ 2355 def: def, 2356 ui: ui, 2357 instance: null, 2358 range: invertedRange, 2359 isStart: false, 2360 isEnd: false 2361 }); 2362 } 2363 } 2364 for (var defId in inverseBgByDefId) { 2365 var ranges = inverseBgByDefId[defId]; 2366 var invertedRanges = invertRanges(ranges, framingRange); 2367 for (var _a = 0, invertedRanges_2 = invertedRanges; _a < invertedRanges_2.length; _a++) { 2368 var invertedRange = invertedRanges_2[_a]; 2369 bgRanges.push({ 2370 def: eventStore.defs[defId], 2371 ui: eventUis[defId], 2372 instance: null, 2373 range: invertedRange, 2374 isStart: false, 2375 isEnd: false 2376 }); 2377 } 2378 } 2379 return { bg: bgRanges, fg: fgRanges }; 2380 } 2381 function hasBgRendering(def) { 2382 return def.rendering === 'background' || def.rendering === 'inverse-background'; 2383 } 2384 function filterSegsViaEls(view, segs, isMirror) { 2385 if (view.hasPublicHandlers('eventRender')) { 2386 segs = segs.filter(function (seg) { 2387 var custom = view.publiclyTrigger('eventRender', [ 2388 { 2389 event: new EventApi(view.calendar, seg.eventRange.def, seg.eventRange.instance), 2390 isMirror: isMirror, 2391 isStart: seg.isStart, 2392 isEnd: seg.isEnd, 2393 // TODO: include seg.range once all components consistently generate it 2394 el: seg.el, 2395 view: view 2396 } 2397 ]); 2398 if (custom === false) { // means don't render at all 2399 return false;
2400 } 2401 else if (custom && custom !== true) { 2402 seg.el = custom; 2403 } 2404 return true; 2405 }); 2406 } 2407 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 2408 var seg = segs_1[_i]; 2409 setElSeg(seg.el, seg); 2410 } 2411 return segs; 2412 } 2413 function setElSeg(el, seg) { 2414 el.fcSeg = seg; 2415 } 2416 function getElSeg(el) { 2417 return el.fcSeg || null; 2418 } 2419 // event ui computation 2420 function compileEventUis(eventDefs, eventUiBases) { 2421 return mapHash(eventDefs, function (eventDef) { 2422 return compileEventUi(eventDef, eventUiBases); 2423 }); 2424 } 2425 function compileEventUi(eventDef, eventUiBases) { 2426 var uis = []; 2427 if (eventUiBases['']) { 2428 uis.push(eventUiBases['']); 2429 } 2430 if (eventUiBases[eventDef.defId]) { 2431 uis.push(eventUiBases[eventDef.defId]); 2432 } 2433 uis.push(eventDef.ui); 2434 return combineEventUis(uis); 2435 } 2436 2437 // applies the mutation to ALL defs/instances within the event store 2438 function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) { 2439 var eventConfigs = compileEventUis(eventStore.defs, eventConfigBase); 2440 var dest = createEmptyEventStore(); 2441 for (var defId in eventStore.defs) { 2442 var def = eventStore.defs[defId]; 2443 dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, calendar.pluginSystem.hooks.eventDefMutationAppliers, calendar); 2444 } 2445 for (var instanceId in eventStore.instances) { 2446 var instance = eventStore.instances[instanceId]; 2447 var def = dest.defs[instance.defId]; // important to grab the newly modified def 2448 dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, calendar); 2449 } 2450 return dest; 2451 } 2452 function applyMutationToEventDef(eventDef, eventConfig, mutation, appliers, calendar) { 2453 var standardProps = mutation.standardProps || {}; 2454 // if hasEnd has not been specified, guess a good value based on deltas. 2455 // if duration will change, there's no way the default duration will persist, 2456 // and thus, we need to mark the event as having a real end 2457 if (standardProps.hasEnd == null && 2458 eventConfig.durationEditable && 2459 willDeltasAffectDuration(eventConfig.startEditable ? mutation.startDelta : null, mutation.endDelta || null)) { 2460 standardProps.hasEnd = true; // TODO: is this mutation okay? 2461 } 2462 var copy = __assign({}, eventDef, standardProps, { ui: __assign({}, eventDef.ui, standardProps.ui) }); 2463 if (mutation.extendedProps) { 2464 copy.extendedProps = __assign({}, copy.extendedProps, mutation.extendedProps); 2465 } 2466 for (var _i = 0, appliers_1 = appliers; _i < appliers_1.length; _i++) { 2467 var applier = appliers_1[_i]; 2468 applier(copy, mutation, calendar); 2469 } 2470 if (!copy.hasEnd && calendar.opt('forceEventDuration')) { 2471 copy.hasEnd = true; 2472 } 2473 return copy; 2474 } 2475 function willDeltasAffectDuration(startDelta, endDelta) { 2476 if (startDelta && !asRoughMs(startDelta)) { 2477 startDelta = null; 2478 } 2479 if (endDelta && !asRoughMs(endDelta)) { 2480 endDelta = null; 2481 } 2482 if (!startDelta && !endDelta) { 2483 return false; 2484 } 2485 if (Boolean(startDelta) !== Boolean(endDelta)) { 2486 return true; 2487 } 2488 return !durationsEqual(startDelta, endDelta); 2489 } 2490 function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef 2491 eventConfig, mutation, calendar) { 2492 var dateEnv = calendar.dateEnv; 2493 var forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true; 2494 var clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false; 2495 var copy = __assign({}, eventInstance); 2496 if (forceAllDay) { 2497 copy.range = computeAlignedDayRange(copy.range); 2498 } 2499 if (mutation.startDelta && eventConfig.startEditable) { 2500 copy.range = { 2501 start: dateEnv.add(copy.range.start, mutation.startDelta), 2502 end: copy.range.end 2503 }; 2504 } 2505 if (clearEnd) { 2506 copy.range = { 2507 start: copy.range.start, 2508 end: calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start) 2509 }; 2510 } 2511 else if (mutation.endDelta && 2512 (eventConfig.durationEditable || 2513 !willDeltasAffectDuration(// TODO: nonDRY logic above 2514 eventConfig.startEditable ? mutation.startDelta : null, mutation.endDelta))) { 2515 copy.range = { 2516 start: copy.range.start, 2517 end: dateEnv.add(copy.range.end, mutation.endDelta) 2518 }; 2519 } 2520 // in case event was all-day but the supplied deltas were not 2521 // better util for this? 2522 if (eventDef.allDay) { 2523 copy.range = { 2524 start: startOfDay(copy.range.start), 2525 end: startOfDay(copy.range.end) 2526 }; 2527 } 2528 // handle invalid durations 2529 if (copy.range.end < copy.range.start) { 2530 copy.range.end = calendar.getDefaultEventEnd(eventDef.allDay, copy.range.start); 2531 } 2532 return copy; 2533 } 2534 2535 function reduceEventStore (eventStore, action, eventSources, dateProfile, calendar) { 2536 switch (action.type) { 2537 case 'RECEIVE_EVENTS': // raw 2538 return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, calendar); 2539 case 'ADD_EVENTS': // already parsed, but not expanded 2540 return addEvent(eventStore, action.eventStore, // new ones 2541 dateProfile ? dateProfile.activeRange : null, calendar); 2542 case 'MERGE_EVENTS': // already parsed and expanded 2543 return mergeEventStores(eventStore, action.eventStore); 2544 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 2545 case 'NEXT': 2546 case 'SET_DATE': 2547 case 'SET_VIEW_TYPE': 2548 if (dateProfile) { 2549 return expandRecurring(eventStore, dateProfile.activeRange, calendar); 2550 } 2551 else { 2552 return eventStore; 2553 } 2554 case 'CHANGE_TIMEZONE': 2555 return rezoneDates(eventStore, action.oldDateEnv, calendar.dateEnv); 2556 case 'MUTATE_EVENTS': 2557 return applyMutationToRelated(eventStore, action.instanceId, action.mutation, action.fromApi, calendar);
2558 case 'REMOVE_EVENT_INSTANCES': 2559 return excludeInstances(eventStore, action.instances); 2560 case 'REMOVE_EVENT_DEF': 2561 return filterEventStoreDefs(eventStore, function (eventDef) { 2562 return eventDef.defId !== action.defId; 2563 }); 2564 case 'REMOVE_EVENT_SOURCE': 2565 return excludeEventsBySourceId(eventStore, action.sourceId); 2566 case 'REMOVE_ALL_EVENT_SOURCES': 2567 return filterEventStoreDefs(eventStore, function (eventDef) { 2568 return !eventDef.sourceId; // only keep events with no source id 2569 }); 2570 case 'REMOVE_ALL_EVENTS': 2571 return createEmptyEventStore(); 2572 case 'RESET_EVENTS': 2573 return { 2574 defs: eventStore.defs, 2575 instances: eventStore.instances 2576 }; 2577 default: 2578 return eventStore; 2579 } 2580 } 2581 function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, calendar) { 2582 if (eventSource && // not already removed 2583 fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources 2584 ) { 2585 var subset = parseEvents(transformRawEvents(rawEvents, eventSource, calendar), eventSource.sourceId, calendar); 2586 if (fetchRange) { 2587 subset = expandRecurring(subset, fetchRange, calendar); 2588 } 2589 return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset); 2590 } 2591 return eventStore; 2592 } 2593 function addEvent(eventStore, subset, expandRange, calendar) { 2594 if (expandRange) { 2595 subset = expandRecurring(subset, expandRange, calendar); 2596 } 2597 return mergeEventStores(eventStore, subset); 2598 } 2599 function rezoneDates(eventStore, oldDateEnv, newDateEnv) { 2600 var defs = eventStore.defs; 2601 var instances = mapHash(eventStore.instances, function (instance) { 2602 var def = defs[instance.defId]; 2603 if (def.allDay || def.recurringDef) { 2604 return instance; // isn't dependent on timezone 2605 } 2606 else { 2607 return __assign({}, instance, { range: { 2608 start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)), 2609 end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)) 2610 }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo }); 2611 } 2612 }); 2613 return { defs: defs, instances: instances }; 2614 } 2615 function applyMutationToRelated(eventStore, instanceId, mutation, fromApi, calendar) { 2616 var relevant = getRelevantEvents(eventStore, instanceId); 2617 var eventConfigBase = fromApi ? 2618 { '': { 2619 startEditable: true, 2620 durationEditable: true, 2621 constraints: [], 2622 overlap: null, 2623 allows: [], 2624 backgroundColor: '', 2625 borderColor: '', 2626 textColor: '', 2627 classNames: [] 2628 } } : 2629 calendar.eventUiBases; 2630 relevant = applyMutationToEventStore(relevant, eventConfigBase, mutation, calendar); 2631 return mergeEventStores(eventStore, relevant); 2632 } 2633 function excludeEventsBySourceId(eventStore, sourceId) { 2634 return filterEventStoreDefs(eventStore, function (eventDef) { 2635 return eventDef.sourceId !== sourceId; 2636 }); 2637 } 2638 // QUESTION: why not just return instances? do a general object-property-exclusion util 2639 function excludeInstances(eventStore, removals) { 2640 return { 2641 defs: eventStore.defs, 2642 instances: filterHash(eventStore.instances, function (instance) { 2643 return !removals[instance.instanceId]; 2644 }) 2645 }; 2646 } 2647 2648 // high-level segmenting-aware tester functions 2649 // ------------------------------------------------------------------------------------------------------------------------ 2650 function isInteractionValid(interaction, calendar) { 2651 return isNewPropsValid({ eventDrag: interaction }, calendar); // HACK: the eventDrag props is used for ALL interactions 2652 } 2653 function isDateSelectionValid(dateSelection, calendar) { 2654 return isNewPropsValid({ dateSelection: dateSelection }, calendar); 2655 } 2656 function isNewPropsValid(newProps, calendar) { 2657 var view = calendar.view; 2658 var props = __assign({ businessHours: view ? view.props.businessHours : createEmptyEventStore(), dateSelection: '', eventStore: calendar.state.eventStore, eventUiBases: calendar.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps); 2659 return (calendar.pluginSystem.hooks.isPropsValid || isPropsValid)(props, calendar); 2660 } 2661 function isPropsValid(state, calendar, dateSpanMeta, filterConfig) {
2662 if (dateSpanMeta === void 0) { dateSpanMeta = {}; } 2663 if (state.eventDrag && !isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { 2664 return false; 2665 } 2666 if (state.dateSelection && !isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig)) { 2667 return false; 2668 } 2669 return true; 2670 } 2671 // Moving Event Validation 2672 // ------------------------------------------------------------------------------------------------------------------------ 2673 function isInteractionPropsValid(state, calendar, dateSpanMeta, filterConfig) { 2674 var interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions 2675 var subjectEventStore = interaction.mutatedEvents; 2676 var subjectDefs = subjectEventStore.defs; 2677 var subjectInstances = subjectEventStore.instances; 2678 var subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ? 2679 state.eventUiBases : 2680 { '': calendar.selectionConfig } // if not a real event, validate as a selection 2681 ); 2682 if (filterConfig) { 2683 subjectConfigs = mapHash(subjectConfigs, filterConfig); 2684 } 2685 var otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances); // exclude the subject events. TODO: exclude defs too? 2686 var otherDefs = otherEventStore.defs; 2687 var otherInstances = otherEventStore.instances; 2688 var otherConfigs = compileEventUis(otherDefs, state.eventUiBases); 2689 for (var subjectInstanceId in subjectInstances) { 2690 var subjectInstance = subjectInstances[subjectInstanceId]; 2691 var subjectRange = subjectInstance.range; 2692 var subjectConfig = subjectConfigs[subjectInstance.defId]; 2693 var subjectDef = subjectDefs[subjectInstance.defId]; 2694 // constraint 2695 if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, calendar)) { 2696 return false; 2697 } 2698 // overlap 2699 var overlapFunc = calendar.opt('eventOverlap'); 2700 if (typeof overlapFunc !== 'function') { 2701 overlapFunc = null; 2702 } 2703 for (var otherInstanceId in otherInstances) { 2704 var otherInstance = otherInstances[otherInstanceId]; 2705 // intersect! evaluate 2706 if (rangesIntersect(subjectRange, otherInstance.range)) { 2707 var otherOverlap = otherConfigs[otherInstance.defId].overlap; 2708 // consider the other event's overlap. only do this if the subject event is a "real" event 2709 if (otherOverlap === false && interaction.isEvent) { 2710 return false; 2711 } 2712 if (subjectConfig.overlap === false) { 2713 return false; 2714 } 2715 if (overlapFunc && !overlapFunc(new EventApi(calendar, otherDefs[otherInstance.defId], otherInstance), // still event 2716 new EventApi(calendar, subjectDef, subjectInstance) // moving event 2717 )) { 2718 return false; 2719 } 2720 } 2721 } 2722 // allow (a function) 2723 for (var _i = 0, _a = subjectConfig.allows; _i < _a.length; _i++) { 2724 var subjectAllow = _a[_i]; 2725 var subjectDateSpan = __assign({}, dateSpanMeta, { range: subjectInstance.range, allDay: subjectDef.allDay }); 2726 var origDef = state.eventStore.defs[subjectDef.defId]; 2727 var origInstance = state.eventStore.instances[subjectInstanceId]; 2728 var eventApi = void 0; 2729 if (origDef) { // was previously in the calendar 2730 eventApi = new EventApi(calendar, origDef, origInstance); 2731 } 2732 else { // was an external event 2733 eventApi = new EventApi(calendar, subjectDef); // no instance, because had no dates 2734 } 2735 if (!subjectAllow(calendar.buildDateSpanApi(subjectDateSpan), eventApi)) { 2736 return false;
2737 } 2738 } 2739 } 2740 return true; 2741 } 2742 // Date Selection Validation 2743 // ------------------------------------------------------------------------------------------------------------------------ 2744 function isDateSelectionPropsValid(state, calendar, dateSpanMeta, filterConfig) { 2745 var relevantEventStore = state.eventStore; 2746 var relevantDefs = relevantEventStore.defs; 2747 var relevantInstances = relevantEventStore.instances; 2748 var selection = state.dateSelection; 2749 var selectionRange = selection.range; 2750 var selectionConfig = calendar.selectionConfig; 2751 if (filterConfig) { 2752 selectionConfig = filterConfig(selectionConfig); 2753 } 2754 // constraint 2755 if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, calendar)) { 2756 return false; 2757 } 2758 // overlap 2759 var overlapFunc = calendar.opt('selectOverlap'); 2760 if (typeof overlapFunc !== 'function') { 2761 overlapFunc = null; 2762 } 2763 for (var relevantInstanceId in relevantInstances) { 2764 var relevantInstance = relevantInstances[relevantInstanceId]; 2765 // intersect! evaluate 2766 if (rangesIntersect(selectionRange, relevantInstance.range)) { 2767 if (selectionConfig.overlap === false) { 2768 return false; 2769 } 2770 if (overlapFunc && !overlapFunc(new EventApi(calendar, relevantDefs[relevantInstance.defId], relevantInstance))) { 2771 return false; 2772 } 2773 } 2774 } 2775 // allow (a function) 2776 for (var _i = 0, _a = selectionConfig.allows; _i < _a.length; _i++) { 2777 var selectionAllow = _a[_i]; 2778 var fullDateSpan = __assign({}, dateSpanMeta, selection); 2779 if (!selectionAllow(calendar.buildDateSpanApi(fullDateSpan), null)) { 2780 return false; 2781 } 2782 } 2783 return true; 2784 } 2785 // Constraint Utils 2786 // ------------------------------------------------------------------------------------------------------------------------ 2787 function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, calendar) { 2788 for (var _i = 0, constraints_1 = constraints; _i < constraints_1.length; _i++) { 2789 var constraint = constraints_1[_i]; 2790 if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, calendar), subjectRange)) { 2791 return false; 2792 } 2793 } 2794 return true; 2795 } 2796 function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours 2797 otherEventStore, // for if constraint is an even group ID 2798 businessHoursUnexpanded, // for if constraint is 'businessHours' 2799 calendar // for expanding businesshours 2800 ) { 2801 if (constraint === 'businessHours') { 2802 return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, calendar)); 2803 } 2804 else if (typeof constraint === 'string') { // an group ID 2805 return eventStoreToRanges(filterEventStoreDefs(otherEventStore, function (eventDef) { 2806 return eventDef.groupId === constraint; 2807 })); 2808 } 2809 else if (typeof constraint === 'object' && constraint) { // non-null object 2810 return eventStoreToRanges(expandRecurring(constraint, subjectRange, calendar)); 2811 } 2812 return []; // if it's false 2813 } 2814 // TODO: move to event-store file? 2815 function eventStoreToRanges(eventStore) { 2816 var instances = eventStore.instances; 2817 var ranges = []; 2818 for (var instanceId in instances) { 2819 ranges.push(instances[instanceId].range); 2820 } 2821 return ranges; 2822 } 2823 // TODO: move to geom file? 2824 function anyRangesContainRange(outerRanges, innerRange) { 2825 for (var _i = 0, outerRanges_1 = outerRanges; _i < outerRanges_1.length; _i++) { 2826 var outerRange = outerRanges_1[_i]; 2827 if (rangeContainsRange(outerRange, innerRange)) { 2828 return true; 2829 } 2830 } 2831 return false;
2832 } 2833 // Parsing 2834 // ------------------------------------------------------------------------------------------------------------------------ 2835 function normalizeConstraint(input, calendar) { 2836 if (Array.isArray(input)) { 2837 return parseEvents(input, '', calendar, true); // allowOpenRange=true 2838 } 2839 else if (typeof input === 'object' && input) { // non-null object 2840 return parseEvents([input], '', calendar, true); // allowOpenRange=true 2841 } 2842 else if (input != null) { 2843 return String(input); 2844 } 2845 else { 2846 return null; 2847 } 2848 } 2849 2850 function htmlEscape(s) { 2851 return (s + '').replace(/&/g, '&') 2852 .replace(/</g, '<') 2853 .replace(/>/g, '>') 2854 .replace(/'/g, ''') 2855 .replace(/"/g, '"') 2856 .replace(/\n/g, '<br />'); 2857 } 2858 // Given a hash of CSS properties, returns a string of CSS. 2859 // Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values. 2860 function cssToStr(cssProps) { 2861 var statements = []; 2862 for (var name_1 in cssProps) { 2863 var val = cssProps[name_1]; 2864 if (val != null && val !== '') { 2865 statements.push(name_1 + ':' + val); 2866 } 2867 } 2868 return statements.join(';'); 2869 } 2870 // Given an object hash of HTML attribute names to values, 2871 // generates a string that can be injected between < > in HTML 2872 function attrsToStr(attrs) { 2873 var parts = []; 2874 for (var name_2 in attrs) { 2875 var val = attrs[name_2]; 2876 if (val != null) { 2877 parts.push(name_2 + '="' + htmlEscape(val) + '"'); 2878 } 2879 } 2880 return parts.join(' '); 2881 } 2882 function parseClassName(raw) { 2883 if (Array.isArray(raw)) { 2884 return raw; 2885 } 2886 else if (typeof raw === 'string') { 2887 return raw.split(/\s+/); 2888 } 2889 else { 2890 return []; 2891 } 2892 } 2893 2894 var UNSCOPED_EVENT_UI_PROPS = { 2895 editable: Boolean, 2896 startEditable: Boolean, 2897 durationEditable: Boolean, 2898 constraint: null, 2899 overlap: null, 2900 allow: null, 2901 className: parseClassName, 2902 classNames: parseClassName, 2903 color: String, 2904 backgroundColor: String, 2905 borderColor: String, 2906 textColor: String 2907 }; 2908 function processUnscopedUiProps(rawProps, calendar, leftovers) { 2909 var props = refineProps(rawProps, UNSCOPED_EVENT_UI_PROPS, {}, leftovers); 2910 var constraint = normalizeConstraint(props.constraint, calendar); 2911 return { 2912 startEditable: props.startEditable != null ? props.startEditable : props.editable, 2913 durationEditable: props.durationEditable != null ? props.durationEditable : props.editable, 2914 constraints: constraint != null ? [constraint] : [], 2915 overlap: props.overlap, 2916 allows: props.allow != null ? [props.allow] : [], 2917 backgroundColor: props.backgroundColor || props.color, 2918 borderColor: props.borderColor || props.color, 2919 textColor: props.textColor, 2920 classNames: props.classNames.concat(props.className) 2921 }; 2922 } 2923 function processScopedUiProps(prefix, rawScoped, calendar, leftovers) { 2924 var rawUnscoped = {}; 2925 var wasFound = {}; 2926 for (var key in UNSCOPED_EVENT_UI_PROPS) { 2927 var scopedKey = prefix + capitaliseFirstLetter(key); 2928 rawUnscoped[key] = rawScoped[scopedKey]; 2929 wasFound[scopedKey] = true; 2930 } 2931 if (prefix === 'event') { 2932 rawUnscoped.editable = rawScoped.editable; // special case. there is no 'eventEditable', just 'editable' 2933 } 2934 if (leftovers) { 2935 for (var key in rawScoped) { 2936 if (!wasFound[key]) { 2937 leftovers[key] = rawScoped[key]; 2938 } 2939 } 2940 } 2941 return processUnscopedUiProps(rawUnscoped, calendar); 2942 } 2943 var EMPTY_EVENT_UI = { 2944 startEditable: null, 2945 durationEditable: null, 2946 constraints: [], 2947 overlap: null, 2948 allows: [], 2949 backgroundColor: '', 2950 borderColor: '', 2951 textColor: '', 2952 classNames: [] 2953 }; 2954 // prevent against problems with <2 args! 2955 function combineEventUis(uis) { 2956 return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI); 2957 } 2958 function combineTwoEventUis(item0, item1) { 2959 return { 2960 startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable, 2961 durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable, 2962 constraints: item0.constraints.concat(item1.constraints), 2963 overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap, 2964 allows: item0.allows.concat(item1.allows), 2965 backgroundColor: item1.backgroundColor || item0.backgroundColor, 2966 borderColor: item1.borderColor || item0.borderColor, 2967 textColor: item1.textColor || item0.textColor,
2968 classNames: item0.classNames.concat(item1.classNames) 2969 }; 2970 } 2971 2972 var NON_DATE_PROPS = { 2973 id: String, 2974 groupId: String, 2975 title: String, 2976 url: String, 2977 rendering: String, 2978 extendedProps: null 2979 }; 2980 var DATE_PROPS = { 2981 start: null, 2982 date: null, 2983 end: null, 2984 allDay: null 2985 }; 2986 var uid = 0; 2987 function parseEvent(raw, sourceId, calendar, allowOpenRange) { 2988 var allDayDefault = computeIsAllDayDefault(sourceId, calendar); 2989 var leftovers0 = {}; 2990 var recurringRes = parseRecurring(raw, // raw, but with single-event stuff stripped out 2991 allDayDefault, calendar.dateEnv, calendar.pluginSystem.hooks.recurringTypes, leftovers0 // will populate with non-recurring props 2992 ); 2993 if (recurringRes) { 2994 var def = parseEventDef(leftovers0, sourceId, recurringRes.allDay, Boolean(recurringRes.duration), calendar); 2995 def.recurringDef = { 2996 typeId: recurringRes.typeId, 2997 typeData: recurringRes.typeData, 2998 duration: recurringRes.duration 2999 }; 3000 return { def: def, instance: null }; 3001 } 3002 else { 3003 var leftovers1 = {}; 3004 var singleRes = parseSingle(raw, allDayDefault, calendar, leftovers1, allowOpenRange); 3005 if (singleRes) { 3006 var def = parseEventDef(leftovers1, sourceId, singleRes.allDay, singleRes.hasEnd, calendar); 3007 var instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo); 3008 return { def: def, instance: instance }; 3009 } 3010 } 3011 return null; 3012 } 3013 /* 3014 Will NOT populate extendedProps with the leftover properties. 3015 Will NOT populate date-related props. 3016 The EventNonDateInput has been normalized (id => publicId, etc). 3017 */ 3018 function parseEventDef(raw, sourceId, allDay, hasEnd, calendar) { 3019 var leftovers = {}; 3020 var def = pluckNonDateProps(raw, calendar, leftovers); 3021 def.defId = String(uid++); 3022 def.sourceId = sourceId; 3023 def.allDay = allDay; 3024 def.hasEnd = hasEnd; 3025 for (var _i = 0, _a = calendar.pluginSystem.hooks.eventDefParsers; _i < _a.length; _i++) { 3026 var eventDefParser = _a[_i]; 3027 var newLeftovers = {}; 3028 eventDefParser(def, leftovers, newLeftovers); 3029 leftovers = newLeftovers; 3030 } 3031 def.extendedProps = __assign(leftovers, def.extendedProps || {}); 3032 // help out EventApi from having user modify props 3033 Object.freeze(def.ui.classNames); 3034 Object.freeze(def.extendedProps); 3035 return def; 3036 } 3037 function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) { 3038 return { 3039 instanceId: String(uid++), 3040 defId: defId, 3041 range: range, 3042 forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo, 3043 forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo 3044 }; 3045 } 3046 function parseSingle(raw, allDayDefault, calendar, leftovers, allowOpenRange) { 3047 var props = pluckDateProps(raw, leftovers); 3048 var allDay = props.allDay; 3049 var startMeta; 3050 var startMarker = null; 3051 var hasEnd = false; 3052 var endMeta; 3053 var endMarker = null; 3054 startMeta = calendar.dateEnv.createMarkerMeta(props.start); 3055 if (startMeta) { 3056 startMarker = startMeta.marker; 3057 } 3058 else if (!allowOpenRange) { 3059 return null; 3060 } 3061 if (props.end != null) { 3062 endMeta = calendar.dateEnv.createMarkerMeta(props.end); 3063 } 3064 if (allDay == null) { 3065 if (allDayDefault != null) { 3066 allDay = allDayDefault; 3067 } 3068 else { 3069 // fall back to the date props LAST 3070 allDay = (!startMeta || startMeta.isTimeUnspecified) && 3071 (!endMeta || endMeta.isTimeUnspecified); 3072 } 3073 } 3074 if (allDay && startMarker) { 3075 startMarker = startOfDay(startMarker); 3076 } 3077 if (endMeta) { 3078 endMarker = endMeta.marker; 3079 if (allDay) { 3080 endMarker = startOfDay(endMarker); 3081 } 3082 if (startMarker && endMarker <= startMarker) { 3083 endMarker = null; 3084 } 3085 } 3086 if (endMarker) { 3087 hasEnd = true; 3088 } 3089 else if (!allowOpenRange) { 3090 hasEnd = calendar.opt('forceEventDuration') || false; 3091 endMarker = calendar.dateEnv.add(startMarker, allDay ? 3092 calendar.defaultAllDayEventDuration : 3093 calendar.defaultTimedEventDuration); 3094 } 3095 return { 3096 allDay: allDay, 3097 hasEnd: hasEnd, 3098 range: { start: startMarker, end: endMarker }, 3099 forcedStartTzo: startMeta ? startMeta.forcedTzo : null, 3100 forcedEndTzo: endMeta ? endMeta.forcedTzo : null 3101 }; 3102 } 3103 function pluckDateProps(raw, leftovers) { 3104 var props = refineProps(raw, DATE_PROPS, {}, leftovers); 3105 props.start = (props.start !== null) ? props.start : props.date; 3106 delete props.date; 3107 return props; 3108 } 3109 function pluckNonDateProps(raw, calendar, leftovers) { 3110 var preLeftovers = {}; 3111 var props = refineProps(raw, NON_DATE_PROPS, {}, preLeftovers); 3112 var ui = processUnscopedUiProps(preLeftovers, calendar, leftovers); 3113 props.publicId = props.id; 3114 delete props.id; 3115 props.ui = ui; 3116 return props; 3117 } 3118 function computeIsAllDayDefault(sourceId, calendar) { 3119 var res = null; 3120 if (sourceId) { 3121 var source = calendar.state.eventSources[sourceId]; 3122 res = source.allDayDefault; 3123 } 3124 if (res == null) { 3125 res = calendar.opt('allDayDefault'); 3126 } 3127 return res; 3128 } 3129 3130 var DEF_DEFAULTS = { 3131 startTime: '09:00', 3132 endTime: '17:00', 3133 daysOfWeek: [1, 2, 3, 4, 5], 3134 rendering: 'inverse-background', 3135 classNames: 'fc-nonbusiness', 3136 groupId: '_businessHours' // so multiple defs get grouped 3137 }; 3138 /* 3139 TODO: pass around as EventDefHash!!! 3140 */ 3141 function parseBusinessHours(input, calendar) { 3142 return parseEvents(refineInputs(input), '', calendar); 3143 } 3144 function refineInputs(input) { 3145 var rawDefs; 3146 if (input === true) { 3147 rawDefs = [{}]; // will get DEF_DEFAULTS verbatim 3148 } 3149 else if (Array.isArray(input)) { 3150 // if specifying an array, every sub-definition NEEDS a day-of-week 3151 rawDefs = input.filter(function (rawDef) { 3152 return rawDef.daysOfWeek; 3153 }); 3154 } 3155 else if (typeof input === 'object' && input) { // non-null object 3156 rawDefs = [input]; 3157 } 3158 else { // is probably false 3159 rawDefs = []; 3160 } 3161 rawDefs = rawDefs.map(function (rawDef) { 3162 return __assign({}, DEF_DEFAULTS, rawDef); 3163 }); 3164 return rawDefs; 3165 } 3166 3167 function memoizeRendering(renderFunc, unrenderFunc, dependencies) { 3168 if (dependencies === void 0) { dependencies = []; } 3169 var dependents = []; 3170 var thisContext; 3171 var prevArgs; 3172 function unrender() { 3173 if (prevArgs) {
3174 for (var _i = 0, dependents_1 = dependents; _i < dependents_1.length; _i++) { 3175 var dependent = dependents_1[_i]; 3176 dependent.unrender(); 3177 } 3178 if (unrenderFunc) { 3179 unrenderFunc.apply(thisContext, prevArgs); 3180 } 3181 prevArgs = null; 3182 } 3183 } 3184 function res() { 3185 if (!prevArgs || !isArraysEqual(prevArgs, arguments)) { 3186 unrender(); 3187 thisContext = this; 3188 prevArgs = arguments; 3189 renderFunc.apply(this, arguments); 3190 } 3191 } 3192 res.dependents = dependents; 3193 res.unrender = unrender; 3194 for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) { 3195 var dependency = dependencies_1[_i]; 3196 dependency.dependents.push(res); 3197 } 3198 return res; 3199 } 3200 3201 var EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere 3202 var Splitter = /** @class */ (function () { 3203 function Splitter() { 3204 this.getKeysForEventDefs = memoize(this._getKeysForEventDefs); 3205 this.splitDateSelection = memoize(this._splitDateSpan); 3206 this.splitEventStore = memoize(this._splitEventStore); 3207 this.splitIndividualUi = memoize(this._splitIndividualUi); 3208 this.splitEventDrag = memoize(this._splitInteraction); 3209 this.splitEventResize = memoize(this._splitInteraction); 3210 this.eventUiBuilders = {}; // TODO: typescript protection 3211 } 3212 Splitter.prototype.splitProps = function (props) { 3213 var _this = this; 3214 var keyInfos = this.getKeyInfo(props); 3215 var defKeys = this.getKeysForEventDefs(props.eventStore); 3216 var dateSelections = this.splitDateSelection(props.dateSelection); 3217 var individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases* 3218 var eventStores = this.splitEventStore(props.eventStore, defKeys); 3219 var eventDrags = this.splitEventDrag(props.eventDrag); 3220 var eventResizes = this.splitEventResize(props.eventResize); 3221 var splitProps = {}; 3222 this.eventUiBuilders = mapHash(keyInfos, function (info, key) { 3223 return _this.eventUiBuilders[key] || memoize(buildEventUiForKey); 3224 }); 3225 for (var key in keyInfos) { 3226 var keyInfo = keyInfos[key]; 3227 var eventStore = eventStores[key] || EMPTY_EVENT_STORE; 3228 var buildEventUi = this.eventUiBuilders[key]; 3229 splitProps[key] = { 3230 businessHours: keyInfo.businessHours || props.businessHours, 3231 dateSelection: dateSelections[key] || null, 3232 eventStore: eventStore, 3233 eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]), 3234 eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '', 3235 eventDrag: eventDrags[key] || null, 3236 eventResize: eventResizes[key] || null 3237 }; 3238 } 3239 return splitProps; 3240 }; 3241 Splitter.prototype._splitDateSpan = function (dateSpan) { 3242 var dateSpans = {}; 3243 if (dateSpan) { 3244 var keys = this.getKeysForDateSpan(dateSpan); 3245 for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { 3246 var key = keys_1[_i]; 3247 dateSpans[key] = dateSpan; 3248 } 3249 } 3250 return dateSpans; 3251 }; 3252 Splitter.prototype._getKeysForEventDefs = function (eventStore) { 3253 var _this = this; 3254 return mapHash(eventStore.defs, function (eventDef) { 3255 return _this.getKeysForEventDef(eventDef); 3256 }); 3257 }; 3258 Splitter.prototype._splitEventStore = function (eventStore, defKeys) { 3259 var defs = eventStore.defs, instances = eventStore.instances; 3260 var splitStores = {}; 3261 for (var defId in defs) { 3262 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 3263 var key = _a[_i]; 3264 if (!splitStores[key]) { 3265 splitStores[key] = createEmptyEventStore(); 3266 }
3267 splitStores[key].defs[defId] = defs[defId]; 3268 } 3269 } 3270 for (var instanceId in instances) { 3271 var instance = instances[instanceId]; 3272 for (var _b = 0, _c = defKeys[instance.defId]; _b < _c.length; _b++) { 3273 var key = _c[_b]; 3274 if (splitStores[key]) { // must have already been created 3275 splitStores[key].instances[instanceId] = instance; 3276 } 3277 } 3278 } 3279 return splitStores; 3280 }; 3281 Splitter.prototype._splitIndividualUi = function (eventUiBases, defKeys) { 3282 var splitHashes = {}; 3283 for (var defId in eventUiBases) { 3284 if (defId) { // not the '' key 3285 for (var _i = 0, _a = defKeys[defId]; _i < _a.length; _i++) { 3286 var key = _a[_i]; 3287 if (!splitHashes[key]) { 3288 splitHashes[key] = {}; 3289 } 3290 splitHashes[key][defId] = eventUiBases[defId]; 3291 } 3292 } 3293 } 3294 return splitHashes; 3295 }; 3296 Splitter.prototype._splitInteraction = function (interaction) { 3297 var splitStates = {}; 3298 if (interaction) { 3299 var affectedStores_1 = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents) // can't use cached. might be events from other calendar 3300 ); 3301 // can't rely on defKeys because event data is mutated 3302 var mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents); 3303 var mutatedStores_1 = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId); 3304 var populate = function (key) { 3305 if (!splitStates[key]) { 3306 splitStates[key] = { 3307 affectedEvents: affectedStores_1[key] || EMPTY_EVENT_STORE, 3308 mutatedEvents: mutatedStores_1[key] || EMPTY_EVENT_STORE, 3309 isEvent: interaction.isEvent, 3310 origSeg: interaction.origSeg 3311 }; 3312 } 3313 }; 3314 for (var key in affectedStores_1) { 3315 populate(key); 3316 } 3317 for (var key in mutatedStores_1) { 3318 populate(key); 3319 } 3320 } 3321 return splitStates; 3322 }; 3323 return Splitter; 3324 }()); 3325 function buildEventUiForKey(allUi, eventUiForKey, individualUi) { 3326 var baseParts = []; 3327 if (allUi) { 3328 baseParts.push(allUi); 3329 } 3330 if (eventUiForKey) { 3331 baseParts.push(eventUiForKey); 3332 } 3333 var stuff = { 3334 '': combineEventUis(baseParts) 3335 }; 3336 if (individualUi) { 3337 __assign(stuff, individualUi); 3338 } 3339 return stuff; 3340 } 3341 3342 // Generates HTML for an anchor to another view into the calendar. 3343 // Will either generate an <a> tag or a non-clickable <span> tag, depending on enabled settings. 3344 // `gotoOptions` can either be a DateMarker, or an object with the form: 3345 // { date, type, forceOff } 3346 // `type` is a view-type like "day" or "week". default value is "day". 3347 // `attrs` and `innerHtml` are use to generate the rest of the HTML tag. 3348 function buildGotoAnchorHtml(component, gotoOptions, attrs, innerHtml) { 3349 var dateEnv = component.dateEnv; 3350 var date; 3351 var type; 3352 var forceOff; 3353 var finalOptions; 3354 if (gotoOptions instanceof Date) { 3355 date = gotoOptions; // a single date-like input 3356 } 3357 else { 3358 date = gotoOptions.date; 3359 type = gotoOptions.type; 3360 forceOff = gotoOptions.forceOff; 3361 } 3362 finalOptions = { 3363 date: dateEnv.formatIso(date, { omitTime: true }), 3364 type: type || 'day' 3365 }; 3366 if (typeof attrs === 'string') { 3367 innerHtml = attrs; 3368 attrs = null; 3369 } 3370 attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space 3371 innerHtml = innerHtml || ''; 3372 if (!forceOff && component.opt('navLinks')) { 3373 return '<a' + attrs + 3374 ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' + 3375 innerHtml + 3376 '</a>'; 3377 } 3378 else { 3379 return '<span' + attrs + '>' + 3380 innerHtml + 3381 '</span>'; 3382 } 3383 } 3384 function getAllDayHtml(component) { 3385 return component.opt('allDayHtml') || htmlEscape(component.opt('allDayText')); 3386 } 3387 // Computes HTML classNames for a single-day element 3388 function getDayClasses(date, dateProfile, context, noThemeHighlight) { 3389 var calendar = context.calendar, view = context.view, theme = context.theme, dateEnv = context.dateEnv; 3390 var classes = []; 3391 var todayStart; 3392 var todayEnd; 3393 if (!rangeContainsMarker(dateProfile.activeRange, date)) { 3394 classes.push('fc-disabled-day'); 3395 } 3396 else { 3397 classes.push('fc-' + DAY_IDS[date.getUTCDay()]); 3398 if (view.opt('monthMode') && 3399 dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) { 3400 classes.push('fc-other-month'); 3401 } 3402 todayStart = startOfDay(calendar.getNow()); 3403 todayEnd = addDays(todayStart, 1); 3404 if (date < todayStart) { 3405 classes.push('fc-past'); 3406 } 3407 else if (date >= todayEnd) { 3408 classes.push('fc-future'); 3409 } 3410 else { 3411 classes.push('fc-today'); 3412 if (noThemeHighlight !== true) { 3413 classes.push(theme.getClass('today')); 3414 } 3415 } 3416 } 3417 return classes; 3418 } 3419 3420 // given a function that resolves a result asynchronously. 3421 // the function can either call passed-in success and failure callbacks, 3422 // or it can return a promise. 3423 // if you need to pass additional params to func, bind them first. 3424 function unpromisify(func, success, failure) { 3425 // guard against success/failure callbacks being called more than once 3426 // and guard against a promise AND callback being used together. 3427 var isResolved = false;
3428 var wrappedSuccess = function () { 3429 if (!isResolved) { 3430 isResolved = true; 3431 success.apply(this, arguments); 3432 } 3433 }; 3434 var wrappedFailure = function () { 3435 if (!isResolved) { 3436 isResolved = true; 3437 if (failure) { 3438 failure.apply(this, arguments); 3439 } 3440 } 3441 }; 3442 var res = func(wrappedSuccess, wrappedFailure); 3443 if (res && typeof res.then === 'function') { 3444 res.then(wrappedSuccess, wrappedFailure); 3445 } 3446 } 3447 3448 var Mixin = /** @class */ (function () { 3449 function Mixin() { 3450 } 3451 // mix into a CLASS 3452 Mixin.mixInto = function (destClass) { 3453 this.mixIntoObj(destClass.prototype); 3454 }; 3455 // mix into ANY object 3456 Mixin.mixIntoObj = function (destObj) { 3457 var _this = this; 3458 Object.getOwnPropertyNames(this.prototype).forEach(function (name) { 3459 if (!destObj[name]) { // if destination doesn't already define it 3460 destObj[name] = _this.prototype[name]; 3461 } 3462 }); 3463 }; 3464 /* 3465 will override existing methods 3466 TODO: remove! not used anymore 3467 */ 3468 Mixin.mixOver = function (destClass) { 3469 var _this = this; 3470 Object.getOwnPropertyNames(this.prototype).forEach(function (name) { 3471 destClass.prototype[name] = _this.prototype[name]; 3472 }); 3473 }; 3474 return Mixin; 3475 }()); 3476 3477 /* 3478 USAGE: 3479 import { default as EmitterMixin, EmitterInterface } from './EmitterMixin' 3480 in class: 3481 on: EmitterInterface['on'] 3482 one: EmitterInterface['one'] 3483 off: EmitterInterface['off'] 3484 trigger: EmitterInterface['trigger'] 3485 triggerWith: EmitterInterface['triggerWith'] 3486 hasHandlers: EmitterInterface['hasHandlers'] 3487 after class: 3488 EmitterMixin.mixInto(TheClass) 3489 */ 3490 var EmitterMixin = /** @class */ (function (_super) { 3491 __extends(EmitterMixin, _super); 3492 function EmitterMixin() { 3493 return _super !== null && _super.apply(this, arguments) || this; 3494 } 3495 EmitterMixin.prototype.on = function (type, handler) { 3496 addToHash(this._handlers || (this._handlers = {}), type, handler); 3497 return this; // for chaining 3498 }; 3499 // todo: add comments 3500 EmitterMixin.prototype.one = function (type, handler) { 3501 addToHash(this._oneHandlers || (this._oneHandlers = {}), type, handler); 3502 return this; // for chaining 3503 }; 3504 EmitterMixin.prototype.off = function (type, handler) { 3505 if (this._handlers) { 3506 removeFromHash(this._handlers, type, handler); 3507 } 3508 if (this._oneHandlers) { 3509 removeFromHash(this._oneHandlers, type, handler); 3510 } 3511 return this; // for chaining 3512 }; 3513 EmitterMixin.prototype.trigger = function (type) { 3514 var args = []; 3515 for (var _i = 1; _i < arguments.length; _i++) { 3516 args[_i - 1] = arguments[_i]; 3517 } 3518 this.triggerWith(type, this, args); 3519 return this; // for chaining 3520 }; 3521 EmitterMixin.prototype.triggerWith = function (type, context, args) { 3522 if (this._handlers) { 3523 applyAll(this._handlers[type], context, args); 3524 } 3525 if (this._oneHandlers) { 3526 applyAll(this._oneHandlers[type], context, args); 3527 delete this._oneHandlers[type]; // will never fire again 3528 } 3529 return this; // for chaining 3530 }; 3531 EmitterMixin.prototype.hasHandlers = function (type) { 3532 return (this._handlers && this._handlers[type] && this._handlers[type].length) || 3533 (this._oneHandlers && this._oneHandlers[type] && this._oneHandlers[type].length); 3534 }; 3535 return EmitterMixin; 3536 }(Mixin)); 3537 function addToHash(hash, type, handler) { 3538 (hash[type] || (hash[type] = [])) 3539 .push(handler); 3540 } 3541 function removeFromHash(hash, type, handler) { 3542 if (handler) { 3543 if (hash[type]) { 3544 hash[type] = hash[type].filter(function (func) { 3545 return func !== handler; 3546 }); 3547 } 3548 } 3549 else { 3550 delete hash[type]; // remove all handler funcs for this type 3551 } 3552 } 3553 3554 /* 3555 Records offset information for a set of elements, relative to an origin element. 3556 Can record the left/right OR the top/bottom OR both. 3557 Provides methods for querying the cache by position. 3558 */ 3559 var PositionCache = /** @class */ (function () { 3560 function PositionCache(originEl, els, isHorizontal, isVertical) { 3561 this.originEl = originEl; 3562 this.els = els; 3563 this.isHorizontal = isHorizontal; 3564 this.isVertical = isVertical; 3565 } 3566 // Queries the els for coordinates and stores them. 3567 // Call this method before using and of the get* methods below. 3568 PositionCache.prototype.build = function () { 3569 var originEl = this.originEl; 3570 var originClientRect = this.originClientRect = 3571 originEl.getBoundingClientRect(); // relative to viewport top-left 3572 if (this.isHorizontal) { 3573 this.buildElHorizontals(originClientRect.left); 3574 } 3575 if (this.isVertical) { 3576 this.buildElVerticals(originClientRect.top); 3577 } 3578 };
3579 // Populates the left/right internal coordinate arrays 3580 PositionCache.prototype.buildElHorizontals = function (originClientLeft) { 3581 var lefts = []; 3582 var rights = []; 3583 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 3584 var el = _a[_i]; 3585 var rect = el.getBoundingClientRect(); 3586 lefts.push(rect.left - originClientLeft); 3587 rights.push(rect.right - originClientLeft); 3588 } 3589 this.lefts = lefts; 3590 this.rights = rights; 3591 }; 3592 // Populates the top/bottom internal coordinate arrays 3593 PositionCache.prototype.buildElVerticals = function (originClientTop) { 3594 var tops = []; 3595 var bottoms = []; 3596 for (var _i = 0, _a = this.els; _i < _a.length; _i++) { 3597 var el = _a[_i]; 3598 var rect = el.getBoundingClientRect(); 3599 tops.push(rect.top - originClientTop); 3600 bottoms.push(rect.bottom - originClientTop); 3601 } 3602 this.tops = tops; 3603 this.bottoms = bottoms; 3604 }; 3605 // Given a left offset (from document left), returns the index of the el that it horizontally intersects. 3606 // If no intersection is made, returns undefined. 3607 PositionCache.prototype.leftToIndex = function (leftPosition) { 3608 var lefts = this.lefts; 3609 var rights = this.rights; 3610 var len = lefts.length; 3611 var i; 3612 for (i = 0; i < len; i++) { 3613 if (leftPosition >= lefts[i] && leftPosition < rights[i]) { 3614 return i; 3615 } 3616 } 3617 }; 3618 // Given a top offset (from document top), returns the index of the el that it vertically intersects. 3619 // If no intersection is made, returns undefined. 3620 PositionCache.prototype.topToIndex = function (topPosition) { 3621 var tops = this.tops; 3622 var bottoms = this.bottoms; 3623 var len = tops.length; 3624 var i; 3625 for (i = 0; i < len; i++) { 3626 if (topPosition >= tops[i] && topPosition < bottoms[i]) { 3627 return i; 3628 } 3629 } 3630 }; 3631 // Gets the width of the element at the given index 3632 PositionCache.prototype.getWidth = function (leftIndex) { 3633 return this.rights[leftIndex] - this.lefts[leftIndex]; 3634 }; 3635 // Gets the height of the element at the given index 3636 PositionCache.prototype.getHeight = function (topIndex) { 3637 return this.bottoms[topIndex] - this.tops[topIndex]; 3638 }; 3639 return PositionCache; 3640 }()); 3641 3642 /* 3643 An object for getting/setting scroll-related information for an element. 3644 Internally, this is done very differently for window versus DOM element, 3645 so this object serves as a common interface. 3646 */ 3647 var ScrollController = /** @class */ (function () { 3648 function ScrollController() { 3649 } 3650 ScrollController.prototype.getMaxScrollTop = function () { 3651 return this.getScrollHeight() - this.getClientHeight(); 3652 }; 3653 ScrollController.prototype.getMaxScrollLeft = function () { 3654 return this.getScrollWidth() - this.getClientWidth(); 3655 }; 3656 ScrollController.prototype.canScrollVertically = function () { 3657 return this.getMaxScrollTop() > 0; 3658 }; 3659 ScrollController.prototype.canScrollHorizontally = function () { 3660 return this.getMaxScrollLeft() > 0; 3661 }; 3662 ScrollController.prototype.canScrollUp = function () { 3663 return this.getScrollTop() > 0; 3664 }; 3665 ScrollController.prototype.canScrollDown = function () { 3666 return this.getScrollTop() < this.getMaxScrollTop(); 3667 }; 3668 ScrollController.prototype.canScrollLeft = function () { 3669 return this.getScrollLeft() > 0; 3670 }; 3671 ScrollController.prototype.canScrollRight = function () { 3672 return this.getScrollLeft() < this.getMaxScrollLeft(); 3673 };
3674 return ScrollController; 3675 }()); 3676 var ElementScrollController = /** @class */ (function (_super) { 3677 __extends(ElementScrollController, _super); 3678 function ElementScrollController(el) { 3679 var _this = _super.call(this) || this; 3680 _this.el = el; 3681 return _this; 3682 } 3683 ElementScrollController.prototype.getScrollTop = function () { 3684 return this.el.scrollTop; 3685 }; 3686 ElementScrollController.prototype.getScrollLeft = function () { 3687 return this.el.scrollLeft; 3688 }; 3689 ElementScrollController.prototype.setScrollTop = function (top) { 3690 this.el.scrollTop = top; 3691 }; 3692 ElementScrollController.prototype.setScrollLeft = function (left) { 3693 this.el.scrollLeft = left; 3694 }; 3695 ElementScrollController.prototype.getScrollWidth = function () { 3696 return this.el.scrollWidth; 3697 }; 3698 ElementScrollController.prototype.getScrollHeight = function () { 3699 return this.el.scrollHeight; 3700 }; 3701 ElementScrollController.prototype.getClientHeight = function () { 3702 return this.el.clientHeight; 3703 }; 3704 ElementScrollController.prototype.getClientWidth = function () { 3705 return this.el.clientWidth; 3706 }; 3707 return ElementScrollController; 3708 }(ScrollController)); 3709 var WindowScrollController = /** @class */ (function (_super) { 3710 __extends(WindowScrollController, _super); 3711 function WindowScrollController() { 3712 return _super !== null && _super.apply(this, arguments) || this; 3713 } 3714 WindowScrollController.prototype.getScrollTop = function () { 3715 return window.pageYOffset; 3716 }; 3717 WindowScrollController.prototype.getScrollLeft = function () { 3718 return window.pageXOffset; 3719 }; 3720 WindowScrollController.prototype.setScrollTop = function (n) { 3721 window.scroll(window.pageXOffset, n); 3722 }; 3723 WindowScrollController.prototype.setScrollLeft = function (n) { 3724 window.scroll(n, window.pageYOffset); 3725 }; 3726 WindowScrollController.prototype.getScrollWidth = function () { 3727 return document.documentElement.scrollWidth; 3728 }; 3729 WindowScrollController.prototype.getScrollHeight = function () { 3730 return document.documentElement.scrollHeight; 3731 }; 3732 WindowScrollController.prototype.getClientHeight = function () { 3733 return document.documentElement.clientHeight; 3734 }; 3735 WindowScrollController.prototype.getClientWidth = function () { 3736 return document.documentElement.clientWidth; 3737 }; 3738 return WindowScrollController; 3739 }(ScrollController)); 3740 3741 /* 3742 Embodies a div that has potential scrollbars 3743 */ 3744 var ScrollComponent = /** @class */ (function (_super) { 3745 __extends(ScrollComponent, _super); 3746 function ScrollComponent(overflowX, overflowY) { 3747 var _this = _super.call(this, createElement('div', { 3748 className: 'fc-scroller' 3749 })) || this; 3750 _this.overflowX = overflowX; 3751 _this.overflowY = overflowY; 3752 _this.applyOverflow(); 3753 return _this; 3754 } 3755 // sets to natural height, unlocks overflow 3756 ScrollComponent.prototype.clear = function () { 3757 this.setHeight('auto'); 3758 this.applyOverflow(); 3759 }; 3760 ScrollComponent.prototype.destroy = function () { 3761 removeElement(this.el); 3762 }; 3763 // Overflow 3764 // ----------------------------------------------------------------------------------------------------------------- 3765 ScrollComponent.prototype.applyOverflow = function () { 3766 applyStyle(this.el, { 3767 overflowX: this.overflowX, 3768 overflowY: this.overflowY 3769 }); 3770 }; 3771 // Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'. 3772 // Useful for preserving scrollbar widths regardless of future resizes. 3773 // Can pass in scrollbarWidths for optimization. 3774 ScrollComponent.prototype.lockOverflow = function (scrollbarWidths) { 3775 var overflowX = this.overflowX; 3776 var overflowY = this.overflowY;
3777 scrollbarWidths = scrollbarWidths || this.getScrollbarWidths(); 3778 if (overflowX === 'auto') { 3779 overflowX = (scrollbarWidths.bottom || // horizontal scrollbars? 3780 this.canScrollHorizontally() // OR scrolling pane with massless scrollbars? 3781 ) ? 'scroll' : 'hidden'; 3782 } 3783 if (overflowY === 'auto') { 3784 overflowY = (scrollbarWidths.left || scrollbarWidths.right || // horizontal scrollbars? 3785 this.canScrollVertically() // OR scrolling pane with massless scrollbars? 3786 ) ? 'scroll' : 'hidden'; 3787 } 3788 applyStyle(this.el, { overflowX: overflowX, overflowY: overflowY }); 3789 }; 3790 ScrollComponent.prototype.setHeight = function (height) { 3791 applyStyleProp(this.el, 'height', height); 3792 }; 3793 ScrollComponent.prototype.getScrollbarWidths = function () { 3794 var edges = computeEdges(this.el); 3795 return { 3796 left: edges.scrollbarLeft, 3797 right: edges.scrollbarRight, 3798 bottom: edges.scrollbarBottom 3799 }; 3800 }; 3801 return ScrollComponent; 3802 }(ElementScrollController)); 3803 3804 var Theme = /** @class */ (function () { 3805 function Theme(calendarOptions) { 3806 this.calendarOptions = calendarOptions; 3807 this.processIconOverride(); 3808 } 3809 Theme.prototype.processIconOverride = function () { 3810 if (this.iconOverrideOption) { 3811 this.setIconOverride(this.calendarOptions[this.iconOverrideOption]); 3812 } 3813 }; 3814 Theme.prototype.setIconOverride = function (iconOverrideHash) { 3815 var iconClassesCopy; 3816 var buttonName; 3817 if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object 3818 iconClassesCopy = __assign({}, this.iconClasses); 3819 for (buttonName in iconOverrideHash) { 3820 iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]); 3821 } 3822 this.iconClasses = iconClassesCopy; 3823 } 3824 else if (iconOverrideHash === false) { 3825 this.iconClasses = {}; 3826 } 3827 }; 3828 Theme.prototype.applyIconOverridePrefix = function (className) { 3829 var prefix = this.iconOverridePrefix; 3830 if (prefix && className.indexOf(prefix) !== 0) { // if not already present 3831 className = prefix + className; 3832 } 3833 return className; 3834 }; 3835 Theme.prototype.getClass = function (key) { 3836 return this.classes[key] || ''; 3837 }; 3838 Theme.prototype.getIconClass = function (buttonName) { 3839 var className = this.iconClasses[buttonName]; 3840 if (className) { 3841 return this.baseIconClass + ' ' + className; 3842 } 3843 return ''; 3844 }; 3845 Theme.prototype.getCustomButtonIconClass = function (customButtonProps) { 3846 var className; 3847 if (this.iconOverrideCustomButtonOption) { 3848 className = customButtonProps[this.iconOverrideCustomButtonOption]; 3849 if (className) { 3850 return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className); 3851 } 3852 } 3853 return ''; 3854 }; 3855 return Theme; 3856 }()); 3857 Theme.prototype.classes = {}; 3858 Theme.prototype.iconClasses = {}; 3859 Theme.prototype.baseIconClass = ''; 3860 Theme.prototype.iconOverridePrefix = ''; 3861 3862 var guid = 0; 3863 var Component = /** @class */ (function () { 3864 function Component(context, isView) { 3865 // HACK to populate view at top of component instantiation call chain 3866 if (isView) { 3867 context.view = this; 3868 } 3869 this.uid = String(guid++); 3870 this.context = context; 3871 this.dateEnv = context.dateEnv; 3872 this.theme = context.theme; 3873 this.view = context.view; 3874 this.calendar = context.calendar; 3875 this.isRtl = this.opt('dir') === 'rtl'; 3876 } 3877 Component.addEqualityFuncs = function (newFuncs) { 3878 this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs); 3879 }; 3880 Component.prototype.opt = function (name) { 3881 return this.context.options[name]; 3882 }; 3883 Component.prototype.receiveProps = function (props) { 3884 var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps; 3885 this.props = comboProps;
3886 if (anyChanges) { 3887 this.render(comboProps); 3888 } 3889 }; 3890 Component.prototype.render = function (props) { 3891 }; 3892 // after destroy is called, this component won't ever be used again 3893 Component.prototype.destroy = function () { 3894 }; 3895 return Component; 3896 }()); 3897 Component.prototype.equalityFuncs = {}; 3898 /* 3899 Reuses old values when equal. If anything is unequal, returns newProps as-is. 3900 Great for PureComponent, but won't be feasible with React, so just eliminate and use React's DOM diffing. 3901 */ 3902 function recycleProps(oldProps, newProps, equalityFuncs) { 3903 var comboProps = {}; // some old, some new 3904 var anyChanges = false; 3905 for (var key in newProps) { 3906 if (key in oldProps && (oldProps[key] === newProps[key] || 3907 (equalityFuncs[key] && equalityFuncs[key](oldProps[key], newProps[key])))) { 3908 // equal to old? use old prop 3909 comboProps[key] = oldProps[key]; 3910 } 3911 else { 3912 comboProps[key] = newProps[key]; 3913 anyChanges = true; 3914 } 3915 } 3916 for (var key in oldProps) { 3917 if (!(key in newProps)) { 3918 anyChanges = true; 3919 break; 3920 } 3921 } 3922 return { anyChanges: anyChanges, comboProps: comboProps }; 3923 } 3924 3925 /* 3926 PURPOSES: 3927 - hook up to fg, fill, and mirror renderers 3928 - interface for dragging and hits 3929 */ 3930 var DateComponent = /** @class */ (function (_super) { 3931 __extends(DateComponent, _super); 3932 function DateComponent(context, el, isView) { 3933 var _this = _super.call(this, context, isView) || this; 3934 _this.el = el; 3935 return _this; 3936 } 3937 DateComponent.prototype.destroy = function () { 3938 _super.prototype.destroy.call(this); 3939 removeElement(this.el); 3940 }; 3941 // TODO: WHAT ABOUT (sourceSeg && sourceSeg.component.doesDragMirror) 3942 // 3943 // Event Drag-n-Drop Rendering (for both events and external elements) 3944 // --------------------------------------------------------------------------------------------------------------- 3945 /* 3946 renderEventDragSegs(state: EventSegUiInteractionState) { 3947 if (state) { 3948 let { isEvent, segs, sourceSeg } = state 3949 3950 if (this.eventRenderer) { 3951 this.eventRenderer.hideByHash(state.affectedInstances) 3952 } 3953 3954 // if the user is dragging something that is considered an event with real event data, 3955 // and this component likes to do drag mirrors OR the component where the seg came from 3956 // likes to do drag mirrors, then render a drag mirror. 3957 if (isEvent && (this.doesDragMirror || sourceSeg && sourceSeg.component.doesDragMirror)) { 3958 if (this.mirrorRenderer) { 3959 this.mirrorRenderer.renderSegs(segs, { isDragging: true, sourceSeg }) 3960 } 3961 } 3962 3963 // if it would be impossible to render a drag mirror OR this component likes to render 3964 // highlights, then render a highlight. 3965 if (!isEvent || this.doesDragHighlight) { 3966 if (this.fillRenderer) { 3967 this.fillRenderer.renderSegs('highlight', segs) 3968 } 3969 } 3970 } 3971 } 3972 */ 3973 // Hit System 3974 // ----------------------------------------------------------------------------------------------------------------- 3975 DateComponent.prototype.buildPositionCaches = function () { 3976 }; 3977 DateComponent.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) { 3978 return null; // this should be abstract 3979 }; 3980 // Validation 3981 // ----------------------------------------------------------------------------------------------------------------- 3982 DateComponent.prototype.isInteractionValid = function (interaction) { 3983 var calendar = this.calendar; 3984 var dateProfile = this.props.dateProfile; // HACK 3985 var instances = interaction.mutatedEvents.instances; 3986 if (dateProfile) { // HACK for DayTile 3987 for (var instanceId in instances) { 3988 if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) { 3989 return false;
3990 } 3991 } 3992 } 3993 return isInteractionValid(interaction, calendar); 3994 }; 3995 DateComponent.prototype.isDateSelectionValid = function (selection) { 3996 var dateProfile = this.props.dateProfile; // HACK 3997 if (dateProfile && // HACK for DayTile 3998 !rangeContainsRange(dateProfile.validRange, selection.range)) { 3999 return false; 4000 } 4001 return isDateSelectionValid(selection, this.calendar); 4002 }; 4003 // Triggering 4004 // ----------------------------------------------------------------------------------------------------------------- 4005 // TODO: move to Calendar 4006 DateComponent.prototype.publiclyTrigger = function (name, args) { 4007 var calendar = this.calendar; 4008 return calendar.publiclyTrigger(name, args); 4009 }; 4010 DateComponent.prototype.publiclyTriggerAfterSizing = function (name, args) { 4011 var calendar = this.calendar; 4012 return calendar.publiclyTriggerAfterSizing(name, args); 4013 }; 4014 DateComponent.prototype.hasPublicHandlers = function (name) { 4015 var calendar = this.calendar; 4016 return calendar.hasPublicHandlers(name); 4017 }; 4018 DateComponent.prototype.triggerRenderedSegs = function (segs, isMirrors) { 4019 var calendar = this.calendar; 4020 if (this.hasPublicHandlers('eventPositioned')) { 4021 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) { 4022 var seg = segs_1[_i]; 4023 this.publiclyTriggerAfterSizing('eventPositioned', [ 4024 { 4025 event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), 4026 isMirror: isMirrors, 4027 isStart: seg.isStart, 4028 isEnd: seg.isEnd, 4029 el: seg.el, 4030 view: this // safe to cast because this method is only called on context.view 4031 } 4032 ]); 4033 } 4034 } 4035 if (!calendar.state.loadingLevel) { // avoid initial empty state while pending 4036 calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once 4037 } 4038 }; 4039 DateComponent.prototype.triggerWillRemoveSegs = function (segs, isMirrors) { 4040 var calendar = this.calendar; 4041 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 4042 var seg = segs_2[_i]; 4043 calendar.trigger('eventElRemove', seg.el); 4044 } 4045 if (this.hasPublicHandlers('eventDestroy')) { 4046 for (var _a = 0, segs_3 = segs; _a < segs_3.length; _a++) { 4047 var seg = segs_3[_a]; 4048 this.publiclyTrigger('eventDestroy', [ 4049 { 4050 event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance), 4051 isMirror: isMirrors, 4052 el: seg.el, 4053 view: this // safe to cast because this method is only called on context.view 4054 } 4055 ]); 4056 } 4057 } 4058 }; 4059 // Pointer Interaction Utils 4060 // ----------------------------------------------------------------------------------------------------------------- 4061 DateComponent.prototype.isValidSegDownEl = function (el) { 4062 return !this.props.eventDrag && // HACK 4063 !this.props.eventResize && // HACK 4064 !elementClosest(el, '.fc-mirror') && 4065 (this.isPopover() || !this.isInPopover(el)); 4066 // ^above line ensures we don't detect a seg interaction within a nested component. 4067 // it's a HACK because it only supports a popover as the nested component. 4068 }; 4069 DateComponent.prototype.isValidDateDownEl = function (el) { 4070 var segEl = elementClosest(el, this.fgSegSelector); 4071 return (!segEl || segEl.classList.contains('fc-mirror')) && 4072 !elementClosest(el, '.fc-more') && // a "more.." link 4073 !elementClosest(el, 'a[data-goto]') && // a clickable nav link 4074 !this.isInPopover(el); 4075 }; 4076 DateComponent.prototype.isPopover = function () { 4077 return this.el.classList.contains('fc-popover'); 4078 }; 4079 DateComponent.prototype.isInPopover = function (el) { 4080 return Boolean(elementClosest(el, '.fc-popover')); 4081 }; 4082 return DateComponent; 4083 }(Component)); 4084 DateComponent.prototype.fgSegSelector = '.fc-event-container > *'; 4085 DateComponent.prototype.bgSegSelector = '.fc-bgevent:not(.fc-nonbusiness)'; 4086 4087 var uid$1 = 0; 4088 function createPlugin(input) { 4089 return { 4090 id: String(uid$1++), 4091 deps: input.deps || [], 4092 reducers: input.reducers || [], 4093 eventDefParsers: input.eventDefParsers || [], 4094 eventDragMutationMassagers: input.eventDragMutationMassagers || [], 4095 eventDefMutationAppliers: input.eventDefMutationAppliers || [], 4096 dateSelectionTransformers: input.dateSelectionTransformers || [], 4097 datePointTransforms: input.datePointTransforms || [], 4098 dateSpanTransforms: input.dateSpanTransforms || [], 4099 views: input.views || {}, 4100 viewPropsTransformers: input.viewPropsTransformers || [], 4101 isPropsValid: input.isPropsValid || null, 4102 externalDefTransforms: input.externalDefTransforms || [], 4103 eventResizeJoinTransforms: input.eventResizeJoinTransforms || [], 4104 viewContainerModifiers: input.viewContainerModifiers || [], 4105 eventDropTransformers: input.eventDropTransformers || [], 4106 componentInteractions: input.componentInteractions || [], 4107 calendarInteractions: input.calendarInteractions || [],
4108 themeClasses: input.themeClasses || {}, 4109 eventSourceDefs: input.eventSourceDefs || [], 4110 cmdFormatter: input.cmdFormatter, 4111 recurringTypes: input.recurringTypes || [], 4112 namedTimeZonedImpl: input.namedTimeZonedImpl, 4113 defaultView: input.defaultView || '', 4114 elementDraggingImpl: input.elementDraggingImpl, 4115 optionChangeHandlers: input.optionChangeHandlers || {} 4116 }; 4117 } 4118 var PluginSystem = /** @class */ (function () { 4119 function PluginSystem() { 4120 this.hooks = { 4121 reducers: [], 4122 eventDefParsers: [], 4123 eventDragMutationMassagers: [], 4124 eventDefMutationAppliers: [], 4125 dateSelectionTransformers: [], 4126 datePointTransforms: [], 4127 dateSpanTransforms: [], 4128 views: {}, 4129 viewPropsTransformers: [], 4130 isPropsValid: null, 4131 externalDefTransforms: [], 4132 eventResizeJoinTransforms: [], 4133 viewContainerModifiers: [], 4134 eventDropTransformers: [], 4135 componentInteractions: [], 4136 calendarInteractions: [], 4137 themeClasses: {}, 4138 eventSourceDefs: [], 4139 cmdFormatter: null, 4140 recurringTypes: [], 4141 namedTimeZonedImpl: null, 4142 defaultView: '', 4143 elementDraggingImpl: null, 4144 optionChangeHandlers: {} 4145 }; 4146 this.addedHash = {}; 4147 } 4148 PluginSystem.prototype.add = function (plugin) { 4149 if (!this.addedHash[plugin.id]) { 4150 this.addedHash[plugin.id] = true; 4151 for (var _i = 0, _a = plugin.deps; _i < _a.length; _i++) { 4152 var dep = _a[_i]; 4153 this.add(dep); 4154 } 4155 this.hooks = combineHooks(this.hooks, plugin); 4156 } 4157 }; 4158 return PluginSystem; 4159 }()); 4160 function combineHooks(hooks0, hooks1) { 4161 return { 4162 reducers: hooks0.reducers.concat(hooks1.reducers), 4163 eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers), 4164 eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers), 4165 eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers), 4166 dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers), 4167 datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms), 4168 dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms), 4169 views: __assign({}, hooks0.views, hooks1.views), 4170 viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers), 4171 isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid, 4172 externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms), 4173 eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms), 4174 viewContainerModifiers: hooks0.viewContainerModifiers.concat(hooks1.viewContainerModifiers), 4175 eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers), 4176 calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions), 4177 componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions), 4178 themeClasses: __assign({}, hooks0.themeClasses, hooks1.themeClasses), 4179 eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs), 4180 cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter, 4181 recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes), 4182 namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl, 4183 defaultView: hooks0.defaultView || hooks1.defaultView, 4184 elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, 4185 optionChangeHandlers: __assign({}, hooks0.optionChangeHandlers, hooks1.optionChangeHandlers) 4186 }; 4187 } 4188 4189 var eventSourceDef = { 4190 ignoreRange: true, 4191 parseMeta: function (raw) { 4192 if (Array.isArray(raw)) { // short form 4193 return raw; 4194 } 4195 else if (Array.isArray(raw.events)) { 4196 return raw.events; 4197 } 4198 return null; 4199 }, 4200 fetch: function (arg, success) { 4201 success({ 4202 rawEvents: arg.eventSource.meta 4203 }); 4204 } 4205 }; 4206 var ArrayEventSourcePlugin = createPlugin({ 4207 eventSourceDefs: [eventSourceDef] 4208 }); 4209 4210 var eventSourceDef$1 = { 4211 parseMeta: function (raw) { 4212 if (typeof raw === 'function') { // short form 4213 return raw; 4214 } 4215 else if (typeof raw.events === 'function') { 4216 return raw.events; 4217 } 4218 return null; 4219 }, 4220 fetch: function (arg, success, failure) { 4221 var dateEnv = arg.calendar.dateEnv; 4222 var func = arg.eventSource.meta; 4223 unpromisify(func.bind(null, { 4224 start: dateEnv.toDate(arg.range.start), 4225 end: dateEnv.toDate(arg.range.end), 4226 startStr: dateEnv.formatIso(arg.range.start), 4227 endStr: dateEnv.formatIso(arg.range.end), 4228 timeZone: dateEnv.timeZone 4229 }), function (rawEvents) { 4230 success({ rawEvents: rawEvents }); // needs an object response 4231 }, failure // send errorObj directly to failure callback 4232 ); 4233 } 4234 }; 4235 var FuncEventSourcePlugin = createPlugin({ 4236 eventSourceDefs: [eventSourceDef$1] 4237 }); 4238 4239 function requestJson(method, url, params, successCallback, failureCallback) { 4240 method = method.toUpperCase(); 4241 var body = null; 4242 if (method === 'GET') { 4243 url = injectQueryStringParams(url, params); 4244 } 4245 else { 4246 body = encodeParams(params); 4247 } 4248 var xhr = new XMLHttpRequest(); 4249 xhr.open(method, url, true); 4250 if (method !== 'GET') { 4251 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 4252 } 4253 xhr.onload = function () { 4254 if (xhr.status >= 200 && xhr.status < 400) { 4255 try { 4256 var res = JSON.parse(xhr.responseText); 4257 successCallback(res, xhr); 4258 } 4259 catch (err) { 4260 failureCallback('Failure parsing JSON', xhr); 4261 } 4262 } 4263 else { 4264 failureCallback('Request failed', xhr); 4265 } 4266 }; 4267 xhr.onerror = function () { 4268 failureCallback('Request failed', xhr); 4269 }; 4270 xhr.send(body); 4271 } 4272 function injectQueryStringParams(url, params) { 4273 return url + 4274 (url.indexOf('?') === -1 ? '?' : '&') + 4275 encodeParams(params); 4276 } 4277 function encodeParams(params) { 4278 var parts = []; 4279 for (var key in params) { 4280 parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key])); 4281 } 4282 return parts.join('&'); 4283 } 4284 4285 var eventSourceDef$2 = { 4286 parseMeta: function (raw) { 4287 if (typeof raw === 'string') { // short form 4288 raw = { url: raw }; 4289 } 4290 else if (!raw || typeof raw !== 'object' || !raw.url) { 4291 return null; 4292 } 4293 return { 4294 url: raw.url, 4295 method: (raw.method || 'GET').toUpperCase(), 4296 extraParams: raw.extraParams, 4297 startParam: raw.startParam, 4298 endParam: raw.endParam, 4299 timeZoneParam: raw.timeZoneParam 4300 }; 4301 }, 4302 fetch: function (arg, success, failure) { 4303 var meta = arg.eventSource.meta;
4304 var requestParams = buildRequestParams(meta, arg.range, arg.calendar); 4305 requestJson(meta.method, meta.url, requestParams, function (rawEvents, xhr) { 4306 success({ rawEvents: rawEvents, xhr: xhr }); 4307 }, function (errorMessage, xhr) { 4308 failure({ message: errorMessage, xhr: xhr }); 4309 }); 4310 } 4311 }; 4312 var JsonFeedEventSourcePlugin = createPlugin({ 4313 eventSourceDefs: [eventSourceDef$2] 4314 }); 4315 function buildRequestParams(meta, range, calendar) { 4316 var dateEnv = calendar.dateEnv; 4317 var startParam; 4318 var endParam; 4319 var timeZoneParam; 4320 var customRequestParams; 4321 var params = {}; 4322 startParam = meta.startParam; 4323 if (startParam == null) { 4324 startParam = calendar.opt('startParam'); 4325 } 4326 endParam = meta.endParam; 4327 if (endParam == null) { 4328 endParam = calendar.opt('endParam'); 4329 } 4330 timeZoneParam = meta.timeZoneParam; 4331 if (timeZoneParam == null) { 4332 timeZoneParam = calendar.opt('timeZoneParam'); 4333 } 4334 // retrieve any outbound GET/POST data from the options 4335 if (typeof meta.extraParams === 'function') { 4336 // supplied as a function that returns a key/value object
4337 customRequestParams = meta.extraParams(); 4338 } 4339 else { 4340 // probably supplied as a straight key/value object 4341 customRequestParams = meta.extraParams || {}; 4342 } 4343 __assign(params, customRequestParams); 4344 params[startParam] = dateEnv.formatIso(range.start); 4345 params[endParam] = dateEnv.formatIso(range.end); 4346 if (dateEnv.timeZone !== 'local') { 4347 params[timeZoneParam] = dateEnv.timeZone; 4348 } 4349 return params; 4350 } 4351 4352 var recurring = { 4353 parse: function (rawEvent, leftoverProps, dateEnv) { 4354 var createMarker = dateEnv.createMarker.bind(dateEnv); 4355 var processors = { 4356 daysOfWeek: null, 4357 startTime: createDuration, 4358 endTime: createDuration, 4359 startRecur: createMarker, 4360 endRecur: createMarker 4361 }; 4362 var props = refineProps(rawEvent, processors, {}, leftoverProps); 4363 var anyValid = false; 4364 for (var propName in props) { 4365 if (props[propName] != null) { 4366 anyValid = true; 4367 break; 4368 } 4369 } 4370 if (anyValid) { 4371 var duration = null; 4372 if ('duration' in leftoverProps) { 4373 duration = createDuration(leftoverProps.duration); 4374 delete leftoverProps.duration; 4375 } 4376 if (!duration && props.startTime && props.endTime) { 4377 duration = subtractDurations(props.endTime, props.startTime); 4378 } 4379 return { 4380 allDayGuess: Boolean(!props.startTime && !props.endTime), 4381 duration: duration, 4382 typeData: props // doesn't need endTime anymore but oh well 4383 }; 4384 } 4385 return null; 4386 }, 4387 expand: function (typeData, framingRange, dateEnv) { 4388 var clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur }); 4389 if (clippedFramingRange) { 4390 return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv); 4391 } 4392 else { 4393 return []; 4394 } 4395 } 4396 }; 4397 var SimpleRecurrencePlugin = createPlugin({ 4398 recurringTypes: [recurring] 4399 }); 4400 function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) { 4401 var dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null; 4402 var dayMarker = startOfDay(framingRange.start); 4403 var endMarker = framingRange.end; 4404 var instanceStarts = []; 4405 while (dayMarker < endMarker) { 4406 var instanceStart 4407 // if everyday, or this particular day-of-week 4408 = void 0; 4409 // if everyday, or this particular day-of-week 4410 if (!dowHash || dowHash[dayMarker.getUTCDay()]) { 4411 if (startTime) { 4412 instanceStart = dateEnv.add(dayMarker, startTime); 4413 } 4414 else { 4415 instanceStart = dayMarker; 4416 } 4417 instanceStarts.push(instanceStart); 4418 } 4419 dayMarker = addDays(dayMarker, 1); 4420 } 4421 return instanceStarts; 4422 } 4423 4424 var DefaultOptionChangeHandlers = createPlugin({ 4425 optionChangeHandlers: { 4426 events: function (events, calendar, deepEquals) { 4427 handleEventSources([events], calendar, deepEquals); 4428 }, 4429 eventSources: handleEventSources, 4430 plugins: handlePlugins 4431 } 4432 }); 4433 function handleEventSources(inputs, calendar, deepEquals) { 4434 var unfoundSources = hashValuesToArray(calendar.state.eventSources);
4435 var newInputs = []; 4436 for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) { 4437 var input = inputs_1[_i]; 4438 var inputFound = false; 4439 for (var i = 0; i < unfoundSources.length; i++) { 4440 if (deepEquals(unfoundSources[i]._raw, input)) { 4441 unfoundSources.splice(i, 1); // delete 4442 inputFound = true; 4443 break; 4444 } 4445 } 4446 if (!inputFound) { 4447 newInputs.push(input); 4448 } 4449 } 4450 for (var _a = 0, unfoundSources_1 = unfoundSources; _a < unfoundSources_1.length; _a++) { 4451 var unfoundSource = unfoundSources_1[_a]; 4452 calendar.dispatch({ 4453 type: 'REMOVE_EVENT_SOURCE', 4454 sourceId: unfoundSource.sourceId 4455 }); 4456 } 4457 for (var _b = 0, newInputs_1 = newInputs; _b < newInputs_1.length; _b++) { 4458 var newInput = newInputs_1[_b]; 4459 calendar.addEventSource(newInput); 4460 } 4461 } 4462 // shortcoming: won't remove plugins 4463 function handlePlugins(inputs, calendar) { 4464 calendar.addPluginInputs(inputs); // will gracefully handle duplicates 4465 } 4466 4467 var config = {}; // TODO: make these options 4468 var globalDefaults = { 4469 defaultRangeSeparator: ' - ', 4470 titleRangeSeparator: ' \u2013 ', 4471 defaultTimedEventDuration: '01:00:00', 4472 defaultAllDayEventDuration: { day: 1 }, 4473 forceEventDuration: false, 4474 nextDayThreshold: '00:00:00', 4475 // display 4476 columnHeader: true, 4477 defaultView: '', 4478 aspectRatio: 1.35, 4479 header: { 4480 left: 'title', 4481 center: '', 4482 right: 'today prev,next' 4483 }, 4484 weekends: true, 4485 weekNumbers: false, 4486 weekNumberCalculation: 'local', 4487 editable: false, 4488 // nowIndicator: false, 4489 scrollTime: '06:00:00', 4490 minTime: '00:00:00', 4491 maxTime: '24:00:00', 4492 showNonCurrentDates: true, 4493 // event ajax 4494 lazyFetching: true, 4495 startParam: 'start', 4496 endParam: 'end', 4497 timeZoneParam: 'timeZone', 4498 timeZone: 'local', 4499 // allDayDefault: undefined, 4500 // locale 4501 locales: [], 4502 locale: '', 4503 // dir: will get this from the default locale 4504 // buttonIcons: null, 4505 // allows setting a min-height to the event segment to prevent short events overlapping each other 4506 timeGridEventMinHeight: 0, 4507 themeSystem: 'standard', 4508 // eventResizableFromStart: false, 4509 dragRevertDuration: 500, 4510 dragScroll: true, 4511 allDayMaintainDuration: false, 4512 // selectable: false, 4513 unselectAuto: true, 4514 // selectMinDistance: 0, 4515 dropAccept: '*', 4516 eventOrder: 'start,-duration,allDay,title', 4517 // ^ if start tie, longer events go before shorter. final tie-breaker is title text 4518 // rerenderDelay: null, 4519 eventLimit: false, 4520 eventLimitClick: 'popover', 4521 dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' }, 4522 handleWindowResize: true, 4523 windowResizeDelay: 100, 4524 longPressDelay: 1000, 4525 eventDragMinDistance: 5 // only applies to mouse 4526 }; 4527 var rtlDefaults = { 4528 header: { 4529 left: 'next,prev today', 4530 center: '', 4531 right: 'title' 4532 }, 4533 buttonIcons: { 4534 // TODO: make RTL support the responibility of the theme 4535 prev: 'fc-icon-chevron-right', 4536 next: 'fc-icon-chevron-left', 4537 prevYear: 'fc-icon-chevrons-right', 4538 nextYear: 'fc-icon-chevrons-left' 4539 } 4540 }; 4541 var complexOptions = [ 4542 'header', 4543 'footer', 4544 'buttonText', 4545 'buttonIcons' 4546 ]; 4547 // Merges an array of option objects into a single object 4548 function mergeOptions(optionObjs) { 4549 return mergeProps(optionObjs, complexOptions); 4550 } 4551 // TODO: move this stuff to a "plugin"-related file... 4552 var INTERNAL_PLUGINS = [ 4553 ArrayEventSourcePlugin, 4554 FuncEventSourcePlugin, 4555 JsonFeedEventSourcePlugin, 4556 SimpleRecurrencePlugin, 4557 DefaultOptionChangeHandlers 4558 ]; 4559 function refinePluginDefs(pluginInputs) { 4560 var plugins = []; 4561 for (var _i = 0, pluginInputs_1 = pluginInputs; _i < pluginInputs_1.length; _i++) { 4562 var pluginInput = pluginInputs_1[_i]; 4563 if (typeof pluginInput === 'string') { 4564 var globalName = 'FullCalendar' + capitaliseFirstLetter(pluginInput); 4565 if (!window[globalName]) { 4566 console.warn('Plugin file not loaded for ' + pluginInput); 4567 } 4568 else { 4569 plugins.push(window[globalName].default); // is an ES6 module 4570 } 4571 } 4572 else { 4573 plugins.push(pluginInput); 4574 } 4575 } 4576 return INTERNAL_PLUGINS.concat(plugins); 4577 } 4578 4579 var RAW_EN_LOCALE = { 4580 code: 'en', 4581 week: { 4582 dow: 0, 4583 doy: 4 // 4 days need to be within the year to be considered the first week 4584 }, 4585 dir: 'ltr', 4586 buttonText: { 4587 prev: 'prev', 4588 next: 'next', 4589 prevYear: 'prev year', 4590 nextYear: 'next year', 4591 year: 'year', 4592 today: 'today', 4593 month: 'month', 4594 week: 'week', 4595 day: 'day', 4596 list: 'list' 4597 }, 4598 weekLabel: 'W', 4599 allDayText: 'all-day', 4600 eventLimitText: 'more', 4601 noEventsMessage: 'No events to display' 4602 }; 4603 function parseRawLocales(explicitRawLocales) { 4604 var defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en'; 4605 var globalArray = window['FullCalendarLocalesAll'] || []; // from locales-all.js 4606 var globalObject = window['FullCalendarLocales'] || {}; // from locales/*.js. keys are meaningless 4607 var allRawLocales = globalArray.concat(// globalArray is low prio 4608 hashValuesToArray(globalObject), // medium prio 4609 explicitRawLocales // highest prio 4610 ); 4611 var rawLocaleMap = { 4612 en: RAW_EN_LOCALE // necessary? 4613 }; 4614 for (var _i = 0, allRawLocales_1 = allRawLocales; _i < allRawLocales_1.length; _i++) { 4615 var rawLocale = allRawLocales_1[_i]; 4616 rawLocaleMap[rawLocale.code] = rawLocale; 4617 } 4618 return { 4619 map: rawLocaleMap, 4620 defaultCode: defaultCode 4621 }; 4622 } 4623 function buildLocale(inputSingular, available) { 4624 if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) { 4625 return parseLocale(inputSingular.code, [inputSingular.code], inputSingular); 4626 } 4627 else { 4628 return queryLocale(inputSingular, available); 4629 } 4630 } 4631 function queryLocale(codeArg, available) { 4632 var codes = [].concat(codeArg || []); // will convert to array 4633 var raw = queryRawLocale(codes, available) || RAW_EN_LOCALE; 4634 return parseLocale(codeArg, codes, raw); 4635 } 4636 function queryRawLocale(codes, available) { 4637 for (var i = 0; i < codes.length; i++) { 4638 var parts = codes[i].toLocaleLowerCase().split('-'); 4639 for (var j = parts.length; j > 0; j--) { 4640 var simpleId = parts.slice(0, j).join('-'); 4641 if (available[simpleId]) { 4642 return available[simpleId]; 4643 } 4644 } 4645 } 4646 return null; 4647 } 4648 function parseLocale(codeArg, codes, raw) { 4649 var merged = mergeProps([RAW_EN_LOCALE, raw], ['buttonText']); 4650 delete merged.code; // don't want this part of the options 4651 var week = merged.week; 4652 delete merged.week; 4653 return { 4654 codeArg: codeArg, 4655 codes: codes, 4656 week: week, 4657 simpleNumberFormat: new Intl.NumberFormat(codeArg), 4658 options: merged 4659 }; 4660 } 4661 4662 var OptionsManager = /** @class */ (function () { 4663 function OptionsManager(overrides) { 4664 this.overrides = __assign({}, overrides); // make a copy 4665 this.dynamicOverrides = {}; 4666 this.compute(); 4667 } 4668 OptionsManager.prototype.mutate = function (updates, removals, isDynamic) { 4669 var overrideHash = isDynamic ? this.dynamicOverrides : this.overrides; 4670 __assign(overrideHash, updates); 4671 for (var _i = 0, removals_1 = removals; _i < removals_1.length; _i++) { 4672 var propName = removals_1[_i]; 4673 delete overrideHash[propName]; 4674 } 4675 this.compute(); 4676 }; 4677 // Computes the flattened options hash for the calendar and assigns to `this.options`. 4678 // Assumes this.overrides and this.dynamicOverrides have already been initialized. 4679 OptionsManager.prototype.compute = function () {
4680 // TODO: not a very efficient system 4681 var locales = firstDefined(// explicit locale option given? 4682 this.dynamicOverrides.locales, this.overrides.locales, globalDefaults.locales); 4683 var locale = firstDefined(// explicit locales option given? 4684 this.dynamicOverrides.locale, this.overrides.locale, globalDefaults.locale); 4685 var available = parseRawLocales(locales); 4686 var localeDefaults = buildLocale(locale || available.defaultCode, available.map).options; 4687 var dir = firstDefined(// based on options computed so far, is direction RTL? 4688 this.dynamicOverrides.dir, this.overrides.dir, localeDefaults.dir); 4689 var dirDefaults = dir === 'rtl' ? rtlDefaults : {}; 4690 this.dirDefaults = dirDefaults; 4691 this.localeDefaults = localeDefaults; 4692 this.computed = mergeOptions([ 4693 globalDefaults, 4694 dirDefaults, 4695 localeDefaults, 4696 this.overrides, 4697 this.dynamicOverrides 4698 ]); 4699 }; 4700 return OptionsManager; 4701 }()); 4702 4703 var calendarSystemClassMap = {}; 4704 function registerCalendarSystem(name, theClass) { 4705 calendarSystemClassMap[name] = theClass; 4706 } 4707 function createCalendarSystem(name) { 4708 return new calendarSystemClassMap[name](); 4709 } 4710 var GregorianCalendarSystem = /** @class */ (function () { 4711 function GregorianCalendarSystem() { 4712 } 4713 GregorianCalendarSystem.prototype.getMarkerYear = function (d) { 4714 return d.getUTCFullYear(); 4715 }; 4716 GregorianCalendarSystem.prototype.getMarkerMonth = function (d) { 4717 return d.getUTCMonth(); 4718 }; 4719 GregorianCalendarSystem.prototype.getMarkerDay = function (d) { 4720 return d.getUTCDate(); 4721 }; 4722 GregorianCalendarSystem.prototype.arrayToMarker = function (arr) { 4723 return arrayToUtcDate(arr); 4724 }; 4725 GregorianCalendarSystem.prototype.markerToArray = function (marker) { 4726 return dateToUtcArray(marker); 4727 }; 4728 return GregorianCalendarSystem; 4729 }()); 4730 registerCalendarSystem('gregory', GregorianCalendarSystem); 4731 4732 var ISO_RE = /^\s*(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/; 4733 function parse(str) { 4734 var m = ISO_RE.exec(str); 4735 if (m) { 4736 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)); 4737 if (isValidDate(marker)) { 4738 var timeZoneOffset = null; 4739 if (m[13]) { 4740 timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 + 4741 Number(m[18] || 0)); 4742 } 4743 return { 4744 marker: marker, 4745 isTimeUnspecified: !m[6], 4746 timeZoneOffset: timeZoneOffset 4747 }; 4748 } 4749 } 4750 return null; 4751 } 4752 4753 var DateEnv = /** @class */ (function () { 4754 function DateEnv(settings) { 4755 var timeZone = this.timeZone = settings.timeZone; 4756 var isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC'; 4757 if (settings.namedTimeZoneImpl && isNamedTimeZone) { 4758 this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone); 4759 } 4760 this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl); 4761 this.calendarSystem = createCalendarSystem(settings.calendarSystem); 4762 this.locale = settings.locale; 4763 this.weekDow = settings.locale.week.dow; 4764 this.weekDoy = settings.locale.week.doy; 4765 if (settings.weekNumberCalculation === 'ISO') { 4766 this.weekDow = 1; 4767 this.weekDoy = 4; 4768 } 4769 else if (typeof settings.firstDay === 'number') { 4770 this.weekDow = settings.firstDay; 4771 } 4772 if (typeof settings.weekNumberCalculation === 'function') {
4773 this.weekNumberFunc = settings.weekNumberCalculation; 4774 } 4775 this.weekLabel = settings.weekLabel != null ? settings.weekLabel : settings.locale.options.weekLabel; 4776 this.cmdFormatter = settings.cmdFormatter; 4777 } 4778 // Creating / Parsing 4779 DateEnv.prototype.createMarker = function (input) { 4780 var meta = this.createMarkerMeta(input); 4781 if (meta === null) { 4782 return null; 4783 } 4784 return meta.marker; 4785 }; 4786 DateEnv.prototype.createNowMarker = function () { 4787 if (this.canComputeOffset) { 4788 return this.timestampToMarker(new Date().valueOf()); 4789 } 4790 else { 4791 // if we can't compute the current date val for a timezone, 4792 // better to give the current local date vals than UTC 4793 return arrayToUtcDate(dateToLocalArray(new Date())); 4794 } 4795 }; 4796 DateEnv.prototype.createMarkerMeta = function (input) { 4797 if (typeof input === 'string') { 4798 return this.parse(input); 4799 } 4800 var marker = null; 4801 if (typeof input === 'number') { 4802 marker = this.timestampToMarker(input); 4803 } 4804 else if (input instanceof Date) { 4805 input = input.valueOf(); 4806 if (!isNaN(input)) { 4807 marker = this.timestampToMarker(input); 4808 } 4809 } 4810 else if (Array.isArray(input)) { 4811 marker = arrayToUtcDate(input); 4812 } 4813 if (marker === null || !isValidDate(marker)) { 4814 return null; 4815 } 4816 return { marker: marker, isTimeUnspecified: false, forcedTzo: null }; 4817 }; 4818 DateEnv.prototype.parse = function (s) { 4819 var parts = parse(s); 4820 if (parts === null) { 4821 return null; 4822 } 4823 var marker = parts.marker; 4824 var forcedTzo = null; 4825 if (parts.timeZoneOffset !== null) { 4826 if (this.canComputeOffset) { 4827 marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000); 4828 } 4829 else { 4830 forcedTzo = parts.timeZoneOffset; 4831 } 4832 } 4833 return { marker: marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo: forcedTzo }; 4834 }; 4835 // Accessors 4836 DateEnv.prototype.getYear = function (marker) { 4837 return this.calendarSystem.getMarkerYear(marker); 4838 }; 4839 DateEnv.prototype.getMonth = function (marker) { 4840 return this.calendarSystem.getMarkerMonth(marker); 4841 }; 4842 // Adding / Subtracting 4843 DateEnv.prototype.add = function (marker, dur) { 4844 var a = this.calendarSystem.markerToArray(marker); 4845 a[0] += dur.years; 4846 a[1] += dur.months; 4847 a[2] += dur.days; 4848 a[6] += dur.milliseconds; 4849 return this.calendarSystem.arrayToMarker(a); 4850 }; 4851 DateEnv.prototype.subtract = function (marker, dur) { 4852 var a = this.calendarSystem.markerToArray(marker); 4853 a[0] -= dur.years; 4854 a[1] -= dur.months; 4855 a[2] -= dur.days; 4856 a[6] -= dur.milliseconds; 4857 return this.calendarSystem.arrayToMarker(a); 4858 }; 4859 DateEnv.prototype.addYears = function (marker, n) { 4860 var a = this.calendarSystem.markerToArray(marker); 4861 a[0] += n; 4862 return this.calendarSystem.arrayToMarker(a); 4863 }; 4864 DateEnv.prototype.addMonths = function (marker, n) { 4865 var a = this.calendarSystem.markerToArray(marker); 4866 a[1] += n; 4867 return this.calendarSystem.arrayToMarker(a); 4868 }; 4869 // Diffing Whole Units 4870 DateEnv.prototype.diffWholeYears = function (m0, m1) { 4871 var calendarSystem = this.calendarSystem; 4872 if (timeAsMs(m0) === timeAsMs(m1) && 4873 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) && 4874 calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) { 4875 return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0); 4876 } 4877 return null; 4878 }; 4879 DateEnv.prototype.diffWholeMonths = function (m0, m1) { 4880 var calendarSystem = this.calendarSystem; 4881 if (timeAsMs(m0) === timeAsMs(m1) && 4882 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) { 4883 return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) + 4884 (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12; 4885 } 4886 return null; 4887 }; 4888 // Range / Duration 4889 DateEnv.prototype.greatestWholeUnit = function (m0, m1) { 4890 var n = this.diffWholeYears(m0, m1); 4891 if (n !== null) { 4892 return { unit: 'year', value: n }; 4893 } 4894 n = this.diffWholeMonths(m0, m1); 4895 if (n !== null) { 4896 return { unit: 'month', value: n }; 4897 } 4898 n = diffWholeWeeks(m0, m1); 4899 if (n !== null) { 4900 return { unit: 'week', value: n }; 4901 } 4902 n = diffWholeDays(m0, m1); 4903 if (n !== null) { 4904 return { unit: 'day', value: n }; 4905 } 4906 n = diffHours(m0, m1); 4907 if (isInt(n)) { 4908 return { unit: 'hour', value: n }; 4909 } 4910 n = diffMinutes(m0, m1); 4911 if (isInt(n)) { 4912 return { unit: 'minute', value: n }; 4913 } 4914 n = diffSeconds(m0, m1); 4915 if (isInt(n)) { 4916 return { unit: 'second', value: n }; 4917 } 4918 return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() }; 4919 }; 4920 DateEnv.prototype.countDurationsBetween = function (m0, m1, d) { 4921 // TODO: can use greatestWholeUnit 4922 var diff; 4923 if (d.years) { 4924 diff = this.diffWholeYears(m0, m1); 4925 if (diff !== null) { 4926 return diff / asRoughYears(d); 4927 } 4928 } 4929 if (d.months) { 4930 diff = this.diffWholeMonths(m0, m1); 4931 if (diff !== null) { 4932 return diff / asRoughMonths(d); 4933 } 4934 } 4935 if (d.days) { 4936 diff = diffWholeDays(m0, m1); 4937 if (diff !== null) { 4938 return diff / asRoughDays(d); 4939 } 4940 } 4941 return (m1.valueOf() - m0.valueOf()) / asRoughMs(d); 4942 }; 4943 // Start-Of 4944 DateEnv.prototype.startOf = function (m, unit) { 4945 if (unit === 'year') { 4946 return this.startOfYear(m); 4947 } 4948 else if (unit === 'month') { 4949 return this.startOfMonth(m); 4950 } 4951 else if (unit === 'week') { 4952 return this.startOfWeek(m); 4953 } 4954 else if (unit === 'day') { 4955 return startOfDay(m); 4956 } 4957 else if (unit === 'hour') { 4958 return startOfHour(m); 4959 } 4960 else if (unit === 'minute') { 4961 return startOfMinute(m); 4962 } 4963 else if (unit === 'second') { 4964 return startOfSecond(m); 4965 } 4966 }; 4967 DateEnv.prototype.startOfYear = function (m) { 4968 return this.calendarSystem.arrayToMarker([ 4969 this.calendarSystem.getMarkerYear(m) 4970 ]); 4971 }; 4972 DateEnv.prototype.startOfMonth = function (m) { 4973 return this.calendarSystem.arrayToMarker([ 4974 this.calendarSystem.getMarkerYear(m), 4975 this.calendarSystem.getMarkerMonth(m) 4976 ]); 4977 }; 4978 DateEnv.prototype.startOfWeek = function (m) { 4979 return this.calendarSystem.arrayToMarker([ 4980 this.calendarSystem.getMarkerYear(m), 4981 this.calendarSystem.getMarkerMonth(m), 4982 m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7) 4983 ]); 4984 }; 4985 // Week Number 4986 DateEnv.prototype.computeWeekNumber = function (marker) { 4987 if (this.weekNumberFunc) { 4988 return this.weekNumberFunc(this.toDate(marker)); 4989 } 4990 else { 4991 return weekOfYear(marker, this.weekDow, this.weekDoy); 4992 } 4993 }; 4994 // TODO: choke on timeZoneName: long 4995 DateEnv.prototype.format = function (marker, formatter, dateOptions) { 4996 if (dateOptions === void 0) { dateOptions = {}; } 4997 return formatter.format({ 4998 marker: marker, 4999 timeZoneOffset: dateOptions.forcedTzo != null ? 5000 dateOptions.forcedTzo : 5001 this.offsetForMarker(marker) 5002 }, this); 5003 }; 5004 DateEnv.prototype.formatRange = function (start, end, formatter, dateOptions) { 5005 if (dateOptions === void 0) { dateOptions = {}; } 5006 if (dateOptions.isEndExclusive) { 5007 end = addMs(end, -1); 5008 } 5009 return formatter.formatRange({ 5010 marker: start, 5011 timeZoneOffset: dateOptions.forcedStartTzo != null ? 5012 dateOptions.forcedStartTzo : 5013 this.offsetForMarker(start) 5014 }, { 5015 marker: end, 5016 timeZoneOffset: dateOptions.forcedEndTzo != null ? 5017 dateOptions.forcedEndTzo : 5018 this.offsetForMarker(end) 5019 }, this); 5020 }; 5021 DateEnv.prototype.formatIso = function (marker, extraOptions) { 5022 if (extraOptions === void 0) { extraOptions = {}; } 5023 var timeZoneOffset = null; 5024 if (!extraOptions.omitTimeZoneOffset) { 5025 if (extraOptions.forcedTzo != null) { 5026 timeZoneOffset = extraOptions.forcedTzo; 5027 } 5028 else { 5029 timeZoneOffset = this.offsetForMarker(marker); 5030 } 5031 } 5032 return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime); 5033 }; 5034 // TimeZone 5035 DateEnv.prototype.timestampToMarker = function (ms) { 5036 if (this.timeZone === 'local') { 5037 return arrayToUtcDate(dateToLocalArray(new Date(ms))); 5038 } 5039 else if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) { 5040 return new Date(ms); 5041 } 5042 else { 5043 return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms)); 5044 } 5045 }; 5046 DateEnv.prototype.offsetForMarker = function (m) { 5047 if (this.timeZone === 'local') { 5048 return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset 5049 } 5050 else if (this.timeZone === 'UTC') { 5051 return 0; 5052 } 5053 else if (this.namedTimeZoneImpl) { 5054 return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)); 5055 } 5056 return null; 5057 }; 5058 // Conversion 5059 DateEnv.prototype.toDate = function (m, forcedTzo) { 5060 if (this.timeZone === 'local') { 5061 return arrayToLocalDate(dateToUtcArray(m)); 5062 } 5063 else if (this.timeZone === 'UTC') { 5064 return new Date(m.valueOf()); // make sure it's a copy 5065 } 5066 else if (!this.namedTimeZoneImpl) { 5067 return new Date(m.valueOf() - (forcedTzo || 0)); 5068 } 5069 else { 5070 return new Date(m.valueOf() - 5071 this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60 // convert minutes -> ms 5072 ); 5073 } 5074 }; 5075 return DateEnv; 5076 }()); 5077 5078 var SIMPLE_SOURCE_PROPS = { 5079 id: String, 5080 allDayDefault: Boolean, 5081 eventDataTransform: Function, 5082 success: Function, 5083 failure: Function 5084 }; 5085 var uid$2 = 0; 5086 function doesSourceNeedRange(eventSource, calendar) { 5087 var defs = calendar.pluginSystem.hooks.eventSourceDefs; 5088 return !defs[eventSource.sourceDefId].ignoreRange; 5089 } 5090 function parseEventSource(raw, calendar) { 5091 var defs = calendar.pluginSystem.hooks.eventSourceDefs;
5092 for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence 5093 var def = defs[i]; 5094 var meta = def.parseMeta(raw); 5095 if (meta) { 5096 var res = parseEventSourceProps(typeof raw === 'object' ? raw : {}, meta, i, calendar); 5097 res._raw = raw; 5098 return res; 5099 } 5100 } 5101 return null; 5102 } 5103 function parseEventSourceProps(raw, meta, sourceDefId, calendar) { 5104 var leftovers0 = {}; 5105 var props = refineProps(raw, SIMPLE_SOURCE_PROPS, {}, leftovers0); 5106 var leftovers1 = {}; 5107 var ui = processUnscopedUiProps(leftovers0, calendar, leftovers1); 5108 props.isFetching = false; 5109 props.latestFetchId = ''; 5110 props.fetchRange = null; 5111 props.publicId = String(raw.id || ''); 5112 props.sourceId = String(uid$2++); 5113 props.sourceDefId = sourceDefId; 5114 props.meta = meta; 5115 props.ui = ui; 5116 props.extendedProps = leftovers1; 5117 return props; 5118 } 5119 5120 function reduceEventSources (eventSources, action, dateProfile, calendar) { 5121 switch (action.type) { 5122 case 'ADD_EVENT_SOURCES': // already parsed 5123 return addSources(eventSources, action.sources, dateProfile ? dateProfile.activeRange : null, calendar);
5124 case 'REMOVE_EVENT_SOURCE': 5125 return removeSource(eventSources, action.sourceId); 5126 case 'PREV': // TODO: how do we track all actions that affect dateProfile :( 5127 case 'NEXT': 5128 case 'SET_DATE': 5129 case 'SET_VIEW_TYPE': 5130 if (dateProfile) { 5131 return fetchDirtySources(eventSources, dateProfile.activeRange, calendar); 5132 } 5133 else { 5134 return eventSources; 5135 } 5136 case 'FETCH_EVENT_SOURCES': 5137 case 'CHANGE_TIMEZONE': 5138 return fetchSourcesByIds(eventSources, action.sourceIds ? 5139 arrayToHash(action.sourceIds) : 5140 excludeStaticSources(eventSources, calendar), dateProfile ? dateProfile.activeRange : null, calendar); 5141 case 'RECEIVE_EVENTS': 5142 case 'RECEIVE_EVENT_ERROR': 5143 return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange); 5144 case 'REMOVE_ALL_EVENT_SOURCES': 5145 return {}; 5146 default: 5147 return eventSources; 5148 } 5149 } 5150 var uid$3 = 0; 5151 function addSources(eventSourceHash, sources, fetchRange, calendar) { 5152 var hash = {}; 5153 for (var _i = 0, sources_1 = sources; _i < sources_1.length; _i++) { 5154 var source = sources_1[_i]; 5155 hash[source.sourceId] = source; 5156 } 5157 if (fetchRange) { 5158 hash = fetchDirtySources(hash, fetchRange, calendar); 5159 } 5160 return __assign({}, eventSourceHash, hash); 5161 } 5162 function removeSource(eventSourceHash, sourceId) { 5163 return filterHash(eventSourceHash, function (eventSource) { 5164 return eventSource.sourceId !== sourceId; 5165 }); 5166 } 5167 function fetchDirtySources(sourceHash, fetchRange, calendar) { 5168 return fetchSourcesByIds(sourceHash, filterHash(sourceHash, function (eventSource) { 5169 return isSourceDirty(eventSource, fetchRange, calendar); 5170 }), fetchRange, calendar); 5171 } 5172 function isSourceDirty(eventSource, fetchRange, calendar) { 5173 if (!doesSourceNeedRange(eventSource, calendar)) { 5174 return !eventSource.latestFetchId; 5175 } 5176 else { 5177 return !calendar.opt('lazyFetching') || 5178 !eventSource.fetchRange || 5179 fetchRange.start < eventSource.fetchRange.start || 5180 fetchRange.end > eventSource.fetchRange.end; 5181 } 5182 } 5183 function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, calendar) { 5184 var nextSources = {}; 5185 for (var sourceId in prevSources) { 5186 var source = prevSources[sourceId]; 5187 if (sourceIdHash[sourceId]) { 5188 nextSources[sourceId] = fetchSource(source, fetchRange, calendar); 5189 } 5190 else { 5191 nextSources[sourceId] = source; 5192 } 5193 } 5194 return nextSources; 5195 } 5196 function fetchSource(eventSource, fetchRange, calendar) { 5197 var sourceDef = calendar.pluginSystem.hooks.eventSourceDefs[eventSource.sourceDefId]; 5198 var fetchId = String(uid$3++); 5199 sourceDef.fetch({ 5200 eventSource: eventSource, 5201 calendar: calendar, 5202 range: fetchRange 5203 }, function (res) { 5204 var rawEvents = res.rawEvents; 5205 var calSuccess = calendar.opt('eventSourceSuccess'); 5206 var calSuccessRes; 5207 var sourceSuccessRes; 5208 if (eventSource.success) { 5209 sourceSuccessRes = eventSource.success(rawEvents, res.xhr); 5210 } 5211 if (calSuccess) { 5212 calSuccessRes = calSuccess(rawEvents, res.xhr); 5213 } 5214 rawEvents = sourceSuccessRes || calSuccessRes || rawEvents; 5215 calendar.dispatch({ 5216 type: 'RECEIVE_EVENTS', 5217 sourceId: eventSource.sourceId, 5218 fetchId: fetchId, 5219 fetchRange: fetchRange, 5220 rawEvents: rawEvents 5221 }); 5222 }, function (error) { 5223 var callFailure = calendar.opt('eventSourceFailure'); 5224 console.warn(error.message, error); 5225 if (eventSource.failure) { 5226 eventSource.failure(error); 5227 } 5228 if (callFailure) { 5229 callFailure(error); 5230 } 5231 calendar.dispatch({ 5232 type: 'RECEIVE_EVENT_ERROR', 5233 sourceId: eventSource.sourceId, 5234 fetchId: fetchId, 5235 fetchRange: fetchRange, 5236 error: error 5237 }); 5238 }); 5239 return __assign({}, eventSource, { isFetching: true, latestFetchId: fetchId }); 5240 } 5241 function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) { 5242 var _a; 5243 var eventSource = sourceHash[sourceId]; 5244 if (eventSource && // not already removed 5245 fetchId === eventSource.latestFetchId) { 5246 return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange }), _a)); 5247 } 5248 return sourceHash; 5249 } 5250 function excludeStaticSources(eventSources, calendar) { 5251 return filterHash(eventSources, function (eventSource) { 5252 return doesSourceNeedRange(eventSource, calendar); 5253 }); 5254 } 5255 5256 var DateProfileGenerator = /** @class */ (function () { 5257 function DateProfileGenerator(viewSpec, calendar) { 5258 this.viewSpec = viewSpec; 5259 this.options = viewSpec.options; 5260 this.dateEnv = calendar.dateEnv; 5261 this.calendar = calendar; 5262 this.initHiddenDays(); 5263 } 5264 /* Date Range Computation 5265 ------------------------------------------------------------------------------------------------------------------*/ 5266 // Builds a structure with info about what the dates/ranges will be for the "prev" view. 5267 DateProfileGenerator.prototype.buildPrev = function (currentDateProfile, currentDate) { 5268 var dateEnv = this.dateEnv; 5269 var prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5270 currentDateProfile.dateIncrement); 5271 return this.build(prevDate, -1); 5272 }; 5273 // Builds a structure with info about what the dates/ranges will be for the "next" view. 5274 DateProfileGenerator.prototype.buildNext = function (currentDateProfile, currentDate) { 5275 var dateEnv = this.dateEnv; 5276 var nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month 5277 currentDateProfile.dateIncrement); 5278 return this.build(nextDate, 1); 5279 }; 5280 // Builds a structure holding dates/ranges for rendering around the given date. 5281 // Optional direction param indicates whether the date is being incremented/decremented 5282 // from its previous value. decremented = -1, incremented = 1 (default). 5283 DateProfileGenerator.prototype.build = function (currentDate, direction, forceToValid) { 5284 if (forceToValid === void 0) { forceToValid = false; }
5285 var validRange; 5286 var minTime = null; 5287 var maxTime = null; 5288 var currentInfo; 5289 var isRangeAllDay; 5290 var renderRange; 5291 var activeRange; 5292 var isValid; 5293 validRange = this.buildValidRange(); 5294 validRange = this.trimHiddenDays(validRange); 5295 if (forceToValid) { 5296 currentDate = constrainMarkerToRange(currentDate, validRange); 5297 } 5298 currentInfo = this.buildCurrentRangeInfo(currentDate, direction); 5299 isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit); 5300 renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay); 5301 renderRange = this.trimHiddenDays(renderRange); 5302 activeRange = renderRange; 5303 if (!this.options.showNonCurrentDates) { 5304 activeRange = intersectRanges(activeRange, currentInfo.range); 5305 } 5306 minTime = createDuration(this.options.minTime); 5307 maxTime = createDuration(this.options.maxTime); 5308 activeRange = this.adjustActiveRange(activeRange, minTime, maxTime); 5309 activeRange = intersectRanges(activeRange, validRange); // might return null 5310 // it's invalid if the originally requested date is not contained, 5311 // or if the range is completely outside of the valid range. 5312 isValid = rangesIntersect(currentInfo.range, validRange); 5313 return { 5314 // constraint for where prev/next operations can go and where events can be dragged/resized to. 5315 // an object with optional start and end properties. 5316 validRange: validRange, 5317 // range the view is formally responsible for. 5318 // for example, a month view might have 1st-31st, excluding padded dates 5319 currentRange: currentInfo.range, 5320 // name of largest unit being displayed, like "month" or "week" 5321 currentRangeUnit: currentInfo.unit, 5322 isRangeAllDay: isRangeAllDay, 5323 // dates that display events and accept drag-n-drop 5324 // will be `null` if no dates accept events 5325 activeRange: activeRange, 5326 // date range with a rendered skeleton 5327 // includes not-active days that need some sort of DOM 5328 renderRange: renderRange, 5329 // Duration object that denotes the first visible time of any given day 5330 minTime: minTime, 5331 // Duration object that denotes the exclusive visible end time of any given day 5332 maxTime: maxTime, 5333 isValid: isValid, 5334 // how far the current date will move for a prev/next operation 5335 dateIncrement: this.buildDateIncrement(currentInfo.duration) 5336 // pass a fallback (might be null) ^ 5337 }; 5338 }; 5339 // Builds an object with optional start/end properties. 5340 // Indicates the minimum/maximum dates to display. 5341 // not responsible for trimming hidden days. 5342 DateProfileGenerator.prototype.buildValidRange = function () { 5343 return this.getRangeOption('validRange', this.calendar.getNow()) || 5344 { start: null, end: null }; // completely open-ended 5345 }; 5346 // Builds a structure with info about the "current" range, the range that is 5347 // highlighted as being the current month for example. 5348 // See build() for a description of `direction`. 5349 // Guaranteed to have `range` and `unit` properties. `duration` is optional. 5350 DateProfileGenerator.prototype.buildCurrentRangeInfo = function (date, direction) { 5351 var _a = this, viewSpec = _a.viewSpec, dateEnv = _a.dateEnv; 5352 var duration = null; 5353 var unit = null; 5354 var range = null; 5355 var dayCount; 5356 if (viewSpec.duration) { 5357 duration = viewSpec.duration; 5358 unit = viewSpec.durationUnit; 5359 range = this.buildRangeFromDuration(date, direction, duration, unit); 5360 } 5361 else if ((dayCount = this.options.dayCount)) { 5362 unit = 'day'; 5363 range = this.buildRangeFromDayCount(date, direction, dayCount); 5364 } 5365 else if ((range = this.buildCustomVisibleRange(date))) { 5366 unit = dateEnv.greatestWholeUnit(range.start, range.end).unit; 5367 } 5368 else { 5369 duration = this.getFallbackDuration(); 5370 unit = greatestDurationDenominator(duration).unit; 5371 range = this.buildRangeFromDuration(date, direction, duration, unit); 5372 } 5373 return { duration: duration, unit: unit, range: range }; 5374 }; 5375 DateProfileGenerator.prototype.getFallbackDuration = function () { 5376 return createDuration({ day: 1 }); 5377 }; 5378 // Returns a new activeRange to have time values (un-ambiguate) 5379 // minTime or maxTime causes the range to expand. 5380 DateProfileGenerator.prototype.adjustActiveRange = function (range, minTime, maxTime) { 5381 var dateEnv = this.dateEnv; 5382 var start = range.start; 5383 var end = range.end; 5384 if (this.viewSpec.class.prototype.usesMinMaxTime) { 5385 // expand active range if minTime is negative (why not when positive?) 5386 if (asRoughDays(minTime) < 0) { 5387 start = startOfDay(start); // necessary? 5388 start = dateEnv.add(start, minTime); 5389 } 5390 // expand active range if maxTime is beyond one day (why not when positive?) 5391 if (asRoughDays(maxTime) > 1) { 5392 end = startOfDay(end); // necessary? 5393 end = addDays(end, -1); 5394 end = dateEnv.add(end, maxTime); 5395 } 5396 } 5397 return { start: start, end: end }; 5398 }; 5399 // Builds the "current" range when it is specified as an explicit duration. 5400 // `unit` is the already-computed greatestDurationDenominator unit of duration. 5401 DateProfileGenerator.prototype.buildRangeFromDuration = function (date, direction, duration, unit) { 5402 var dateEnv = this.dateEnv; 5403 var alignment = this.options.dateAlignment; 5404 var dateIncrementInput; 5405 var dateIncrementDuration; 5406 var start; 5407 var end; 5408 var res; 5409 // compute what the alignment should be 5410 if (!alignment) { 5411 dateIncrementInput = this.options.dateIncrement; 5412 if (dateIncrementInput) { 5413 dateIncrementDuration = createDuration(dateIncrementInput); 5414 // use the smaller of the two units 5415 if (asRoughMs(dateIncrementDuration) < asRoughMs(duration)) { 5416 alignment = greatestDurationDenominator(dateIncrementDuration, !getWeeksFromInput(dateIncrementInput)).unit; 5417 } 5418 else { 5419 alignment = unit; 5420 } 5421 } 5422 else { 5423 alignment = unit; 5424 } 5425 }
5426 // if the view displays a single day or smaller 5427 if (asRoughDays(duration) <= 1) { 5428 if (this.isHiddenDay(start)) { 5429 start = this.skipHiddenDays(start, direction); 5430 start = startOfDay(start); 5431 } 5432 } 5433 function computeRes() { 5434 start = dateEnv.startOf(date, alignment); 5435 end = dateEnv.add(start, duration); 5436 res = { start: start, end: end }; 5437 } 5438 computeRes(); 5439 // if range is completely enveloped by hidden days, go past the hidden days 5440 if (!this.trimHiddenDays(res)) { 5441 date = this.skipHiddenDays(date, direction); 5442 computeRes(); 5443 } 5444 return res; 5445 }; 5446 // Builds the "current" range when a dayCount is specified. 5447 DateProfileGenerator.prototype.buildRangeFromDayCount = function (date, direction, dayCount) { 5448 var dateEnv = this.dateEnv; 5449 var customAlignment = this.options.dateAlignment; 5450 var runningCount = 0; 5451 var start = date; 5452 var end; 5453 if (customAlignment) { 5454 start = dateEnv.startOf(start, customAlignment); 5455 } 5456 start = startOfDay(start); 5457 start = this.skipHiddenDays(start, direction); 5458 end = start; 5459 do { 5460 end = addDays(end, 1); 5461 if (!this.isHiddenDay(end)) { 5462 runningCount++; 5463 } 5464 } while (runningCount < dayCount); 5465 return { start: start, end: end }; 5466 }; 5467 // Builds a normalized range object for the "visible" range, 5468 // which is a way to define the currentRange and activeRange at the same time. 5469 DateProfileGenerator.prototype.buildCustomVisibleRange = function (date) { 5470 var dateEnv = this.dateEnv; 5471 var visibleRange = this.getRangeOption('visibleRange', dateEnv.toDate(date)); 5472 if (visibleRange && (visibleRange.start == null || visibleRange.end == null)) { 5473 return null; 5474 } 5475 return visibleRange; 5476 }; 5477 // Computes the range that will represent the element/cells for *rendering*, 5478 // but which may have voided days/times. 5479 // not responsible for trimming hidden days. 5480 DateProfileGenerator.prototype.buildRenderRange = function (currentRange, currentRangeUnit, isRangeAllDay) { 5481 return currentRange; 5482 }; 5483 // Compute the duration value that should be added/substracted to the current date 5484 // when a prev/next operation happens. 5485 DateProfileGenerator.prototype.buildDateIncrement = function (fallback) { 5486 var dateIncrementInput = this.options.dateIncrement; 5487 var customAlignment; 5488 if (dateIncrementInput) { 5489 return createDuration(dateIncrementInput); 5490 } 5491 else if ((customAlignment = this.options.dateAlignment)) { 5492 return createDuration(1, customAlignment); 5493 } 5494 else if (fallback) { 5495 return fallback; 5496 } 5497 else { 5498 return createDuration({ days: 1 }); 5499 } 5500 }; 5501 // Arguments after name will be forwarded to a hypothetical function value 5502 // WARNING: passed-in arguments will be given to generator functions as-is and can cause side-effects. 5503 // Always clone your objects if you fear mutation. 5504 DateProfileGenerator.prototype.getRangeOption = function (name) { 5505 var otherArgs = []; 5506 for (var _i = 1; _i < arguments.length; _i++) { 5507 otherArgs[_i - 1] = arguments[_i]; 5508 } 5509 var val = this.options[name]; 5510 if (typeof val === 'function') { 5511 val = val.apply(null, otherArgs); 5512 } 5513 if (val) { 5514 val = parseRange(val, this.dateEnv); 5515 } 5516 if (val) { 5517 val = computeVisibleDayRange(val); 5518 } 5519 return val; 5520 }; 5521 /* Hidden Days 5522 ------------------------------------------------------------------------------------------------------------------*/ 5523 // Initializes internal variables related to calculating hidden days-of-week 5524 DateProfileGenerator.prototype.initHiddenDays = function () { 5525 var hiddenDays = this.options.hiddenDays || []; // array of day-of-week indices that are hidden
5526 var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool) 5527 var dayCnt = 0; 5528 var i; 5529 if (this.options.weekends === false) { 5530 hiddenDays.push(0, 6); // 0=sunday, 6=saturday 5531 } 5532 for (i = 0; i < 7; i++) { 5533 if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) { 5534 dayCnt++; 5535 } 5536 } 5537 if (!dayCnt) { 5538 throw new Error('invalid hiddenDays'); // all days were hidden? bad. 5539 } 5540 this.isHiddenDayHash = isHiddenDayHash; 5541 }; 5542 // Remove days from the beginning and end of the range that are computed as hidden. 5543 // If the whole range is trimmed off, returns null 5544 DateProfileGenerator.prototype.trimHiddenDays = function (range) { 5545 var start = range.start; 5546 var end = range.end; 5547 if (start) { 5548 start = this.skipHiddenDays(start); 5549 } 5550 if (end) { 5551 end = this.skipHiddenDays(end, -1, true); 5552 } 5553 if (start == null || end == null || start < end) { 5554 return { start: start, end: end }; 5555 } 5556 return null; 5557 }; 5558 // Is the current day hidden? 5559 // `day` is a day-of-week index (0-6), or a Date (used for UTC) 5560 DateProfileGenerator.prototype.isHiddenDay = function (day) { 5561 if (day instanceof Date) { 5562 day = day.getUTCDay(); 5563 } 5564 return this.isHiddenDayHash[day]; 5565 }; 5566 // Incrementing the current day until it is no longer a hidden day, returning a copy. 5567 // DOES NOT CONSIDER validRange! 5568 // If the initial value of `date` is not a hidden day, don't do anything. 5569 // Pass `isExclusive` as `true` if you are dealing with an end date. 5570 // `inc` defaults to `1` (increment one day forward each time) 5571 DateProfileGenerator.prototype.skipHiddenDays = function (date, inc, isExclusive) { 5572 if (inc === void 0) { inc = 1; } 5573 if (isExclusive === void 0) { isExclusive = false; } 5574 while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) { 5575 date = addDays(date, inc); 5576 } 5577 return date; 5578 }; 5579 return DateProfileGenerator; 5580 }());
5581 // TODO: find a way to avoid comparing DateProfiles. it's tedious 5582 function isDateProfilesEqual(p0, p1) { 5583 return rangesEqual(p0.activeRange, p1.activeRange) && 5584 rangesEqual(p0.validRange, p1.validRange) && 5585 durationsEqual(p0.minTime, p1.minTime) && 5586 durationsEqual(p0.maxTime, p1.maxTime); 5587 } 5588 5589 function reduce (state, action, calendar) { 5590 var viewType = reduceViewType(state.viewType, action); 5591 var dateProfile = reduceDateProfile(state.dateProfile, action, state.currentDate, viewType, calendar); 5592 var eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendar); 5593 var nextState = __assign({}, state, { viewType: viewType, 5594 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) }); 5595 for (var _i = 0, _a = calendar.pluginSystem.hooks.reducers; _i < _a.length; _i++) { 5596 var reducerFunc = _a[_i]; 5597 nextState = reducerFunc(nextState, action, calendar); 5598 } 5599 // console.log(action.type, nextState) 5600 return nextState; 5601 } 5602 function reduceViewType(currentViewType, action) { 5603 switch (action.type) { 5604 case 'SET_VIEW_TYPE': 5605 return action.viewType; 5606 default: 5607 return currentViewType; 5608 } 5609 } 5610 function reduceDateProfile(currentDateProfile, action, currentDate, viewType, calendar) { 5611 var newDateProfile; 5612 switch (action.type) { 5613 case 'PREV': 5614 newDateProfile = calendar.dateProfileGenerators[viewType].buildPrev(currentDateProfile, currentDate); 5615 break; 5616 case 'NEXT': 5617 newDateProfile = calendar.dateProfileGenerators[viewType].buildNext(currentDateProfile, currentDate); 5618 break; 5619 case 'SET_DATE': 5620 if (!currentDateProfile.activeRange || 5621 !rangeContainsMarker(currentDateProfile.currentRange, action.dateMarker)) { 5622 newDateProfile = calendar.dateProfileGenerators[viewType].build(action.dateMarker, undefined, true // forceToValid 5623 ); 5624 } 5625 break; 5626 case 'SET_VIEW_TYPE': 5627 var generator = calendar.dateProfileGenerators[viewType]; 5628 if (!generator) { 5629 throw new Error(viewType ? 5630 'The FullCalendar view "' + viewType + '" does not exist. Make sure your plugins are loaded correctly.' : 5631 'No available FullCalendar view plugins.'); 5632 } 5633 newDateProfile = generator.build(action.dateMarker || currentDate, undefined, true // forceToValid 5634 ); 5635 break; 5636 } 5637 if (newDateProfile && 5638 newDateProfile.isValid && 5639 !(currentDateProfile && isDateProfilesEqual(currentDateProfile, newDateProfile))) { 5640 return newDateProfile; 5641 } 5642 else { 5643 return currentDateProfile; 5644 } 5645 } 5646 function reduceCurrentDate(currentDate, action, dateProfile) { 5647 switch (action.type) { 5648 case 'PREV': 5649 case 'NEXT': 5650 if (!rangeContainsMarker(dateProfile.currentRange, currentDate)) { 5651 return dateProfile.currentRange.start; 5652 } 5653 else { 5654 return currentDate; 5655 } 5656 case 'SET_DATE': 5657 case 'SET_VIEW_TYPE': 5658 var newDate = action.dateMarker || currentDate; 5659 if (dateProfile.activeRange && !rangeContainsMarker(dateProfile.activeRange, newD
5659ate)) { 5660 return dateProfile.currentRange.start; 5661 } 5662 else { 5663 return newDate; 5664 } 5665 default: 5666 return currentDate; 5667 } 5668 } 5669 function reduceDateSelection(currentSelection, action, calendar) { 5670 switch (action.type) { 5671 case 'SELECT_DATES': 5672 return action.selection; 5673 case 'UNSELECT_DATES': 5674 return null; 5675 default: 5676 return currentSelection; 5677 } 5678 } 5679 function reduceSelectedEvent(currentInstanceId, action) { 5680 switch (action.type) { 5681 case 'SELECT_EVENT': 5682 return action.eventInstanceId; 5683 case 'UNSELECT_EVENT': 5684 return ''; 5685 default: 5686 return currentInstanceId; 5687 } 5688 } 5689 function reduceEventDrag(currentDrag, action, sources, calendar) { 5690 switch (action.type) { 5691 case 'SET_EVENT_DRAG': 5692 var newDrag = action.state; 5693 return { 5694 affectedEvents: newDrag.affectedEvents, 5695 mutatedEvents: newDrag.mutatedEvents, 5696 isEvent: newDrag.isEvent, 5697 origSeg: newDrag.origSeg 5698 }; 5699 case 'UNSET_EVENT_DRAG': 5700 return null; 5701 default: 5702 return currentDrag; 5703 } 5704 } 5705 function reduceEventResize(currentResize, action, sources, calendar) { 5706 switch (action.type) { 5707 case 'SET_EVENT_RESIZE': 5708 var newResize = action.state; 5709 return { 5710 affectedEvents: newResize.affectedEvents, 5711 mutatedEvents: newResize.mutatedEvents, 5712 isEvent: newResize.isEvent, 5713 origSeg: newResize.origSeg 5714 }; 5715 case 'UNSET_EVENT_RESIZE': 5716 return null; 5717 default: 5718 return currentResize; 5719 } 5720 } 5721 function computeLoadingLevel(eventSources) { 5722 var cnt = 0; 5723 for (var sourceId in eventSources) { 5724 if (eventSources[sourceId].isFetching) { 5725 cnt++; 5726 } 5727 } 5728 return cnt; 5729 } 5730 5731 var STANDARD_PROPS = { 5732 start: null, 5733 end: null, 5734 allDay: Boolean 5735 }; 5736 function parseDateSpan(raw, dateEnv, defaultDuration) { 5737 var span = parseOpenDateSpan(raw, dateEnv); 5738 var range = span.range; 5739 if (!range.start) { 5740 return null; 5741 } 5742 if (!range.end) { 5743 if (defaultDuration == null) { 5744 return null; 5745 } 5746 else { 5747 range.end = dateEnv.add(range.start, defaultDuration); 5748 } 5749 } 5750 return span; 5751 } 5752 /* 5753 TODO: somehow combine with parseRange? 5754 Will return null if the start/end props were present but parsed invalidly. 5755 */ 5756 function parseOpenDateSpan(raw, dateEnv) { 5757 var leftovers = {}; 5758 var standardProps = refineProps(raw, STANDARD_PROPS, {}, leftovers); 5759 var startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null; 5760 var endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null; 5761 var allDay = standardProps.allDay; 5762 if (allDay == null) { 5763 allDay = (startMeta && startMeta.isTimeUnspecified) && 5764 (!endMeta || endMeta.isTimeUnspecified); 5765 } 5766 // use this leftover object as the selection object 5767 leftovers.range = { 5768 start: startMeta ? startMeta.marker : null, 5769 end: endMeta ? endMeta.marker : null 5770 }; 5771 leftovers.allDay = allDay; 5772 return leftovers; 5773 } 5774 function isDateSpansEqual(span0, span1) { 5775 return rangesEqual(span0.range, span1.range) && 5776 span0.allDay === span1.allDay && 5777 isSpanPropsEqual(span0, span1); 5778 } 5779 // the NON-DATE-RELATED props 5780 function isSpanPropsEqual(span0, span1) { 5781 for (var propName in span1) { 5782 if (propName !== 'range' && propName !== 'allDay') { 5783 if (span0[propName] !== span1[propName]) { 5784 return false;
5785 } 5786 } 5787 } 5788 // are there any props that span0 has that span1 DOESN'T have? 5789 // both have range/allDay, so no need to special-case. 5790 for (var propName in span0) { 5791 if (!(propName in span1)) { 5792 return false; 5793 } 5794 } 5795 return true; 5796 } 5797 function buildDateSpanApi(span, dateEnv) { 5798 return { 5799 start: dateEnv.toDate(span.range.start), 5800 end: dateEnv.toDate(span.range.end), 5801 startStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), 5802 endStr: dateEnv.formatIso(span.range.end, { omitTime: span.allDay }), 5803 allDay: span.allDay 5804 }; 5805 } 5806 function buildDatePointApi(span, dateEnv) { 5807 return { 5808 date: dateEnv.toDate(span.range.start), 5809 dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }), 5810 allDay: span.allDay 5811 }; 5812 } 5813 function fabricateEventRange(dateSpan, eventUiBases, calendar) { 5814 var def = parseEventDef({ editable: false }, '', // sourceId 5815 dateSpan.allDay, true, // hasEnd 5816 calendar); 5817 return { 5818 def: def, 5819 ui: compileEventUi(def, eventUiBases), 5820 instance: createEventInstance(def.defId, dateSpan.range), 5821 range: dateSpan.range, 5822 isStart: true, 5823 isEnd: true 5824 }; 5825 } 5826 5827 function compileViewDefs(defaultConfigs, overrideConfigs) { 5828 var hash = {}; 5829 var viewType; 5830 for (viewType in defaultConfigs) { 5831 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5832 } 5833 for (viewType in overrideConfigs) { 5834 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5835 } 5836 return hash; 5837 } 5838 function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5839 if (hash[viewType]) { 5840 return hash[viewType]; 5841 } 5842 var viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs); 5843 if (viewDef) { 5844 hash[viewType] = viewDef; 5845 } 5846 return viewDef; 5847 } 5848 function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) { 5849 var defaultConfig = defaultConfigs[viewType]; 5850 var overrideConfig = overrideConfigs[viewType]; 5851 var queryProp = function (name) { 5852 return (defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] : 5853 ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null); 5854 }; 5855 var theClass = queryProp('class'); 5856 var superType = queryProp('superType'); 5857 if (!superType && theClass) { 5858 superType = 5859 findViewNameBySubclass(theClass, overrideConfigs) || 5860 findViewNameBySubclass(theClass, defaultConfigs); 5861 } 5862 var superDef = superType ? ensureViewDef(superType, hash, defaultConfigs, overrideConfigs) : null; 5863 if (!theClass && superDef) { 5864 theClass = superDef.class; 5865 } 5866 if (!theClass) { 5867 return null; // don't throw a warning, might be settings for a single-unit view 5868 } 5869 return { 5870 type: viewType, 5871 class: theClass, 5872 defaults: __assign({}, (superDef ? superDef.defaults : {}), (defaultConfig ? defaultConfig.options : {})), 5873 overrides: __assign({}, (superDef ? superDef.overrides : {}), (overrideConfig ? overrideConfig.options : {})) 5874 }; 5875 } 5876 function findViewNameBySubclass(viewSubclass, configs) { 5877 var superProto = Object.getPrototypeOf(viewSubclass.prototype); 5878 for (var viewType in configs) { 5879 var parsed = configs[viewType]; 5880 // need DIRECT subclass, so instanceof won't do it 5881 if (parsed.class && parsed.class.prototype === superProto) { 5882 return viewType; 5883 } 5884 } 5885 return ''; 5886 } 5887 5888 function parseViewConfigs(inputs) { 5889 return mapHash(inputs, parseViewConfig); 5890 } 5891 var VIEW_DEF_PROPS = { 5892 type: String, 5893 class: null 5894 }; 5895 function parseViewConfig(input) { 5896 if (typeof input === 'function') { 5897 input = { class: input }; 5898 } 5899 var options = {}; 5900 var props = refineProps(input, VIEW_DEF_PROPS, {}, options); 5901 return { 5902 superType: props.type, 5903 class: props.class, 5904 options: options 5905 }; 5906 } 5907 5908 function buildViewSpecs(defaultInputs, optionsManager) { 5909 var defaultConfigs = parseViewConfigs(defaultInputs); 5910 var overrideConfigs = parseViewConfigs(optionsManager.overrides.views); 5911 var viewDefs = compileViewDefs(defaultConfigs, overrideConfigs); 5912 return mapHash(viewDefs, function (viewDef) { 5913 return buildViewSpec(viewDef, overrideConfigs, optionsManager); 5914 }); 5915 } 5916 function buildViewSpec(viewDef, overrideConfigs, optionsManager) { 5917 var durationInput = viewDef.overrides.duration || 5918 viewDef.defaults.duration || 5919 optionsManager.dynamicOverrides.duration || 5920 optionsManager.overrides.duration; 5921 var duration = null; 5922 var durationUnit = ''; 5923 var singleUnit = ''; 5924 var singleUnitOverrides = {}; 5925 if (durationInput) { 5926 duration = createDuration(durationInput); 5927 if (duration) { // valid? 5928 var denom = greatestDurationDenominator(duration, !getWeeksFromInput(durationInput)); 5929 durationUnit = denom.unit; 5930 if (denom.value === 1) { 5931 singleUnit = durationUnit; 5932 singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].options : {}; 5933 } 5934 } 5935 } 5936 var queryButtonText = function (options) { 5937 var buttonTextMap = options.buttonText || {}; 5938 var buttonTextKey = viewDef.defaults.buttonTextKey; 5939 if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) { 5940 return buttonTextMap[buttonTextKey]; 5941 } 5942 if (buttonTextMap[viewDef.type] != null) { 5943 return buttonTextMap[viewDef.type]; 5944 } 5945 if (buttonTextMap[singleUnit] != null) { 5946 return buttonTextMap[singleUnit]; 5947 } 5948 }; 5949 return { 5950 type: viewDef.type, 5951 class: viewDef.class, 5952 duration: duration, 5953 durationUnit: durationUnit, 5954 singleUnit: singleUnit, 5955 options: __assign({}, globalDefaults, viewDef.defaults, optionsManager.dirDefaults, optionsManager.localeDefaults, optionsManager.overrides, singleUnitOverrides, viewDef.overrides, optionsManager.dynamicOverrides), 5956 buttonTextOverride: queryButtonText(optionsManager.dynamicOverrides) || 5957 queryButtonText(optionsManager.overrides) || // constructor-specified buttonText lookup hash takes precedence 5958 viewDef.overrides.buttonText, 5959 buttonTextDefault: queryButtonText(optionsManager.localeDefaults) || 5960 queryButtonText(optionsManager.dirDefaults) || 5961 viewDef.defaults.buttonText || 5962 queryButtonText(globalDefaults) || 5963 viewDef.type // fall back to given view name 5964 }; 5965 } 5966 5967 var Toolbar = /** @class */ (function (_super) { 5968 __extends(Toolbar, _super); 5969 function Toolbar(context, extraClassName) { 5970 var _this = _super.call(this, context) || this; 5971 _this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout); 5972 _this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]); 5973 _this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]); 5974 _this._updateToday = memoizeRendering(_this.updateToday, null, [_this._renderLayout]); 5975 _this._updatePrev = memoizeRendering(_this.updatePrev, null, [_this._renderLayout]); 5976 _this._updateNext = memoizeRendering(_this.updateNext, null, [_this._renderLayout]); 5977 _this.el = createElement('div', { className: 'fc-toolbar ' + extraClassName }); 5978 return _this; 5979 } 5980 Toolbar.prototype.destroy = function () { 5981 _super.prototype.destroy.call(this); 5982 this._renderLayout.unrender(); // should unrender everything else 5983 removeElement(this.el); 5984 }; 5985 Toolbar.prototype.render = function (props) { 5986 this._renderLayout(props.layout); 5987 this._updateTitle(props.title); 5988 this._updateActiveButton(props.activeButton); 5989 this._updateToday(props.isTodayEnabled); 5990 this._updatePrev(props.isPrevEnabled); 5991 this._updateNext(props.isNextEnabled); 5992 }; 5993 Toolbar.prototype.renderLayout = function (layout) { 5994 var el = this.el; 5995 this.viewsWithButtons = []; 5996 appendToElement(el, this.renderSection('left', layout.left)); 5997 appendToElement(el, this.renderSection('center', layout.center)); 5998 appendToElement(el, this.renderSection('right', layout.right)); 5999 }; 6000 Toolbar.prototype.unrenderLayout = function () { 6001 this.el.innerHTML = ''; 6002 }; 6003 Toolbar.prototype.renderSection = function (position, buttonStr) { 6004 var _this = this; 6005 var _a = this, theme = _a.theme, calendar = _a.calendar; 6006 var optionsManager = calendar.optionsManager; 6007 var viewSpecs = calendar.viewSpecs; 6008 var sectionEl = createElement('div', { className: 'fc-' + position }); 6009 var calendarCustomButtons = optionsManager.computed.customButtons || {}; 6010 var calendarButtonTextOverrides = optionsManager.overrides.buttonText || {}; 6011 var calendarButtonText = optionsManager.computed.buttonText || {}; 6012 if (buttonStr) { 6013 buttonStr.split(' ').forEach(function (buttonGroupStr, i) { 6014 var groupChildren = []; 6015 var isOnlyButtons = true; 6016 var groupEl; 6017 buttonGroupStr.split(',').forEach(function (buttonName, j) { 6018 var customButtonProps; 6019 var viewSpec; 6020 var buttonClick; 6021 var buttonIcon; // only one of these will be set 6022 var buttonText; // " 6023 var buttonInnerHtml;
6024 var buttonClasses; 6025 var buttonEl; 6026 var buttonAriaAttr; 6027 if (buttonName === 'title') { 6028 groupChildren.push(htmlToElement('<h2> </h2>')); // we always want it to take up height 6029 isOnlyButtons = false; 6030 } 6031 else { 6032 if ((customButtonProps = calendarCustomButtons[buttonName])) { 6033 buttonClick = function (ev) { 6034 if (customButtonProps.click) { 6035 customButtonProps.click.call(buttonEl, ev); 6036 } 6037 }; 6038 (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) || 6039 (buttonIcon = theme.getIconClass(buttonName)) || 6040 (buttonText = customButtonProps.text); 6041 } 6042 else if ((viewSpec = viewSpecs[buttonName])) { 6043 _this.viewsWithButtons.push(buttonName); 6044 buttonClick = function () { 6045 calendar.changeView(buttonName); 6046 }; 6047 (buttonText = viewSpec.buttonTextOverride) || 6048 (buttonIcon = theme.getIconClass(buttonName)) || 6049 (buttonText = viewSpec.buttonTextDefault); 6050 } 6051 else if (calendar[buttonName]) { // a calendar method 6052 buttonClick = function () { 6053 calendar[buttonName](); 6054 }; 6055 (buttonText = calendarButtonTextOverrides[buttonName]) || 6056 (buttonIcon = theme.getIconClass(buttonName)) || 6057 (buttonText = calendarButtonText[buttonName]); 6058 // ^ everything else is considered default 6059 } 6060 if (buttonClick) { 6061 buttonClasses = [ 6062 'fc-' + buttonName + '-button', 6063 theme.getClass('button') 6064 ]; 6065 if (buttonText) { 6066 buttonInnerHtml = htmlEscape(buttonText); 6067 buttonAriaAttr = ''; 6068 } 6069 else if (buttonIcon) { 6070 buttonInnerHtml = "<span class='" + buttonIcon + "'></span>"; 6071 buttonAriaAttr = ' aria-label="' + buttonName + '"'; 6072 } 6073 buttonEl = htmlToElement(// type="button" so that it doesn't submit a form 6074 '<button type="button" class="' + buttonClasses.join(' ') + '"' + 6075 buttonAriaAttr + 6076 '>' + buttonInnerHtml + '</button>'); 6077 buttonEl.addEventListener('click', buttonClick); 6078 groupChildren.push(buttonEl); 6079 } 6080 } 6081 }); 6082 if (groupChildren.length > 1) { 6083 groupEl = document.createElement('div'); 6084 var buttonGroupClassName = theme.getClass('buttonGroup'); 6085 if (isOnlyButtons && buttonGroupClassName) { 6086 groupEl.classList.add(buttonGroupClassName); 6087 } 6088 appendToElement(groupEl, groupChildren); 6089 sectionEl.appendChild(groupEl); 6090 } 6091 else { 6092 appendToElement(sectionEl, groupChildren); // 1 or 0 children 6093 } 6094 }); 6095 } 6096 return sectionEl; 6097 }; 6098 Toolbar.prototype.updateToday = function (isTodayEnabled) { 6099 this.toggleButtonEnabled('today', isTodayEnabled); 6100 }; 6101 Toolbar.prototype.updatePrev = function (isPrevEnabled) { 6102 this.toggleButtonEnabled('prev', isPrevEnabled); 6103 }; 6104 Toolbar.prototype.updateNext = function (isNextEnabled) { 6105 this.toggleButtonEnabled('next', isNextEnabled); 6106 }; 6107 Toolbar.prototype.updateTitle = function (text) { 6108 findElements(this.el, 'h2').forEach(function (titleEl) { 6109 titleEl.innerText = text; 6110 }); 6111 }; 6112 Toolbar.prototype.updateActiveButton = function (buttonName) { 6113 var className = this.theme.getClass('buttonActive'); 6114 findElements(this.el, 'button').forEach(function (buttonEl) { 6115 if (buttonName && buttonEl.classList.contains('fc-'
6115+ buttonName + '-button')) { 6116 buttonEl.classList.add(className); 6117 } 6118 else { 6119 buttonEl.classList.remove(className); 6120 } 6121 }); 6122 }; 6123 Toolbar.prototype.toggleButtonEnabled = function (buttonName, bool) { 6124 findElements(this.el, '.fc-' + buttonName + '-button').forEach(function (buttonEl) { 6125 buttonEl.disabled = !bool; 6126 }); 6127 }; 6128 return Toolbar; 6129 }(Component)); 6130 6131 var CalendarComponent = /** @class */ (function (_super) { 6132 __extends(CalendarComponent, _super); 6133 function CalendarComponent(context, el) { 6134 var _this = _super.call(this, context) || this; 6135 _this._renderToolbars = memoizeRendering(_this.renderToolbars); 6136 _this.buildViewPropTransformers = memoize(buildViewPropTransformers); 6137 _this.el = el; 6138 prependToElement(el, _this.contentEl = createElement('div', { className: 'fc-view-container' })); 6139 var calendar = _this.calendar; 6140 for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) { 6141 var modifyViewContainer = _a[_i]; 6142 modifyViewContainer(_this.contentEl, calendar); 6143 } 6144 _this.toggleElClassNames(true); 6145 _this.computeTitle = memoize(computeTitle); 6146 _this.parseBusinessHours = memoize(function (input) { 6147 return parseBusinessHours(input, _this.calendar); 6148 }); 6149 return _this; 6150 } 6151 CalendarComponent.prototype.destroy = function () { 6152 if (this.header) { 6153 this.header.destroy(); 6154 } 6155 if (this.footer) { 6156 this.footer.destroy(); 6157 } 6158 if (this.view) { 6159 this.view.destroy(); 6160 } 6161 removeElement(this.contentEl); 6162 this.toggleElClassNames(false); 6163 _super.prototype.destroy.call(this); 6164 }; 6165 CalendarComponent.prototype.toggleElClassNames = function (bool) { 6166 var classList = this.el.classList; 6167 var dirClassName = 'fc-' + this.opt('dir'); 6168 var themeClassName = this.theme.getClass('widget'); 6169 if (bool) { 6170 classList.add('fc'); 6171 classList.add(dirClassName); 6172 classList.add(themeClassName); 6173 } 6174 else { 6175 classList.remove('fc'); 6176 classList.remove(dirClassName); 6177 classList.remove(themeClassName); 6178 } 6179 }; 6180 CalendarComponent.prototype.render = function (props) { 6181 this.freezeHeight(); 6182 var title = this.computeTitle(props.dateProfile, props.viewSpec.options); 6183 this._renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, props.dateProfileGenerator, title); 6184 this.renderView(props, title); 6185 this.updateSize(); 6186 this.thawHeight(); 6187 }; 6188 CalendarComponent.prototype.renderToolbars = function (viewSpec, dateProfile, currentDate, dateProfileGenerator, title) { 6189 var headerLayout = this.opt('header'); 6190 var footerLayout = this.opt('footer'); 6191 var now = this.calendar.getNow(); 6192 var todayInfo = dateProfileGenerator.build(now); 6193 var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate); 6194 var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate); 6195 var toolbarProps = { 6196 title: title, 6197 activeButton: viewSpec.type, 6198 isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now), 6199 isPrevEnabled: prevInfo.isValid, 6200 isNextEnabled: nextInfo.isValid 6201 }; 6202 if (headerLayout) { 6203 if (!this.header) { 6204 this.header = new Toolbar(this.context, 'fc-header-toolbar'); 6205 prependToElement(this.el, this.header.el); 6206 } 6207 this.header.receiveProps(__assign({ layout: headerLayout }, toolbarProps)); 6208 } 6209 else if (this.header) { 6210 this.header.destroy(); 6211 this.header = null; 6212 }
6213 if (footerLayout) { 6214 if (!this.footer) { 6215 this.footer = new Toolbar(this.context, 'fc-footer-toolbar'); 6216 appendToElement(this.el, this.footer.el); 6217 } 6218 this.footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps)); 6219 } 6220 else if (this.footer) { 6221 this.footer.destroy(); 6222 this.footer = null; 6223 } 6224 }; 6225 CalendarComponent.prototype.renderView = function (props, title) { 6226 var view = this.view; 6227 var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator; 6228 if (!view || view.viewSpec !== viewSpec) { 6229 if (view) { 6230 view.destroy(); 6231 } 6232 view = this.view = new viewSpec['class']({ 6233 calendar: this.calendar, 6234 view: null, 6235 dateEnv: this.dateEnv, 6236 theme: this.theme, 6237 options: viewSpec.options 6238 }, viewSpec, dateProfileGenerator, this.contentEl); 6239 } 6240 else { 6241 view.addScroll(view.queryScroll()); 6242 } 6243 view.title = title; // for the API 6244 var viewProps = { 6245 dateProfile: props.dateProfile, 6246 businessHours: this.parseBusinessHours(viewSpec.options.businessHours), 6247 eventStore: props.eventStore, 6248 eventUiBases: props.eventUiBases, 6249 dateSelection: props.dateSelection, 6250 eventSelection: props.eventSelection, 6251 eventDrag: props.eventDrag, 6252 eventResize: props.eventResize 6253 }; 6254 var transformers = this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers); 6255 for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) { 6256 var transformer = transformers_1[_i]; 6257 __assign(viewProps, transformer.transform(viewProps, viewSpec, props, view)); 6258 } 6259 view.receiveProps(viewProps); 6260 }; 6261 // Sizing 6262 // ----------------------------------------------------------------------------------------------------------------- 6263 CalendarComponent.prototype.updateSize = function (isResize) { 6264 if (isResize === void 0) { isResize = false; } 6265 var view = this.view; 6266 if (isResize) { 6267 view.addScroll(view.queryScroll()); 6268 } 6269 if (isResize || this.isHeightAuto == null) { 6270 this.computeHeightVars(); 6271 } 6272 view.updateSize(isResize, this.viewHeight, this.isHeightAuto); 6273 view.updateNowIndicator(); // we need to guarantee this will run after updateSize 6274 view.popScroll(isResize); 6275 }; 6276 CalendarComponent.prototype.computeHeightVars = function () { 6277 var calendar = this.calendar; // yuck. need to handle dynamic options 6278 var heightInput = calendar.opt('height'); 6279 var contentHeightInput = calendar.opt('contentHeight'); 6280 this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto'; 6281 if (typeof contentHeightInput === 'number') { // exists and not 'auto' 6282 this.viewHeight = contentHeightInput; 6283 } 6284 else if (typeof contentHeightInput === 'function') { // exists and is a function 6285 this.viewHeight = contentHeightInput(); 6286 } 6287 else if (typeof heightInput === 'number') { // exists and not 'auto' 6288 this.viewHeight = heightInput - this.queryToolbarsHeight(); 6289 } 6290 else if (typeof heightInput === 'function') { // exists and is a function 6291 this.viewHeight = heightInput() - this.queryToolbarsHeight(); 6292 } 6293 else if (heightInput === 'parent') { // set to height of parent element 6294 this.viewHeight = this.el.parentNode.offsetHeight - this.queryToolbarsHeight(); 6295 } 6296 else { 6297 this.viewHeight = Math.round(this.contentEl.offsetWidth / 6298 Math.max(calendar.opt('aspectRatio'), .5)); 6299 } 6300 }; 6301 CalendarComponent.prototype.queryToolbarsHeight = function () { 6302 var height = 0; 6303 if (this.header) { 6304 height += computeHeightAndMargins(this.header.el); 6305 } 6306 if (this.footer) { 6307 height += computeHeightAndMargins(this.footer.el); 6308 } 6309 return height; 6310 }; 6311 // Height "Freezing" 6312 // ----------------------------------------------------------------------------------------------------------------- 6313 CalendarComponent.prototype.freezeHeight = function () { 6314 applyStyle(this.el, { 6315 height: this.el.offsetHeight, 6316 overflow: 'hidden' 6317 }); 6318 }; 6319 CalendarComponent.prototype.thawHeight = function () { 6320 applyStyle(this.el, { 6321 height: '', 6322 overflow: '' 6323 }); 6324 }; 6325 return CalendarComponent; 6326 }(Component)); 6327 // Title and Date Formatting 6328 // ----------------------------------------------------------------------------------------------------------------- 6329 // Computes what the title at the top of the calendar should be for this view 6330 function computeTitle(dateProfile, viewOptions) { 6331 var range; 6332 // for views that span a large unit of time, show the proper interval, ignoring stray days before and after 6333 if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) { 6334 range = dateProfile.currentRange; 6335 } 6336 else { // for day units or smaller, use the actual day range 6337 range = dateProfile.activeRange; 6338 } 6339 return this.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay }); 6340 }
6341 // Generates the format string that should be used to generate the title for the current date range. 6342 // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`. 6343 function computeTitleFormat(dateProfile) { 6344 var currentRangeUnit = dateProfile.currentRangeUnit; 6345 if (currentRangeUnit === 'year') { 6346 return { year: 'numeric' }; 6347 } 6348 else if (currentRangeUnit === 'month') { 6349 return { year: 'numeric', month: 'long' }; // like "September 2014" 6350 } 6351 else { 6352 var days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end); 6353 if (days !== null && days > 1) { 6354 // multi-day range. shorter, like "Sep 9 - 10 2014" 6355 return { year: 'numeric', month: 'short', day: 'numeric' }; 6356 } 6357 else { 6358 // one day. longer, like "September 9 2014" 6359 return { year: 'numeric', month: 'long', day: 'numeric' }; 6360 } 6361 } 6362 } 6363 // Plugin 6364 // ----------------------------------------------------------------------------------------------------------------- 6365 function buildViewPropTransformers(theClasses) { 6366 return theClasses.map(function (theClass) { 6367 return new theClass(); 6368 }); 6369 } 6370 6371 var Interaction = /** @class */ (function () { 6372 function Interaction(settings) { 6373 this.component = settings.component; 6374 } 6375 Interaction.prototype.destroy = function () { 6376 }; 6377 return Interaction; 6378 }()); 6379 function parseInteractionSettings(component, input) { 6380 return { 6381 component: component, 6382 el: input.el, 6383 useEventCenter: input.useEventCenter != null ? input.useEventCenter : true 6384 }; 6385 } 6386 function interactionSettingsToStore(settings) { 6387 var _a; 6388 return _a = {}, 6389 _a[settings.component.uid] = settings, 6390 _a; 6391 } 6392 // global state 6393 var interactionSettingsStore = {}; 6394 6395 /* 6396 Detects when the user clicks on an event within a DateComponent 6397 */ 6398 var EventClicking = /** @class */ (function (_super) { 6399 __extends(EventClicking, _super); 6400 function EventClicking(settings) { 6401 var _this = _super.call(this, settings) || this; 6402 _this.handleSegClick = function (ev, segEl) { 6403 var component = _this.component; 6404 var seg = getElSeg(segEl); 6405 if (seg && // might be the <div> surrounding the more link 6406 component.isValidSegDownEl(ev.target)) { 6407 // our way to simulate a link click for elements that can't be <a> tags 6408 // grab before trigger fired in case trigger trashes DOM thru rerendering 6409 var hasUrlContainer = elementClosest(ev.target, '.fc-has-url'); 6410 var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : ''; 6411 component.publiclyTrigger('eventClick', [ 6412 { 6413 el: segEl, 6414 event: new EventApi(component.calendar, seg.eventRange.def, seg.eventRange.instance), 6415 jsEvent: ev, 6416 view: component.view 6417 } 6418 ]); 6419 if (url && !ev.defaultPrevented) { 6420 window.location.href = url; 6421 } 6422 } 6423 }; 6424 var component = settings.component; 6425 _this.destroy = listenBySelector(component.el, 'click', component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegClick); 6426 return _this; 6427 } 6428 return EventClicking; 6429 }(Interaction)); 6430 6431 /* 6432 Triggers events and adds/removes core classNames when the user's pointer 6433 enters/leaves event-elements of a component. 6434 */ 6435 var EventHovering = /** @class */ (function (_super) { 6436 __extends(EventHovering, _super); 6437 function EventHovering(settings) { 6438 var _this = _super.call(this, settings) || this; 6439 // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it 6440 _this.handleEventElRemove = function (el) { 6441 if (el === _this.currentSegEl) { 6442 _this.handleSegLeave(null, _this.currentSegEl); 6443 } 6444 }; 6445 _this.handleSegEnter = function (ev, segEl) { 6446 if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper 6447 segEl.classList.add('fc-allow-mouse-resize'); 6448 _this.currentSegEl = segEl; 6449 _this.triggerEvent('eventMouseEnter', ev, segEl); 6450 } 6451 }; 6452 _this.handleSegLeave = function (ev, segEl) { 6453 if (_this.currentSegEl) { 6454 segEl.classList.remove('fc-allow-mouse-resize'); 6455 _this.currentSegEl = null; 6456 _this.triggerEvent('eventMouseLeave', ev, segEl); 6457 } 6458 }; 6459 var component = settings.component; 6460 _this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave); 6461 component.calendar.on('eventElRemove', _this.handleEventElRemove); 6462 return _this; 6463 } 6464 EventHovering.prototype.destroy = function () { 6465 this.removeHoverListeners(); 6466 this.component.calendar.off('eventElRemove', this.handleEventElRemove); 6467 }; 6468 EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) { 6469 var component = this.component; 6470 var seg = getElSeg(segEl); 6471 if (!ev || component.isValidSegDownEl(ev.target)) { 6472 component.publiclyTrigger(publicEvName, [ 6473 { 6474 el: segEl, 6475 event: new EventApi(this.component.calendar, seg.eventRange.def, seg.eventRange.instance), 6476 jsEvent: ev, 6477 view: component.view 6478 } 6479 ]); 6480 } 6481 }; 6482 return EventHovering; 6483 }(Interaction)); 6484 6485 var StandardTheme = /** @class */ (function (_super) { 6486 __extends(StandardTheme, _super); 6487 function StandardTheme() { 6488 return _super !== null && _super.apply(this, arguments) || this; 6489 } 6490 return StandardTheme; 6491 }(Theme)); 6492 StandardTheme.prototype.classes = { 6493 widget: 'fc-unthemed', 6494 widgetHeader: 'fc-widget-header', 6495 widgetContent: 'fc-widget-content', 6496 buttonGroup: 'fc-button-group', 6497 button: 'fc-button fc-button-primary', 6498 buttonActive: 'fc-button-active', 6499 popoverHeader: 'fc-widget-header', 6500 popoverContent: 'fc-widget-content', 6501 // day grid 6502 headerRow: 'fc-widget-header', 6503 dayRow: 'fc-widget-content', 6504 // list view 6505 listView: 'fc-widget-content' 6506 }; 6507 StandardTheme.prototype.baseIconClass = 'fc-icon'; 6508 StandardTheme.prototype.iconClasses = { 6509 close: 'fc-icon-x', 6510 prev: 'fc-icon-chevron-left', 6511 next: 'fc-icon-chevron-right', 6512 prevYear: 'fc-icon-chevrons-left', 6513 nextYear: 'fc-icon-chevrons-right' 6514 }; 6515 StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; 6516 StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon'; 6517 StandardTheme.prototype.iconOverridePrefix = 'fc-icon-'; 6518 6519 var Calendar = /** @class */ (function () { 6520 function Calendar(el, overrides) { 6521 var _this = this; 6522 this.parseRawLocales = memoize(parseRawLocales); 6523 this.buildLocale = memoize(buildLocale); 6524 this.buildDateEnv = memoize(buildDateEnv); 6525 this.buildTheme = memoize(buildTheme); 6526 this.buildEventUiSingleBase = memoize(this._buildEventUiSingleBase); 6527 this.buildSelectionConfig = memoize(this._buildSelectionConfig); 6528 this.buildEventUiBySource = memoizeOutput(buildEventUiBySource, isPropsEqual); 6529 this.buildEventUiBases = memoize(buildEventUiBases); 6530 this.interactionsStore = {}; 6531 this.actionQueue = []; 6532 this.isReducing = false;
6533 // isDisplaying: boolean = false // installed in DOM? accepting renders? 6534 this.needsRerender = false; // needs a render? 6535 this.needsFullRerender = false; 6536 this.isRendering = false; // currently in the executeRender function? 6537 this.renderingPauseDepth = 0; 6538 this.buildDelayedRerender = memoize(buildDelayedRerender); 6539 this.afterSizingTriggers = {}; 6540 this.isViewUpdated = false; 6541 this.isDatesUpdated = false; 6542 this.isEventsUpdated = false; 6543 this.el = el; 6544 this.optionsManager = new OptionsManager(overrides || {}); 6545 this.pluginSystem = new PluginSystem(); 6546 // only do once. don't do in handleOptions. because can't remove plugins 6547 this.addPluginInputs(this.optionsManager.computed.plugins || []); 6548 this.handleOptions(this.optionsManager.computed); 6549 this.publiclyTrigger('_init'); // for tests 6550 this.hydrate(); 6551 this.calendarInteractions = this.pluginSystem.hooks.calendarInteractions 6552 .map(function (calendarInteractionClass) { 6553 return new calendarInteractionClass(_this); 6554 }); 6555 } 6556 Calendar.prototype.addPluginInputs = function (pluginInputs) { 6557 var pluginDefs = refinePluginDefs(pluginInputs); 6558 for (var _i = 0, pluginDefs_1 = pluginDefs; _i < pluginDefs_1.length; _i++) { 6559 var pluginDef = pluginDefs_1[_i]; 6560 this.pluginSystem.add(pluginDef); 6561 } 6562 }; 6563 Object.defineProperty(Calendar.prototype, "view", { 6564 // public API 6565 get: function () { 6566 return this.component ? this.component.view : null; 6567 }, 6568 enumerable: true, 6569 configurable: true 6570 }); 6571 // Public API for rendering 6572 // ----------------------------------------------------------------------------------------------------------------- 6573 Calendar.prototype.render = function () { 6574 if (!this.component) { 6575 this.renderableEventStore = createEmptyEventStore(); 6576 this.bindHandlers(); 6577 this.executeRender(); 6578 } 6579 else { 6580 this.requestRerender(true); 6581 } 6582 }; 6583 Calendar.prototype.destroy = function () { 6584 if (this.component) { 6585 this.unbindHandlers(); 6586 this.component.destroy(); // don't null-out. in case API needs access 6587 this.component = null; // umm ??? 6588 for (var _i = 0, _a = this.calendarInteractions; _i < _a.length; _i++) { 6589 var interaction = _a[_i]; 6590 interaction.destroy(); 6591 } 6592 this.publiclyTrigger('_destroyed'); 6593 } 6594 }; 6595 // Handlers 6596 // ----------------------------------------------------------------------------------------------------------------- 6597 Calendar.prototype.bindHandlers = function () { 6598 var _this = this; 6599 // event delegation for nav links 6600 this.removeNavLinkListener = listenBySelector(this.el, 'click', 'a[data-goto]', function (ev, anchorEl) { 6601 var gotoOptions = anchorEl.getAttribute('data-goto'); 6602 gotoOptions = gotoOptions ? JSON.parse(gotoOptions) : {}; 6603 var dateEnv = _this.dateEnv; 6604 var dateMarker = dateEnv.createMarker(gotoOptions.date); 6605 var viewType = gotoOptions.type; 6606 // property like "navLinkDayClick". might be a string or a function 6607 var customAction = _this.viewOpt('navLink' + capitaliseFirstLetter(viewType) + 'Click'); 6608 if (typeof customAction === 'function') { 6609 customAction(dateEnv.toDate(dateMarker), ev); 6610 } 6611 else { 6612 if (typeof customAction === 'string') { 6613 viewType = customAction; 6614 }
6615 _this.zoomTo(dateMarker, viewType); 6616 } 6617 }); 6618 if (this.opt('handleWindowResize')) { 6619 window.addEventListener('resize', this.windowResizeProxy = debounce(// prevents rapid calls 6620 this.windowResize.bind(this), this.opt('windowResizeDelay'))); 6621 } 6622 }; 6623 Calendar.prototype.unbindHandlers = function () { 6624 this.removeNavLinkListener(); 6625 if (this.windowResizeProxy) { 6626 window.removeEventListener('resize', this.windowResizeProxy); 6627 this.windowResizeProxy = null; 6628 } 6629 }; 6630 // Dispatcher 6631 // ----------------------------------------------------------------------------------------------------------------- 6632 Calendar.prototype.hydrate = function () { 6633 var _this = this; 6634 this.state = this.buildInitialState(); 6635 var rawSources = this.opt('eventSources') || []; 6636 var singleRawSource = this.opt('events'); 6637 var sources = []; // parsed 6638 if (singleRawSource) { 6639 rawSources.unshift(singleRawSource); 6640 } 6641 for (var _i = 0, rawSources_1 = rawSources; _i < rawSources_1.length; _i++) { 6642 var rawSource = rawSources_1[_i]; 6643 var source = parseEventSource(rawSource, this); 6644 if (source) { 6645 sources.push(source); 6646 } 6647 } 6648 this.batchRendering(function () { 6649 _this.dispatch({ type: 'INIT' }); // pass in sources here? 6650 _this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: sources }); 6651 _this.dispatch({ 6652 type: 'SET_VIEW_TYPE', 6653 viewType: _this.opt('defaultView') || _this.pluginSystem.hooks.defaultView 6654 }); 6655 }); 6656 }; 6657 Calendar.prototype.buildInitialState = function () { 6658 return { 6659 viewType: null, 6660 loadingLevel: 0, 6661 eventSourceLoadingLevel: 0, 6662 currentDate: this.getInitialDate(), 6663 dateProfile: null, 6664 eventSources: {}, 6665 eventStore: createEmptyEventStore(), 6666 dateSelection: null, 6667 eventSelection: '', 6668 eventDrag: null, 6669 eventResize: null 6670 }; 6671 }; 6672 Calendar.prototype.dispatch = function (action) { 6673 this.actionQueue.push(action); 6674 if (!this.isReducing) { 6675 this.isReducing = true; 6676 var oldState = this.state; 6677 while (this.actionQueue.length) { 6678 this.state = this.reduce(this.state, this.actionQueue.shift(), this); 6679 } 6680 var newState = this.state; 6681 this.isReducing = false; 6682 if (!oldState.loadingLevel && newState.loadingLevel) { 6683 this.publiclyTrigger('loading', [true]); 6684 } 6685 else if (oldState.loadingLevel && !newState.loadingLevel) { 6686 this.publiclyTrigger('loading', [false]); 6687 } 6688 var view = this.component && this.component.view; 6689 if (oldState.eventStore !== newState.eventStore || this.needsFullRerender) { 6690 if (oldState.eventStore) { 6691 this.isEventsUpdated = true; 6692 } 6693 } 6694 if (oldState.dateProfile !== newState.dateProfile || this.needsFullRerender) { 6695 if (oldState.dateProfile && view) { // why would view be null!? 6696 this.publiclyTrigger('datesDestroy', [ 6697 { 6698 view: view, 6699 el: view.el 6700 } 6701 ]); 6702 } 6703 this.isDatesUpdated = true; 6704 } 6705 if (oldState.viewType !== newState.viewType || this.needsFullRerender) { 6706 if (oldState.viewType && view) { // why would view be null!? 6707 this.publiclyTrigger('viewSkeletonDestroy', [ 6708 { 6709 view: view, 6710 el: view.el 6711 } 6712 ]); 6713 } 6714 this.isViewUpdated = true; 6715 } 6716 this.requestRerender(); 6717 } 6718 }; 6719 Calendar.prototype.reduce = function (state, action, calendar) { 6720 return reduce(state, action, calendar); 6721 }; 6722 // Render Queue 6723 // ----------------------------------------------------------------------------------------------------------------- 6724 Calendar.prototype.requestRerender = function (needsFull) { 6725 if (needsFull === void 0) { needsFull = false; } 6726 this.needsRerender = true; 6727 this.needsFullRerender = this.needsFullRerender || needsFull; 6728 this.delayedRerender(); // will call a debounced-version of tryRerender 6729 }; 6730 Calendar.prototype.tryRerender = function () { 6731 if (this.component && // must be accepting renders 6732 this.needsRerender && // indicates that a rerender was requested 6733 !this.renderingPauseDepth && // not paused 6734 !this.isRendering // not currently in the render loop 6735 ) {
6736 this.executeRender(); 6737 } 6738 }; 6739 Calendar.prototype.batchRendering = function (func) { 6740 this.renderingPauseDepth++; 6741 func(); 6742 this.renderingPauseDepth--; 6743 if (this.needsRerender) { 6744 this.requestRerender(); 6745 } 6746 }; 6747 // Rendering 6748 // ----------------------------------------------------------------------------------------------------------------- 6749 Calendar.prototype.executeRender = function () { 6750 var needsFullRerender = this.needsFullRerender; // save before clearing 6751 // clear these BEFORE the render so that new values will accumulate during render 6752 this.needsRerender = false; 6753 this.needsFullRerender = false; 6754 this.isRendering = true; 6755 this.renderComponent(needsFullRerender); 6756 this.isRendering = false; 6757 // received a rerender request while rendering 6758 if (this.needsRerender) { 6759 this.delayedRerender(); 6760 } 6761 }; 6762 /* 6763 don't call this directly. use executeRender instead 6764 */ 6765 Calendar.prototype.renderComponent = function (needsFull) { 6766 var _a = this, state = _a.state, component = _a.component; 6767 var viewType = state.viewType; 6768 var viewSpec = this.viewSpecs[viewType]; 6769 var savedScroll = (needsFull && component) ? component.view.queryScroll() : null; 6770 if (!viewSpec) { 6771 throw new Error("View type \"" + viewType + "\" is not valid"); 6772 } 6773 // if event sources are still loading and progressive rendering hasn't been enabled, 6774 // keep rendering the last fully loaded set of events 6775 var renderableEventStore = this.renderableEventStore = 6776 (state.eventSourceLoadingLevel && !this.opt('progressiveEventRendering')) ? 6777 this.renderableEventStore : 6778 state.eventStore; 6779 var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options); 6780 var eventUiBySource = this.buildEventUiBySource(state.eventSources); 6781 var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource); 6782 if (needsFull || !component) { 6783 if (component) { 6784 component.freezeHeight(); // next component will unfreeze it 6785 component.destroy(); 6786 } 6787 component = this.component = new CalendarComponent({ 6788 calendar: this, 6789 view: null, 6790 dateEnv: this.dateEnv, 6791 theme: this.theme, 6792 options: this.optionsManager.computed 6793 }, this.el); 6794 } 6795 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 })); 6796 if (savedScroll) { 6797 component.view.applyScroll(savedScroll, false); 6798 } 6799 if (this.isViewUpdated) { 6800 this.isViewUpdated = false; 6801 this.publiclyTrigger('viewSkeletonRender', [ 6802 { 6803 view: component.view, 6804 el: component.view.el 6805 } 6806 ]); 6807 } 6808 if (this.isDatesUpdated) { 6809 this.isDatesUpdated = false; 6810 this.publiclyTrigger('datesRender', [ 6811 { 6812 view: component.view, 6813 el: component.view.el 6814 } 6815 ]); 6816 } 6817 if (this.isEventsUpdated) { 6818 this.isEventsUpdated = false; 6819 } 6820 this.releaseAfterSizingTriggers(); 6821 }; 6822 // Options 6823 // ----------------------------------------------------------------------------------------------------------------- 6824 Calendar.prototype.setOption = function (name, val) { 6825 var _a; 6826 this.mutateOptions((_a = {}, _a[name] = val, _a), [], true); 6827 }; 6828 Calendar.prototype.getOption = function (name) { 6829 return this.optionsManager.computed[name]; 6830 }; 6831 Calendar.prototype.opt = function (name) { 6832 return this.optionsManager.computed[name]; 6833 }; 6834 Calendar.prototype.viewOpt = function (name) { 6835 return this.viewOpts()[name]; 6836 }; 6837 Calendar.prototype.viewOpts = function () { 6838 return this.viewSpecs[this.state.viewType].options; 6839 }; 6840 /* 6841 handles option changes (like a diff) 6842 */ 6843 Calendar.prototype.mutateOptions = function (updates, removals, isDynamic, deepEquals) { 6844 var _this = this; 6845 var changeHandlers = this.pluginSystem.hooks.optionChangeHandlers; 6846 var normalUpdates = {}; 6847 var specialUpdates = {}; 6848 var oldDateEnv = this.dateEnv; // do this before handleOptions 6849 var isTimeZoneDirty = false;
6850 var isSizeDirty = false; 6851 var anyDifficultOptions = Boolean(removals.length); 6852 for (var name_1 in updates) { 6853 if (changeHandlers[name_1]) { 6854 specialUpdates[name_1] = updates[name_1]; 6855 } 6856 else { 6857 normalUpdates[name_1] = updates[name_1]; 6858 } 6859 } 6860 for (var name_2 in normalUpdates) { 6861 if (/^(height|contentHeight|aspectRatio)$/.test(name_2)) { 6862 isSizeDirty = true; 6863 } 6864 else if (/^(defaultDate|defaultView)$/.test(name_2)) ; 6865 else { 6866 anyDifficultOptions = true; 6867 if (name_2 === 'timeZone') { 6868 isTimeZoneDirty = true; 6869 } 6870 } 6871 } 6872 this.optionsManager.mutate(normalUpdates, removals, isDynamic); 6873 if (anyDifficultOptions) { 6874 this.handleOptions(this.optionsManager.computed); 6875 this.needsFullRerender = true; 6876 } 6877 this.batchRendering(function () { 6878 if (anyDifficultOptions) { 6879 if (isTimeZoneDirty) { 6880 _this.dispatch({ 6881 type: 'CHANGE_TIMEZONE', 6882 oldDateEnv: oldDateEnv 6883 }); 6884 } 6885 /* HACK 6886 has the same effect as calling this.requestRerender(true) 6887 but recomputes the state's dateProfile 6888 */ 6889 _this.dispatch({ 6890 type: 'SET_VIEW_TYPE', 6891 viewType: _this.state.viewType 6892 }); 6893 } 6894 else if (isSizeDirty) { 6895 _this.updateSize(); 6896 } 6897 // special updates 6898 if (deepEquals) { 6899 for (var name_3 in specialUpdates) { 6900 changeHandlers[name_3](specialUpdates[name_3], _this, deepEquals); 6901 } 6902 } 6903 }); 6904 }; 6905 /* 6906 rebuilds things based off of a complete set of refined options 6907 */ 6908 Calendar.prototype.handleOptions = function (options) { 6909 var _this = this; 6910 var pluginHooks = this.pluginSystem.hooks; 6911 this.defaultAllDayEventDuration = createDuration(options.defaultAllDayEventDuration); 6912 this.defaultTimedEventDuration = createDuration(options.defaultTimedEventDuration); 6913 this.delayedRerender = this.buildDelayedRerender(options.rerenderDelay); 6914 this.theme = this.buildTheme(options); 6915 var available = this.parseRawLocales(options.locales); 6916 this.availableRawLocales = available.map; 6917 var locale = this.buildLocale(options.locale || available.defaultCode, available.map); 6918 this.dateEnv = this.buildDateEnv(locale, options.timeZone, pluginHooks.namedTimeZonedImpl, options.firstDay, options.weekNumberCalculation, options.weekLabel, pluginHooks.cmdFormatter); 6919 this.selectionConfig = this.buildSelectionConfig(options); // needs dateEnv. do after :( 6920 // ineffecient to do every time? 6921 this.viewSpecs = buildViewSpecs(pluginHooks.views, this.optionsManager); 6922 // ineffecient to do every time? 6923 this.dateProfileGenerators = mapHash(this.viewSpecs, function (viewSpec) { 6924 return new viewSpec.class.prototype.dateProfileGeneratorClass(viewSpec, _this); 6925 }); 6926 }; 6927 Calendar.prototype.getAvailableLocaleCodes = function () { 6928 return Object.keys(this.availableRawLocales); 6929 }; 6930 Calendar.prototype._buildSelectionConfig = function (rawOpts) { 6931 return processScopedUiProps('select', rawOpts, this); 6932 }; 6933 Calendar.prototype._buildEventUiSingleBase = function (rawOpts) { 6934 if (rawOpts.editable) { // so 'editable' affected events 6935 rawOpts = __assign({}, rawOpts, { eventEditable: true }); 6936 } 6937 return processScopedUiProps('event', rawOpts, this); 6938 }; 6939 // Trigger 6940 // ----------------------------------------------------------------------------------------------------------------- 6941 Calendar.prototype.hasPublicHandlers = function (name) { 6942 return this.hasHandlers(name) || 6943 this.opt(name); // handler specified in options 6944 }; 6945 Calendar.prototype.publiclyTrigger = function (name, args) { 6946 var optHandler = this.opt(name); 6947 this.triggerWith(name, this, args); 6948 if (optHandler) { 6949 return optHandler.apply(this, args); 6950 } 6951 }; 6952 Calendar.prototype.publiclyTriggerAfterSizing = function (name, args) { 6953 var afterSizingTriggers = this.afterSizingTriggers; 6954 (afterSizingTriggers[name] || (afterSizingTriggers[name] = [])).push(args); 6955 }; 6956 Calendar.prototype.releaseAfterSizingTriggers = function () { 6957 var afterSizingTriggers = this.afterSizingTriggers; 6958 for (var name_4 in afterSizingTriggers) { 6959 for (var _i = 0, _a = afterSizingTriggers[name_4]; _i < _a.length; _i++) { 6960 var args = _a[_i]; 6961 this.publiclyTrigger(name_4, args); 6962 } 6963 } 6964 this.afterSizingTriggers = {}; 6965 }; 6966 // View 6967 // ----------------------------------------------------------------------------------------------------------------- 6968 // Returns a boolean about whether the view is okay to instantiate at some point 6969 Calendar.prototype.isValidViewType = function (viewType) { 6970 return Boolean(this.viewSpecs[viewType]); 6971 }; 6972 Calendar.prototype.changeView = function (viewType, dateOrRange) { 6973 var dateMarker = null; 6974 if (dateOrRange) { 6975 if (dateOrRange.start && dateOrRange.end) { // a range 6976 this.optionsManager.mutate({ visibleRange: dateOrRange }, []); // will not rerender 6977 this.handleOptions(this.optionsManager.computed); // ...but yuck 6978 } 6979 else { // a date 6980 dateMarker = this.dateEnv.createMarker(dateOrRange); // just like gotoDate 6981 } 6982 } 6983 this.unselect(); 6984 this.dispatch({ 6985 type: 'SET_VIEW_TYPE', 6986 viewType: viewType, 6987 dateMarker: dateMarker 6988 }); 6989 };
6990 // Forces navigation to a view for the given date. 6991 // `viewType` can be a specific view name or a generic one like "week" or "day". 6992 // needs to change 6993 Calendar.prototype.zoomTo = function (dateMarker, viewType) { 6994 var spec; 6995 viewType = viewType || 'day'; // day is default zoom 6996 spec = this.viewSpecs[viewType] || 6997 this.getUnitViewSpec(viewType); 6998 this.unselect(); 6999 if (spec) { 7000 this.dispatch({ 7001 type: 'SET_VIEW_TYPE', 7002 viewType: spec.type, 7003 dateMarker: dateMarker 7004 }); 7005 } 7006 else { 7007 this.dispatch({ 7008 type: 'SET_DATE', 7009 dateMarker: dateMarker 7010 }); 7011 } 7012 }; 7013 // Given a duration singular unit, like "week" or "day", finds a matching view spec. 7014 // Preference is given to views that have corresponding buttons. 7015 Calendar.prototype.getUnitViewSpec = function (unit) { 7016 var component = this.component; 7017 var viewTypes = []; 7018 var i; 7019 var spec; 7020 // put views that have buttons first. there will be duplicates, but oh 7021 if (component.header) { 7022 viewTypes.push.apply(viewTypes, component.header.viewsWithButtons); 7023 } 7024 if (component.footer) { 7025 viewTypes.push.apply(viewTypes, component.footer.viewsWithButtons); 7026 } 7027 for (var viewType in this.viewSpecs) { 7028 viewTypes.push(viewType); 7029 } 7030 for (i = 0; i < viewTypes.length; i++) { 7031 spec = this.viewSpecs[viewTypes[i]]; 7032 if (spec) { 7033 if (spec.singleUnit === unit) { 7034 return spec; 7035 } 7036 } 7037 } 7038 }; 7039 // Current Date 7040 // ----------------------------------------------------------------------------------------------------------------- 7041 Calendar.prototype.getInitialDate = function () { 7042 var defaultDateInput = this.opt('defaultDate'); 7043 // compute the initial ambig-timezone date 7044 if (defaultDateInput != null) { 7045 return this.dateEnv.createMarker(defaultDateInput); 7046 } 7047 else { 7048 return this.getNow(); // getNow already returns unzoned 7049 } 7050 }; 7051 Calendar.prototype.prev = function () { 7052 this.unselect(); 7053 this.dispatch({ type: 'PREV' }); 7054 }; 7055 Calendar.prototype.next = function () { 7056 this.unselect(); 7057 this.dispatch({ type: 'NEXT' }); 7058 }; 7059 Calendar.prototype.prevYear = function () { 7060 this.unselect(); 7061 this.dispatch({ 7062 type: 'SET_DATE', 7063 dateMarker: this.dateEnv.addYears(this.state.currentDate, -1) 7064 }); 7065 }; 7066 Calendar.prototype.nextYear = function () { 7067 this.unselect(); 7068 this.dispatch({ 7069 type: 'SET_DATE', 7070 dateMarker: this.dateEnv.addYears(this.state.currentDate, 1) 7071 }); 7072 }; 7073 Calendar.prototype.today = function () { 7074 this.unselect(); 7075 this.dispatch({ 7076 type: 'SET_DATE', 7077 dateMarker: this.getNow() 7078 }); 7079 }; 7080 Calendar.prototype.gotoDate = function (zonedDateInput) { 7081 this.unselect(); 7082 this.dispatch({ 7083 type: 'SET_DATE', 7084 dateMarker: this.dateEnv.createMarker(zonedDateInput) 7085 }); 7086 }; 7087 Calendar.prototype.incrementDate = function (deltaInput) { 7088 var delta = createDuration(deltaInput); 7089 if (delta) { // else, warn about invalid input? 7090 this.unselect(); 7091 this.dispatch({ 7092 type: 'SET_DATE', 7093 dateMarker: this.dateEnv.add(this.state.currentDate, delta) 7094 }); 7095 } 7096 }; 7097 // for external API 7098 Calendar.prototype.getDate = function () { 7099 return this.dateEnv.toDate(this.state.currentDate); 7100 }; 7101 // Date Formatting Utils 7102 // ----------------------------------------------------------------------------------------------------------------- 7103 Calendar.prototype.formatDate = function (d, formatter) { 7104 var dateEnv = this.dateEnv; 7105 return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter)); 7106 }; 7107 // `settings` is for formatter AND isEndExclusive 7108 Calendar.prototype.formatRange = function (d0, d1, settings) { 7109 var dateEnv = this.dateEnv; 7110 return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings, this.opt('defaultRangeSeparator')), settings); 7111 }; 7112 Calendar.prototype.formatIso = function (d, omitTime) { 7113 var dateEnv = this.dateEnv; 7114 return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime: omitTime }); 7115 }; 7116 // Sizing 7117 // ----------------------------------------------------------------------------------------------------------------- 7118 Calendar.prototype.windowResize = function (ev) { 7119 if (!this.isHandlingWindowResize && 7120 this.component && // why? 7121 ev.target === window // not a jqui resize event 7122 ) { 7123 this.isHandlingWindowResize = true; 7124 this.updateSize(); 7125 this.publiclyTrigger('windowResize', [this.view]); 7126 this.isHandlingWindowResize = false;
7127 } 7128 }; 7129 Calendar.prototype.updateSize = function () { 7130 if (this.component) { // when? 7131 this.component.updateSize(true); 7132 } 7133 }; 7134 // Component Registration 7135 // ----------------------------------------------------------------------------------------------------------------- 7136 Calendar.prototype.registerInteractiveComponent = function (component, settingsInput) { 7137 var settings = parseInteractionSettings(component, settingsInput); 7138 var DEFAULT_INTERACTIONS = [ 7139 EventClicking, 7140 EventHovering 7141 ]; 7142 var interactionClasses = DEFAULT_INTERACTIONS.concat(this.pluginSystem.hooks.componentInteractions); 7143 var interactions = interactionClasses.map(function (interactionClass) { 7144 return new interactionClass(settings); 7145 }); 7146 this.interactionsStore[component.uid] = interactions; 7147 interactionSettingsStore[component.uid] = settings; 7148 }; 7149 Calendar.prototype.unregisterInteractiveComponent = function (component) { 7150 for (var _i = 0, _a = this.interactionsStore[component.uid]; _i < _a.length; _i++) { 7151 var listener = _a[_i]; 7152 listener.destroy(); 7153 } 7154 delete this.interactionsStore[component.uid]; 7155 delete interactionSettingsStore[component.uid]; 7156 }; 7157 // Date Selection / Event Selection / DayClick 7158 // ----------------------------------------------------------------------------------------------------------------- 7159 // this public method receives start/end dates in any format, with any timezone 7160 // NOTE: args were changed from v3 7161 Calendar.prototype.select = function (dateOrObj, endDate) { 7162 var selectionInput; 7163 if (endDate == null) { 7164 if (dateOrObj.start != null) { 7165 selectionInput = dateOrObj; 7166 } 7167 else { 7168 selectionInput = { 7169 start: dateOrObj, 7170 end: null 7171 }; 7172 } 7173 } 7174 else { 7175 selectionInput = { 7176 start: dateOrObj, 7177 end: endDate 7178 }; 7179 } 7180 var selection = parseDateSpan(selectionInput, this.dateEnv, createDuration({ days: 1 }) // TODO: cache this? 7181 ); 7182 if (selection) { // throw parse error otherwise? 7183 this.dispatch({ type: 'SELECT_DATES', selection: selection }); 7184 this.triggerDateSelect(selection); 7185 } 7186 }; 7187 // public method 7188 Calendar.prototype.unselect = function (pev) { 7189 if (this.state.dateSelection) { 7190 this.dispatch({ type: 'UNSELECT_DATES' }); 7191 this.triggerDateUnselect(pev); 7192 } 7193 }; 7194 Calendar.prototype.triggerDateSelect = function (selection, pev) { 7195 var arg = __assign({}, this.buildDateSpanApi(selection), { jsEvent: pev ? pev.origEvent : null, view: this.view }); 7196 this.publiclyTrigger('select', [arg]); 7197 }; 7198 Calendar.prototype.triggerDateUnselect = function (pev) { 7199 this.publiclyTrigger('unselect', [ 7200 { 7201 jsEvent: pev ? pev.origEvent : null, 7202 view: this.view 7203 } 7204 ]); 7205 }; 7206 // TODO: receive pev? 7207 Calendar.prototype.triggerDateClick = function (dateSpan, dayEl, view, ev) { 7208 var arg = __assign({}, this.buildDatePointApi(dateSpan), { dayEl: dayEl, jsEvent: ev, // Is this always a mouse event? See #4655 7209 view: view }); 7210 this.publiclyTrigger('dateClick', [arg]); 7211 }; 7212 Calendar.prototype.buildDatePointApi = function (dateSpan) { 7213 var props = {}; 7214 for (var _i = 0, _a = this.pluginSystem.hooks.datePointTransforms; _i < _a.length; _i++) { 7215 var transform = _a[_i]; 7216 __assign(props, transform(dateSpan, this)); 7217 } 7218 __assign(props, buildDatePointApi(dateSpan, this.dateEnv)); 7219 return props; 7220 }; 7221 Calendar.prototype.buildDateSpanApi = function (dateSpan) { 7222 var props = {}; 7223 for (var _i = 0, _a = this.pluginSystem.hooks.dateSpanTransforms; _i < _a.length; _i++) { 7224 var transform = _a[_i]; 7225 __assign(props, transform(dateSpan, this)); 7226 } 7227 __assign(props, buildDateSpanApi(dateSpan, this.dateEnv)); 7228 return props; 7229 }; 7230 // Date Utils 7231 // ----------------------------------------------------------------------------------------------------------------- 7232 // Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option 7233 Calendar.prototype.getNow = function () { 7234 var now = this.opt('now'); 7235 if (typeof now === 'function') { 7236 now = now(); 7237 } 7238 if (now == null) { 7239 return this.dateEnv.createNowMarker(); 7240 } 7241 return this.dateEnv.createMarker(now); 7242 }; 7243 // Event-Date Utilities 7244 // ----------------------------------------------------------------------------------------------------------------- 7245 // Given an event's allDay status and start date, return what its fallback end date should be. 7246 // TODO: rename to computeDefaultEventEnd 7247 Calendar.prototype.getDefaultEventEnd = function (allDay, marker) { 7248 var end = marker; 7249 if (allDay) { 7250 end = startOfDay(end); 7251 end = this.dateEnv.add(end, this.defaultAllDayEventDuration); 7252 } 7253 else { 7254 end = this.dateEnv.add(end, this.defaultTimedEventDuration); 7255 } 7256 return end; 7257 }; 7258 // Public Events API 7259 // ----------------------------------------------------------------------------------------------------------------- 7260 Calendar.prototype.addEvent = function (eventInput, sourceIn
7260put) { 7261 if (eventInput instanceof EventApi) { 7262 var def = eventInput._def; 7263 var instance = eventInput._instance; 7264 // not already present? don't want to add an old snapshot 7265 if (!this.state.eventStore.defs[def.defId]) { 7266 this.dispatch({ 7267 type: 'ADD_EVENTS', 7268 eventStore: eventTupleToStore({ def: def, instance: instance }) // TODO: better util for two args? 7269 }); 7270 } 7271 return eventInput; 7272 } 7273 var sourceId; 7274 if (sourceInput instanceof EventSourceApi) { 7275 sourceId = sourceInput.internalEventSource.sourceId; 7276 } 7277 else if (sourceInput != null) { 7278 var sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function 7279 if (!sourceApi) { 7280 console.warn('Could not find an event source with ID "' + sourceInput + '"'); // TODO: test 7281 return null; 7282 } 7283 else { 7284 sourceId = sourceApi.internalEventSource.sourceId; 7285 } 7286 } 7287 var tuple = parseEvent(eventInput, sourceId, this); 7288 if (tuple) { 7289 this.dispatch({ 7290 type: 'ADD_EVENTS', 7291 eventStore: eventTupleToStore(tuple) 7292 }); 7293 return new EventApi(this, tuple.def, tuple.def.recurringDef ? null : tuple.instance); 7294 } 7295 return null; 7296 }; 7297 // TODO: optimize 7298 Calendar.prototype.getEventById = function (id) { 7299 var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; 7300 id = String(id); 7301 for (var defId in defs) { 7302 var def = defs[defId]; 7303 if (def.publicId === id) { 7304 if (def.recurringDef) { 7305 return new EventApi(this, def, null); 7306 } 7307 else { 7308 for (var instanceId in instances) { 7309 var instance = instances[instanceId]; 7310 if (instance.defId === def.defId) { 7311 return new EventApi(this, def, instance); 7312 } 7313 } 7314 } 7315 } 7316 } 7317 return null; 7318 }; 7319 Calendar.prototype.getEvents = function () { 7320 var _a = this.state.eventStore, defs = _a.defs, instances = _a.instances; 7321 var eventApis = []; 7322 for (var id in instances) { 7323 var instance = instances[id]; 7324 var def = defs[instance.defId]; 7325 eventApis.push(new EventApi(this, def, instance)); 7326 } 7327 return eventApis; 7328 }; 7329 Calendar.prototype.removeAllEvents = function () { 7330 this.dispatch({ type: 'REMOVE_ALL_EVENTS' }); 7331 }; 7332 Calendar.prototype.rerenderEvents = function () { 7333 this.dispatch({ type: 'RESET_EVENTS' }); 7334 }; 7335 // Public Event Sources API 7336 // ----------------------------------------------------------------------------------------------------------------- 7337 Calendar.prototype.getEventSources = function () { 7338 var sourceHash = this.state.eventSources; 7339 var sourceApis = []; 7340 for (var internalId in sourceHash) { 7341 sourceApis.push(new EventSourceApi(this, sourceHash[internalId])); 7342 } 7343 return sourceApis; 7344 }; 7345 Calendar.prototype.getEventSourceById = function (id) { 7346 var sourceHash = this.state.eventSources; 7347 id = String(id); 7348 for (var sourceId in sourceHash) { 7349 if (sourceHash[sourceId].publicId === id) { 7350 return new EventSourceApi(this, sourceHash[sourceId]); 7351 } 7352 } 7353 return null; 7354 }; 7355 Calendar.prototype.addEventSource = function (sourceInput) { 7356 if (sourceInput instanceof EventSourceApi) { 7357 // not already present? don't want to add an old snapshot
7358 if (!this.state.eventSources[sourceInput.internalEventSource.sourceId]) { 7359 this.dispatch({ 7360 type: 'ADD_EVENT_SOURCES', 7361 sources: [sourceInput.internalEventSource] 7362 }); 7363 } 7364 return sourceInput; 7365 } 7366 var eventSource = parseEventSource(sourceInput, this); 7367 if (eventSource) { // TODO: error otherwise? 7368 this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] }); 7369 return new EventSourceApi(this, eventSource); 7370 } 7371 return null; 7372 }; 7373 Calendar.prototype.removeAllEventSources = function () { 7374 this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' }); 7375 }; 7376 Calendar.prototype.refetchEvents = function () { 7377 this.dispatch({ type: 'FETCH_EVENT_SOURCES' }); 7378 }; 7379 // Scroll 7380 // ----------------------------------------------------------------------------------------------------------------- 7381 Calendar.prototype.scrollToTime = function (timeInput) { 7382 var time = createDuration(timeInput); 7383 if (time) { 7384 this.component.view.scrollToTime(time); 7385 } 7386 }; 7387 return Calendar; 7388 }()); 7389 EmitterMixin.mixInto(Calendar); 7390 // for memoizers 7391 // ----------------------------------------------------------------------------------------------------------------- 7392 function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) { 7393 return new DateEnv({ 7394 calendarSystem: 'gregory', 7395 timeZone: timeZone, 7396 namedTimeZoneImpl: namedTimeZoneImpl, 7397 locale: locale, 7398 weekNumberCalculation: weekNumberCalculation, 7399 firstDay: firstDay, 7400 weekLabel: weekLabel, 7401 cmdFormatter: cmdFormatter 7402 }); 7403 } 7404 function buildTheme(calendarOptions) { 7405 var themeClass = this.pluginSystem.hooks.themeClasses[calendarOptions.themeSystem] || StandardTheme; 7406 return new themeClass(calendarOptions); 7407 } 7408 function buildDelayedRerender(wait) { 7409 var func = this.tryRerender.bind(this); 7410 if (wait != null) { 7411 func = debounce(func, wait); 7412 } 7413 return func; 7414 } 7415 function buildEventUiBySource(eventSources) { 7416 return mapHash(eventSources, function (eventSource) { 7417 return eventSource.ui; 7418 }); 7419 } 7420 function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) { 7421 var eventUiBases = { '': eventUiSingleBase }; 7422 for (var defId in eventDefs) { 7423 var def = eventDefs[defId]; 7424 if (def.sourceId && eventUiBySource[def.sourceId]) { 7425 eventUiBases[defId] = eventUiBySource[def.sourceId]; 7426 } 7427 } 7428 return eventUiBases; 7429 } 7430 7431 var View = /** @class */ (function (_super) { 7432 __extends(View, _super); 7433 function View(context, viewSpec, dateProfileGenerator, parentEl) { 7434 var _this = _super.call(this, context, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' }), true // isView (HACK) 7435 ) || this; 7436 _this.renderDatesMem = memoizeRendering(_this.renderDatesWrap, _this.unrenderDatesWrap); 7437 _this.renderBusinessHoursMem = memoizeRendering(_this.renderBusinessHours, _this.unrenderBusinessHours, [_this.renderDatesMem]); 7438 _this.renderDateSelectionMem = memoizeRendering(_this.renderDateSelectionWrap, _this.unrenderDateSelectionWrap, [_this.renderDatesMem]); 7439 _this.renderEventsMem = memoizeRendering(_this.renderEvents, _this.unrenderEvents, [_this.renderDatesMem]); 7440 _this.renderEventSelectionMem = memoizeRendering(_this.renderEventSelectionWrap, _this.unrenderEventSelectionWrap, [_this.renderEventsMem]); 7441 _this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]); 7442 _this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]); 7443 _this.viewSpec = viewSpec; 7444 _this.dateProfileGenerator = dateProfileGenerator; 7445 _this.type = viewSpec.type; 7446 _this.eventOrderSpecs = parseFieldSpecs(_this.opt('eventOrder')); 7447 _this.nextDayThreshold = createDuration(_this.opt('nextDayThreshold')); 7448 parentEl.appendChild(_this.el); 7449 _this.initialize(); 7450 return _this; 7451 } 7452 View.prototype.initialize = function () { 7453 }; 7454 Object.defineProperty(View.prototype, "activeStart", { 7455 // Date Setting/Unsetting 7456 // ----------------------------------------------------------------------------------------------------------------- 7457 get: function () { 7458 return this.dateEnv.toDate(this.props.dateProfile.activeRange.start); 7459 }, 7460 enumerable: true, 7461 configurable: true 7462 }); 7463 Object.defineProperty(View.prototype, "activeEnd", { 7464 get: function () { 7465 return this.dateEnv.toDate(this.props.dateProfile.activeRange.end); 7466 }, 7467 enumerable: true, 7468 configurable: true 7469 }); 7470 Object.defineProperty(View.prototype, "currentStart", { 7471 get: function () { 7472 return this.dateEnv.toDate(this.props.dateProfile.currentRange.start); 7473 }, 7474 enumerable: true, 7475 configurable: true 7476 }); 7477 Object.defineProperty(View.prototype, "currentEnd", { 7478 get: function () { 7479 return this.dateEnv.toDate(this.props.dateProfile.currentRange.end); 7480 }, 7481 enumerable: true, 7482 configurable: true 7483 }); 7484 // General Rendering 7485 // ----------------------------------------------------------------------------------------------------------------- 7486 View.prototype.render = function (props) { 7487 this.renderDatesMem(props.dateProfile); 7488 this.renderBusinessHoursMem(props.businessHours); 7489 this.renderDateSelectionMem(props.dateSelection); 7490 this.renderEventsMem(props.eventStore); 7491 this.renderEventSelectionMem(props.eventSelection); 7492 this.renderEventDragMem(props.eventDrag); 7493 this.renderEventResizeMem(props.eventResize); 7494 }; 7495 View.prototype.destroy = function () { 7496 _super.prototype.destroy.call(this); 7497 this.renderDatesMem.unrender(); // should unrender everything else 7498 }; 7499 // Sizing 7500 // ----------------------------------------------------------------------------------------------------------------- 7501 View.prototype.updateSize = function (isResize, viewHeight, isAuto) { 7502 var calendar = this.calendar; 7503 if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) {
7504 // sort of the catch-all sizing 7505 // anything that might cause dimension changes 7506 this.updateBaseSize(isResize, viewHeight, isAuto); 7507 } 7508 }; 7509 View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) { 7510 }; 7511 // Date Rendering 7512 // ----------------------------------------------------------------------------------------------------------------- 7513 View.prototype.renderDatesWrap = function (dateProfile) { 7514 this.renderDates(dateProfile); 7515 this.addScroll({ 7516 timeMs: createDuration(this.opt('scrollTime')).milliseconds 7517 }); 7518 this.startNowIndicator(dateProfile); // shouldn't render yet because updateSize will be called soon 7519 }; 7520 View.prototype.unrenderDatesWrap = function () { 7521 this.stopNowIndicator(); 7522 this.unrenderDates(); 7523 }; 7524 View.prototype.renderDates = function (dateProfile) { }; 7525 View.prototype.unrenderDates = function () { }; 7526 // Business Hours 7527 // ----------------------------------------------------------------------------------------------------------------- 7528 View.prototype.renderBusinessHours = function (businessHours) { }; 7529 View.prototype.unrenderBusinessHours = function () { }; 7530 // Date Selection 7531 // ----------------------------------------------------------------------------------------------------------------- 7532 View.prototype.renderDateSelectionWrap = function (selection) { 7533 if (selection) { 7534 this.renderDateSelection(selection); 7535 } 7536 }; 7537 View.prototype.unrenderDateSelectionWrap = function (selection) { 7538 if (selection) { 7539 this.unrenderDateSelection(selection); 7540 } 7541 }; 7542 View.prototype.renderDateSelection = function (selection) { }; 7543 View.prototype.unrenderDateSelection = function (selection) { }; 7544 // Event Rendering 7545 // ----------------------------------------------------------------------------------------------------------------- 7546 View.prototype.renderEvents = function (eventStore) { }; 7547 View.prototype.unrenderEvents = function () { }; 7548 // util for subclasses 7549 View.prototype.sliceEvents = function (eventStore, allDay) { 7550 var props = this.props; 7551 return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.nextDayThreshold : null).fg; 7552 }; 7553 // Event Selection 7554 // ----------------------------------------------------------------------------------------------------------------- 7555 View.prototype.renderEventSelectionWrap = function (instanceId) { 7556 if (instanceId) { 7557 this.renderEventSelection(instanceId); 7558 } 7559 }; 7560 View.prototype.unrenderEventSelectionWrap = function (instanceId) { 7561 if (instanceId) { 7562 this.unrenderEventSelection(instanceId); 7563 } 7564 }; 7565 View.prototype.renderEventSelection = function (instanceId) { }; 7566 View.prototype.unrenderEventSelection = function (instanceId) { }; 7567 // Event Drag 7568 // ----------------------------------------------------------------------------------------------------------------- 7569 View.prototype.renderEventDragWrap = function (state) { 7570 if (state) { 7571 this.renderEventDrag(state); 7572 } 7573 }; 7574 View.prototype.unrenderEventDragWrap = function (state) { 7575 if (state) { 7576 this.unrenderEventDrag(state); 7577 } 7578 }; 7579 View.prototype.renderEventDrag = function (state) { }; 7580 View.prototype.unrenderEventDrag = function (state) { }; 7581 // Event Resize 7582 // ----------------------------------------------------------------------------------------------------------------- 7583 View.prototype.renderEventResizeWrap = function (state) { 7584 if (state) { 7585 this.renderEventResize(state); 7586 } 7587 }; 7588 View.prototype.unrenderEventResizeWrap = function (state) { 7589 if (state) { 7590 this.unrenderEventResize(state); 7591 } 7592 }; 7593 View.prototype.renderEventResize = function (state) { }; 7594 View.prototype.unrenderEventResize = function (state) { }; 7595 /* Now Indicator 7596 ------------------------------------------------------------------------------------------------------------------*/ 7597 // Immediately render the current time indicator and begins re-rendering it at an interval, 7598 // which is defined by this.getNowIndicatorUnit(). 7599 // TODO: somehow do this for the current whole day's background too 7600 View.prototype.startNowIndicator = function (dateProfile) { 7601 var _this = this; 7602 var dateEnv = this.dateEnv; 7603 var unit; 7604 var update; 7605 var delay; // ms wait value 7606 if (this.opt('nowIndicator')) { 7607 unit = this.getNowIndicatorUnit(dateProfile); 7608 if (unit) { 7609 update = this.updateNowIndicator.bind(this); 7610 this.initialNowDate = this.calendar.getNow(); 7611 this.initialNowQueriedMs = new Date().valueOf(); 7612 // wait until the beginning of the next interval
7613 delay = dateEnv.add(dateEnv.startOf(this.initialNowDate, unit), createDuration(1, unit)).valueOf() - this.initialNowDate.valueOf(); 7614 // TODO: maybe always use setTimeout, waiting until start of next unit 7615 this.nowIndicatorTimeoutID = setTimeout(function () { 7616 _this.nowIndicatorTimeoutID = null; 7617 update(); 7618 if (unit === 'second') { 7619 delay = 1000; // every second 7620 } 7621 else { 7622 delay = 1000 * 60; // otherwise, every minute 7623 } 7624 _this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval 7625 }, delay); 7626 } 7627 // rendering will be initiated in updateSize 7628 } 7629 }; 7630 // rerenders the now indicator, computing the new current time from the amount of time that has passed 7631 // since the initial getNow call. 7632 View.prototype.updateNowIndicator = function () { 7633 if (this.props.dateProfile && // a way to determine if dates were rendered yet 7634 this.initialNowDate // activated before? 7635 ) { 7636 this.unrenderNowIndicator(); // won't unrender if unnecessary 7637 this.renderNowIndicator(addMs(this.initialNowDate, new Date().valueOf() - this.initialNowQueriedMs)); 7638 this.isNowIndicatorRendered = true; 7639 } 7640 }; 7641 // Immediately unrenders the view's current time indicator and stops any re-rendering timers. 7642 // Won't cause side effects if indicator isn't rendered. 7643 View.prototype.stopNowIndicator = function () { 7644 if (this.isNowIndicatorRendered) { 7645 if (this.nowIndicatorTimeoutID) { 7646 clearTimeout(this.nowIndicatorTimeoutID); 7647 this.nowIndicatorTimeoutID = null; 7648 } 7649 if (this.nowIndicatorIntervalID) { 7650 clearInterval(this.nowIndicatorIntervalID); 7651 this.nowIndicatorIntervalID = null; 7652 } 7653 this.unrenderNowIndicator(); 7654 this.isNowIndicatorRendered = false; 7655 } 7656 }; 7657 View.prototype.getNowIndicatorUnit = function (dateProfile) { 7658 // subclasses should implement 7659 }; 7660 // Renders a current time indicator at the given datetime 7661 View.prototype.renderNowIndicator = function (date) { 7662 // SUBCLASSES MUST PASS TO CHILDREN! 7663 }; 7664 // Undoes the rendering actions from renderNowIndicator 7665 View.prototype.unrenderNowIndicator = function () { 7666 // SUBCLASSES MUST PASS TO CHILDREN! 7667 }; 7668 /* Scroller 7669 ------------------------------------------------------------------------------------------------------------------*/ 7670 View.prototype.addScroll = function (scroll) { 7671 var queuedScroll = this.queuedScroll || (this.queuedScroll = {}); 7672 __assign(queuedScroll, scroll); 7673 }; 7674 View.prototype.popScroll = function (isResize) { 7675 this.applyQueuedScroll(isResize); 7676 this.queuedScroll = null; 7677 }; 7678 View.prototype.applyQueuedScroll = function (isResize) { 7679 this.applyScroll(this.queuedScroll || {}, isResize); 7680 }; 7681 View.prototype.queryScroll = function () { 7682 var scroll = {}; 7683 if (this.props.dateProfile) { // dates rendered yet? 7684 __assign(scroll, this.queryDateScroll()); 7685 } 7686 return scroll; 7687 }; 7688 View.prototype.applyScroll = function (scroll, isResize) { 7689 var timeMs = scroll.timeMs; 7690 if (timeMs != null) { 7691 delete scroll.timeMs; 7692 if (this.props.dateProfile) { // dates rendered yet? 7693 __assign(scroll, this.computeDateScroll(timeMs)); 7694 } 7695 } 7696 if (this.props.dateProfile) { // dates rendered yet? 7697 this.applyDateScroll(scroll); 7698 } 7699 }; 7700 View.prototype.computeDateScroll = function (timeMs) { 7701 return {}; // subclasses must implement 7702 }; 7703 View.prototype.queryDateScroll = function () { 7704 return {}; // subclasses must implement 7705 }; 7706 View.prototype.applyDateScroll = function (scroll) { 7707 // subclasses must implement 7708 }; 7709 // for API 7710 View.prototype.scrollToTime = function (time) { 7711 this.applyScroll({ 7712 timeMs: time.milliseconds 7713 }, false); 7714 }; 7715 return View; 7716 }(DateComponent)); 7717 EmitterMixin.mixInto(View); 7718 View.prototype.usesMinMaxTime = false;
7719 View.prototype.dateProfileGeneratorClass = DateProfileGenerator; 7720 7721 var FgEventRenderer = /** @class */ (function () { 7722 function FgEventRenderer(context) { 7723 this.segs = []; 7724 this.isSizeDirty = false; 7725 this.context = context; 7726 } 7727 FgEventRenderer.prototype.renderSegs = function (segs, mirrorInfo) { 7728 this.rangeUpdated(); // called too frequently :( 7729 // render an `.el` on each seg 7730 // returns a subset of the segs. segs that were actually rendered 7731 segs = this.renderSegEls(segs, mirrorInfo); 7732 this.segs = segs; 7733 this.attachSegs(segs, mirrorInfo); 7734 this.isSizeDirty = true; 7735 this.context.view.triggerRenderedSegs(this.segs, Boolean(mirrorInfo)); 7736 }; 7737 FgEventRenderer.prototype.unrender = function (_segs, mirrorInfo) { 7738 this.context.view.triggerWillRemoveSegs(this.segs, Boolean(mirrorInfo)); 7739 this.detachSegs(this.segs); 7740 this.segs = []; 7741 }; 7742 // Updates values that rely on options and also relate to range 7743 FgEventRenderer.prototype.rangeUpdated = function () { 7744 var options = this.context.options; 7745 var displayEventTime; 7746 var displayEventEnd; 7747 this.eventTimeFormat = createFormatter(options.eventTimeFormat || this.computeEventTimeFormat(), options.defaultRangeSeparator); 7748 displayEventTime = options.displayEventTime; 7749 if (displayEventTime == null) { 7750 displayEventTime = this.computeDisplayEventTime(); // might be based off of range 7751 } 7752 displayEventEnd = options.displayEventEnd; 7753 if (displayEventEnd == null) { 7754 displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range 7755 } 7756 this.displayEventTime = displayEventTime; 7757 this.displayEventEnd = displayEventEnd; 7758 }; 7759 // Renders and assigns an `el` property for each foreground event segment. 7760 // Only returns segments that successfully rendered. 7761 FgEventRenderer.prototype.renderSegEls = function (segs, mirrorInfo) { 7762 var html = ''; 7763 var i; 7764 if (segs.length) { // don't build an empty html string 7765 // build a large concatenation of event segment HTML 7766 for (i = 0; i < segs.length; i++) { 7767 html += this.renderSegHtml(segs[i], mirrorInfo); 7768 } 7769 // Grab individual elements from the combined HTML string. Use each as the default rendering. 7770 // Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false. 7771 htmlToElements(html).forEach(function (el, i) { 7772 var seg = segs[i]; 7773 if (el) { 7774 seg.el = el; 7775 } 7776 }); 7777 segs = filterSegsViaEls(this.context.view, segs, Boolean(mirrorInfo)); 7778 } 7779 return segs; 7780 }; 7781 // Generic utility for generating the HTML classNames for an event segment's element 7782 FgEventRenderer.prototype.getSegClasses = function (seg, isDraggable, isResizable, mirrorInfo) { 7783 var classes = [ 7784 'fc-event', 7785 seg.isStart ? 'fc-start' : 'fc-not-start', 7786 seg.isEnd ? 'fc-end' : 'fc-not-end' 7787 ].concat(seg.eventRange.ui.classNames); 7788 if (isDraggable) { 7789 classes.push('fc-draggable'); 7790 } 7791 if (isResizable) { 7792 classes.push('fc-resizable'); 7793 } 7794 if (mirrorInfo) { 7795 classes.push('fc-mirror'); 7796 if (mirrorInfo.isDragging) { 7797 classes.push('fc-dragging'); 7798 } 7799 if (mirrorInfo.isResizing) { 7800 classes.push('fc-resizing'); 7801 } 7802 } 7803 return classes; 7804 }; 7805 // Compute the text that should be displayed on an event's element. 7806 // `range` can be the Event object itself, or something range-like, with at least a `start`. 7807 // If event times are disabled, or the event has no time, will return a blank string. 7808 // If not specified, formatter will default to the eventTimeFormat setting, 7809 // and displayEnd will default to the displayEventEnd setting. 7810 FgEventRenderer.prototype.getTimeText = function (eventRange, formatter, displayEnd) { 7811 var def = eventRange.def, instance = eventRange.instance; 7812 return this._getTimeText(instance.range.start, def.hasEnd ? instance.range.end : null, def.allDay, formatter, displayEnd, instance.forcedStartTzo, instance.forcedEndTzo); 7813 }; 7814 FgEventRenderer.prototype._getTimeText = function (start, end, allDay, formatter, displayEnd, forcedStartTzo, forcedEndTzo) { 7815 var dateEnv = this.context.dateEnv; 7816 if (formatter == null) { 7817 formatter = this.eventTimeFormat; 7818 } 7819 if (displayEnd == null) { 7820 displayEnd = this.displayEventEnd; 7821 } 7822 if (this.displayEventTime && !allDay) { 7823 if (displayEnd && end) { 7824 return dateEnv.formatRange(start, end, formatter, { 7825 forcedStartTzo: forcedStartTzo, 7826 forcedEndTzo: forcedEndTzo 7827 }); 7828 } 7829 else { 7830 return dateEnv.format(start, formatter, { 7831 forcedTzo: forcedStartTzo 7832 }); 7833 } 7834 } 7835 return ''; 7836 }; 7837 FgEventRenderer.prototype.computeEventTimeFormat = function () { 7838 return { 7839 hour: 'numeric', 7840 minute: '2-digit', 7841 omitZeroMinute: true 7842 }; 7843 }; 7844 FgEventRenderer.prototype.computeDisplayEventTime = function () { 7845 return true; 7846 }; 7847 FgEventRenderer.prototype.computeDisplayEventEnd = function () { 7848 return true; 7849 }; 7850 // Utility for generating event skin-related CSS properties 7851 FgEventRenderer.prototype.getSkinCss = function (ui) { 7852 return { 7853 'background-color': ui.backgroundColor, 7854 'border-color': ui.borderColor, 7855 color: ui.textColor 7856 }; 7857 }; 7858 FgEventRenderer.prototype.sortEventSegs = function (segs) { 7859 var specs = this.context.view.eventOrderSpecs; 7860 var objs = segs.map(buildSegCompareObj); 7861 objs.sort(function (obj0, obj1) { 7862 return compareByFieldSpecs(obj0, obj1, specs); 7863 }); 7864 return objs.map(function (c) { 7865 return c._seg; 7866 }); 7867 }; 7868 FgEventRenderer.prototype.computeSizes = function (force) { 7869 if (force || this.isSizeDirty) { 7870 this.computeSegSizes(this.segs); 7871 } 7872 }; 7873 FgEventRenderer.prototype.assignSizes = function (force) { 7874 if (force || this.isSizeDirty) { 7875 this.assignSegSizes(this.segs); 7876 this.isSizeDirty = false;
7877 } 7878 }; 7879 FgEventRenderer.prototype.computeSegSizes = function (segs) { 7880 }; 7881 FgEventRenderer.prototype.assignSegSizes = function (segs) { 7882 }; 7883 // Manipulation on rendered segs 7884 FgEventRenderer.prototype.hideByHash = function (hash) { 7885 if (hash) { 7886 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 7887 var seg = _a[_i]; 7888 if (hash[seg.eventRange.instance.instanceId]) { 7889 seg.el.style.visibility = 'hidden'; 7890 } 7891 } 7892 } 7893 }; 7894 FgEventRenderer.prototype.showByHash = function (hash) { 7895 if (hash) { 7896 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 7897 var seg = _a[_i]; 7898 if (hash[seg.eventRange.instance.instanceId]) { 7899 seg.el.style.visibility = ''; 7900 } 7901 } 7902 } 7903 }; 7904 FgEventRenderer.prototype.selectByInstanceId = function (instanceId) { 7905 if (instanceId) { 7906 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 7907 var seg = _a[_i]; 7908 var eventInstance = seg.eventRange.instance; 7909 if (eventInstance && eventInstance.instanceId === instanceId && 7910 seg.el // necessary? 7911 ) { 7912 seg.el.classList.add('fc-selected'); 7913 } 7914 } 7915 } 7916 }; 7917 FgEventRenderer.prototype.unselectByInstanceId = function (instanceId) { 7918 if (instanceId) { 7919 for (var _i = 0, _a = this.segs; _i < _a.length; _i++) { 7920 var seg = _a[_i]; 7921 if (seg.el) { // necessary? 7922 seg.el.classList.remove('fc-selected'); 7923 } 7924 } 7925 } 7926 }; 7927 return FgEventRenderer; 7928 }()); 7929 // returns a object with all primitive props that can be compared 7930 function buildSegCompareObj(seg) { 7931 var eventDef = seg.eventRange.def; 7932 var range = seg.eventRange.instance.range; 7933 var start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events 7934 var end = range.end ? range.end.valueOf() : 0; // " 7935 return __assign({}, eventDef.extendedProps, eventDef, { id: eventDef.publicId, start: start, 7936 end: end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg // for later retrieval 7937 }); 7938 } 7939 7940 var FillRenderer = /** @class */ (function () { 7941 function FillRenderer(context) { 7942 this.fillSegTag = 'div'; 7943 this.dirtySizeFlags = {}; 7944 this.context = context; 7945 this.containerElsByType = {}; 7946 this.segsByType = {}; 7947 } 7948 FillRenderer.prototype.getSegsByType = function (type) { 7949 return this.segsByType[type] || []; 7950 }; 7951 FillRenderer.prototype.renderSegs = function (type, segs) { 7952 var _a; 7953 var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs 7954 var containerEls = this.attachSegs(type, renderedSegs); 7955 if (containerEls) { 7956 (_a = (this.containerElsByType[type] || (this.containerElsByType[type] = []))).push.apply(_a, containerEls); 7957 } 7958 this.segsByType[type] = renderedSegs; 7959 if (type === 'bgEvent') { 7960 this.context.view.triggerRenderedSegs(renderedSegs, false); // isMirror=false 7961 } 7962 this.dirtySizeFlags[type] = true; 7963 }; 7964 // Unrenders a specific type of fill that is currently rendered on the grid 7965 FillRenderer.prototype.unrender = function (type) { 7966 var segs = this.segsByType[type]; 7967 if (segs) { 7968 if (type === 'bgEvent') { 7969 this.context.view.triggerWillRemoveSegs(segs, false); // isMirror=false 7970 } 7971 this.detachSegs(type, segs); 7972 } 7973 }; 7974 // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types. 7975 // Only returns segments that successfully rendered.
7976 FillRenderer.prototype.renderSegEls = function (type, segs) { 7977 var _this = this; 7978 var html = ''; 7979 var i; 7980 if (segs.length) { 7981 // build a large concatenation of segment HTML 7982 for (i = 0; i < segs.length; i++) { 7983 html += this.renderSegHtml(type, segs[i]); 7984 } 7985 // Grab individual elements from the combined HTML string. Use each as the default rendering. 7986 // Then, compute the 'el' for each segment. 7987 htmlToElements(html).forEach(function (el, i) { 7988 var seg = segs[i]; 7989 if (el) { 7990 seg.el = el; 7991 } 7992 }); 7993 if (type === 'bgEvent') { 7994 segs = filterSegsViaEls(this.context.view, segs, false // isMirror. background events can never be mirror elements 7995 ); 7996 } 7997 // correct element type? (would be bad if a non-TD were inserted into a table for example) 7998 segs = segs.filter(function (seg) { 7999 return elementMatches(seg.el, _this.fillSegTag); 8000 }); 8001 } 8002 return segs; 8003 }; 8004 // Builds the HTML needed for one fill segment. Generic enough to work with different types. 8005 FillRenderer.prototype.renderSegHtml = function (type, seg) { 8006 var css = null; 8007 var classNames = []; 8008 if (type !== 'highlight' && type !== 'businessHours') { 8009 css = { 8010 'background-color': seg.eventRange.ui.backgroundColor 8011 }; 8012 } 8013 if (type !== 'highlight') { 8014 classNames = classNames.concat(seg.eventRange.ui.classNames); 8015 } 8016 if (type === 'businessHours') { 8017 classNames.push('fc-bgevent'); 8018 } 8019 else { 8020 classNames.push('fc-' + type.toLowerCase()); 8021 } 8022 return '<' + this.fillSegTag + 8023 (classNames.length ? ' class="' + classNames.join(' ') + '"' : '') + 8024 (css ? ' style="' + cssToStr(css) + '"' : '') + 8025 '></' + this.fillSegTag + '>'; 8026 }; 8027 FillRenderer.prototype.detachSegs = function (type, segs) { 8028 var containerEls = this.containerElsByType[type]; 8029 if (containerEls) { 8030 containerEls.forEach(removeElement); 8031 delete this.containerElsByType[type]; 8032 } 8033 }; 8034 FillRenderer.prototype.computeSizes = function (force) { 8035 for (var type in this.segsByType) { 8036 if (force || this.dirtySizeFlags[type]) { 8037 this.computeSegSizes(this.segsByType[type]); 8038 } 8039 } 8040 }; 8041 FillRenderer.prototype.assignSizes = function (force) { 8042 for (var type in this.segsByType) { 8043 if (force || this.dirtySizeFlags[type]) { 8044 this.assignSegSizes(this.segsByType[type]); 8045 } 8046 } 8047 this.dirtySizeFlags = {}; 8048 }; 8049 FillRenderer.prototype.computeSegSizes = function (segs) { 8050 }; 8051 FillRenderer.prototype.assignSegSizes = function (segs) { 8052 }; 8053 return FillRenderer; 8054 }()); 8055 8056 var NamedTimeZoneImpl = /** @class */ (function () { 8057 function NamedTimeZoneImpl(timeZoneName) { 8058 this.timeZoneName = timeZoneName; 8059 } 8060 return NamedTimeZoneImpl; 8061 }()); 8062 8063 /* 8064 An abstraction for a dragging interaction originating on an event. 8065 Does higher-level things than PointerDragger, such as possibly: 8066 - a "mirror" that moves with the pointer 8067 - a minimum number of pixels or other criteria for a true drag to begin 8068 8069 subclasses must emit: 8070 - pointerdown 8071 - dragstart 8072 - dragmove 8073 - pointerup 8074 - dragend 8075 */ 8076 var ElementDragging = /** @class */ (function () { 8077 function ElementDragging(el) { 8078 this.emitter = new EmitterMixin(); 8079 } 8080 ElementDragging.prototype.destroy = function () { 8081 }; 8082 ElementDragging.prototype.setMirrorIsVisible = function (bool) {
8083 // optional if subclass doesn't want to support a mirror 8084 }; 8085 ElementDragging.prototype.setMirrorNeedsRevert = function (bool) { 8086 // optional if subclass doesn't want to support a mirror 8087 }; 8088 ElementDragging.prototype.setAutoScrollEnabled = function (bool) { 8089 // optional 8090 }; 8091 return ElementDragging; 8092 }()); 8093 8094 function formatDate(dateInput, settings) { 8095 if (settings === void 0) { settings = {}; } 8096 var dateEnv = buildDateEnv$1(settings); 8097 var formatter = createFormatter(settings); 8098 var dateMeta = dateEnv.createMarkerMeta(dateInput); 8099 if (!dateMeta) { // TODO: warning? 8100 return ''; 8101 } 8102 return dateEnv.format(dateMeta.marker, formatter, { 8103 forcedTzo: dateMeta.forcedTzo 8104 }); 8105 } 8106 function formatRange(startInput, endInput, settings // mixture of env and formatter settings 8107 ) { 8108 var dateEnv = buildDateEnv$1(typeof settings === 'object' && settings ? settings : {}); // pass in if non-null object 8109 var formatter = createFormatter(settings, globalDefaults.defaultRangeSeparator); 8110 var startMeta = dateEnv.createMarkerMeta(startInput); 8111 var endMeta = dateEnv.createMarkerMeta(endInput); 8112 if (!startMeta || !endMeta) { // TODO: warning? 8113 return ''; 8114 } 8115 return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, { 8116 forcedStartTzo: startMeta.forcedTzo, 8117 forcedEndTzo: endMeta.forcedTzo, 8118 isEndExclusive: settings.isEndExclusive 8119 }); 8120 } 8121 // TODO: more DRY and optimized 8122 function buildDateEnv$1(settings) { 8123 var locale = buildLocale(settings.locale || 'en', parseRawLocales([]).map); // TODO: don't hardcode 'en' everywhere 8124 // ensure required settings 8125 settings = __assign({ timeZone: globalDefaults.timeZone, calendarSystem: 'gregory' }, settings, { locale: locale }); 8126 return new DateEnv(settings); 8127 } 8128 8129 var DRAG_META_PROPS = { 8130 startTime: createDuration, 8131 duration: createDuration, 8132 create: Boolean, 8133 sourceId: String 8134 }; 8135 var DRAG_META_DEFAULTS = { 8136 create: true 8137 }; 8138 function parseDragMeta(raw) { 8139 var leftoverProps = {}; 8140 var refined = refineProps(raw, DRAG_META_PROPS, DRAG_META_DEFAULTS, leftoverProps); 8141 refined.leftoverProps = leftoverProps; 8142 return refined; 8143 } 8144 8145 // Computes a default column header formatting string if `colFormat` is not explicitly defined 8146 function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) { 8147 // if more than one week row, or if there are a lot of columns with not much space, 8148 // put just the day numbers will be in each cell 8149 if (!datesRepDistinctDays || dayCnt > 10) { 8150 return { weekday: 'short' }; // "Sat" 8151 } 8152 else if (dayCnt > 1) { 8153 return { weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }; // "Sat 11/12" 8154 } 8155 else { 8156 return { weekday: 'long' }; // "Saturday" 8157 } 8158 } 8159 function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) { 8160 var view = context.view, dateEnv = context.dateEnv, theme = context.theme, options = context.options; 8161 var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow. 8162 var classNames = [ 8163 'fc-day-header', 8164 theme.getClass('widgetHeader') 8165 ]; 8166 var innerHtml; 8167 if (typeof options.columnHeaderHtml === 'function') { 8168 innerHtml = options.columnHeaderHtml(dateEnv.toDate(dateMarker)); 8169 } 8170 else if (typeof options.columnHeaderText === 'function') { 8171 innerHtml = htmlEscape(options.columnHeaderText(dateEnv.toDate(dateMarker))); 8172 } 8173 else { 8174 innerHtml = htmlEscape(dateEnv.format(dateMarker, colHeadFormat)); 8175 } 8176 // if only one row of days, the classNames on the header can represent the specific days beneath 8177 if (datesRepDistinctDays) {
8178 classNames = classNames.concat( 8179 // includes the day-of-week class 8180 // noThemeHighlight=true (don't highlight the header) 8181 getDayClasses(dateMarker, dateProfile, context, true)); 8182 } 8183 else { 8184 classNames.push('fc-' + DAY_IDS[dateMarker.getUTCDay()]); // only add the day-of-week class 8185 } 8186 return '' + 8187 '<th class="' + classNames.join(' ') + '"' + 8188 ((isDateValid && datesRepDistinctDays) ? 8189 ' data-date="' + dateEnv.formatIso(dateMarker, { omitTime: true }) + '"' : 8190 '') + 8191 (colspan > 1 ? 8192 ' colspan="' + colspan + '"' : 8193 '') + 8194 (otherAttrs ? 8195 ' ' + otherAttrs : 8196 '') + 8197 '>' + 8198 (isDateValid ? 8199 // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff) 8200 buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) : 8201 // if not valid, display text, but no link 8202 innerHtml) + 8203 '</th>'; 8204 } 8205 8206 var DayHeader = /** @class */ (function (_super) { 8207 __extends(DayHeader, _super); 8208 function DayHeader(context, parentEl) { 8209 var _this = _super.call(this, context) || this; 8210 parentEl.innerHTML = ''; // because might be nbsp 8211 parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' + 8212 '<table class="' + _this.theme.getClass('tableGrid') + '">' + 8213 '<thead></thead>' + 8214 '</table>' + 8215 '</div>')); 8216 _this.thead = _this.el.querySelector('thead'); 8217 return _this; 8218 } 8219 DayHeader.prototype.destroy = function () { 8220 removeElement(this.el); 8221 }; 8222 DayHeader.prototype.render = function (props) { 8223 var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays; 8224 var parts = []; 8225 if (props.renderIntroHtml) { 8226 parts.push(props.renderIntroHtml()); 8227 } 8228 var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') || 8229 computeFallbackHeaderFormat(datesRepDistinctDays, dates.length)); 8230 for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) { 8231 var date = dates_1[_i]; 8232 parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context)); 8233 } 8234 if (this.isRtl) { 8235 parts.reverse(); 8236 } 8237 this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>'; 8238 }; 8239 return DayHeader; 8240 }(Component)); 8241 8242 var DaySeries = /** @class */ (function () { 8243 function DaySeries(range, dateProfileGenerator) { 8244 var date = range.start; 8245 var end = range.end; 8246 var indices = []; 8247 var dates = []; 8248 var dayIndex = -1; 8249 while (date < end) { // loop each day from start to end 8250 if (dateProfileGenerator.isHiddenDay(date)) { 8251 indices.push(dayIndex + 0.5); // mark that it's between indices 8252 } 8253 else { 8254 dayIndex++; 8255 indices.push(dayIndex); 8256 dates.push(date); 8257 } 8258 date = addDays(date, 1); 8259 } 8260 this.dates = dates; 8261 this.indices = indices; 8262 this.cnt = dates.length; 8263 } 8264 DaySeries.prototype.sliceRange = function (range) { 8265 var firstIndex = this.getDateDayIndex(range.start); // inclusive first index 8266 var lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index 8267 var clippedFirstIndex = Math.max(0, firstIndex); 8268 var clippedLastIndex = Math.min(this.cnt - 1, lastIndex); 8269 // deal with in-between indices 8270 clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell 8271 clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell 8272 if (clippedFirstIndex <= clippedLastIndex) { 8273 return { 8274 firstIndex: clippedFirstIndex, 8275 lastIndex: clippedLastIndex, 8276 isStart: firstIndex === clippedFirstIndex, 8277 isEnd: lastIndex === clippedLastIndex 8278 }; 8279 } 8280 else { 8281 return null; 8282 } 8283 }; 8284 // Given a date, returns its chronolocial cell-index from the first cell of the grid. 8285 // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets. 8286 // If before the first offset, returns a negative number. 8287 // If after the last offset, returns an offset past the last cell offset. 8288 // Only works for *start* dates of cells. Will not work for exclusive end dates for cells. 8289 DaySeries.prototype.getDateDayIndex = function (date) { 8290 var indices = this.indices; 8291 var dayOffset = Math.floor(diffDays(this.dates[0], date)); 8292 if (dayOffset < 0) {
8293 return indices[0] - 1; 8294 } 8295 else if (dayOffset >= indices.length) { 8296 return indices[indices.length - 1] + 1; 8297 } 8298 else { 8299 return indices[dayOffset]; 8300 } 8301 }; 8302 return DaySeries; 8303 }()); 8304 8305 var DayTable = /** @class */ (function () { 8306 function DayTable(daySeries, breakOnWeeks) { 8307 var dates = daySeries.dates; 8308 var daysPerRow; 8309 var firstDay; 8310 var rowCnt; 8311 if (breakOnWeeks) { 8312 // count columns until the day-of-week repeats 8313 firstDay = dates[0].getUTCDay(); 8314 for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow++) { 8315 if (dates[daysPerRow].getUTCDay() === firstDay) { 8316 break; 8317 } 8318 } 8319 rowCnt = Math.ceil(dates.length / daysPerRow); 8320 } 8321 else { 8322 rowCnt = 1; 8323 daysPerRow = dates.length; 8324 } 8325 this.rowCnt = rowCnt; 8326 this.colCnt = daysPerRow; 8327 this.daySeries = daySeries; 8328 this.cells = this.buildCells(); 8329 this.headerDates = this.buildHeaderDates(); 8330 } 8331 DayTable.prototype.buildCells = function () { 8332 var rows = []; 8333 for (var row = 0; row < this.rowCnt; row++) { 8334 var cells = []; 8335 for (var col = 0; col < this.colCnt; col++) { 8336 cells.push(this.buildCell(row, col)); 8337 } 8338 rows.push(cells); 8339 } 8340 return rows; 8341 }; 8342 DayTable.prototype.buildCell = function (row, col) { 8343 return { 8344 date: this.daySeries.dates[row * this.colCnt + col] 8345 }; 8346 }; 8347 DayTable.prototype.buildHeaderDates = function () { 8348 var dates = []; 8349 for (var col = 0; col < this.colCnt; col++) { 8350 dates.push(this.cells[0][col].date); 8351 } 8352 return dates; 8353 }; 8354 DayTable.prototype.sliceRange = function (range) { 8355 var colCnt = this.colCnt; 8356 var seriesSeg = this.daySeries.sliceRange(range); 8357 var segs = []; 8358 if (seriesSeg) { 8359 var firstIndex = seriesSeg.firstIndex, lastIndex = seriesSeg.lastIndex; 8360 var index = firstIndex; 8361 while (index <= lastIndex) { 8362 var row = Math.floor(index / colCnt); 8363 var nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1); 8364 segs.push({ 8365 row: row, 8366 firstCol: index % colCnt, 8367 lastCol: (nextIndex - 1) % colCnt, 8368 isStart: seriesSeg.isStart && index === firstIndex, 8369 isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex 8370 }); 8371 index = nextIndex; 8372 } 8373 } 8374 return segs; 8375 }; 8376 return DayTable; 8377 }()); 8378 8379 var Slicer = /** @class */ (function () { 8380 function Slicer() { 8381 this.sliceBusinessHours = memoize(this._sliceBusinessHours); 8382 this.sliceDateSelection = memoize(this._sliceDateSpan); 8383 this.sliceEventStore = memoize(this._sliceEventStore); 8384 this.sliceEventDrag = memoize(this._sliceInteraction); 8385 this.sliceEventResize = memoize(this._sliceInteraction); 8386 } 8387 Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, component) { 8388 var extraArgs = []; 8389 for (var _i = 4; _i < arguments.length; _i++) { 8390 extraArgs[_i - 4] = arguments[_i]; 8391 } 8392 var eventUiBases = props.eventUiBases; 8393 var eventSegs = this.sliceEventStore.apply(this, [props.eventStore, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)); 8394 return { 8395 dateSelectionSegs: this.sliceDateSelection.apply(this, [props.dateSelection, eventUiBases, component].concat(extraArgs)), 8396 businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, component].concat(extraArgs)), 8397 fgEventSegs: eventSegs.fg, 8398 bgEventSegs: eventSegs.bg, 8399 eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), 8400 eventResize: this.sliceEventResize.apply(this, [props.eventResize, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)), 8401 eventSelection: props.eventSelection 8402 }; // TODO: give interactionSegs? 8403 }; 8404 Slicer.prototype.sliceNowDate = function (// does not memoize 8405 date, component) { 8406 var extraArgs = []; 8407 for (var _i = 2; _i < arguments.length; _i++) { 8408 extraArgs[_i - 2] = arguments[_i]; 8409 } 8410 return this._sliceDateSpan.apply(this, [{ range: { start: date, end: addMs(date, 1) }, allDay: false }, 8411 {}, 8412 component].concat(extraArgs)); 8413 }; 8414 Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, component) { 8415 var extraArgs = []; 8416 for (var _i = 4; _i < arguments.length; _i++) { 8417 extraArgs[_i - 4] = arguments[_i]; 8418 } 8419 if (!businessHours) { 8420 return []; 8421 } 8422 return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), component.calendar), 8423 {}, 8424 dateProfile, 8425 nextDayThreshold, 8426 component].concat(extraArgs)).bg; 8427 }; 8428 Slicer.prototype._sliceEventStore = function (eventStore, eventUiBases, dateProfile, nextDayThreshold, component) { 8429 var extraArgs = []; 8430 for (var _i = 5; _i < arguments.length; _i++) { 8431 extraArgs[_i - 5] = arguments[_i]; 8432 } 8433 if (eventStore) { 8434 var rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8435 return { 8436 bg: this.sliceEventRanges(rangeRes.bg, component, extraArgs), 8437 fg: this.sliceEventRanges(rangeRes.fg, component, extraArgs) 8438 }; 8439 } 8440 else { 8441 return { bg: [], fg: [] }; 8442 } 8443 }; 8444 Slicer.prototype._sliceInteraction = function (interaction, eventUiBases, dateProfile, nextDayThreshold, component) { 8445 var extraArgs = []; 8446 for (var _i = 5; _i < arguments.length; _i++) { 8447 extraArgs[_i - 5] = arguments[_i]; 8448 } 8449 if (!interaction) { 8450 return null; 8451 } 8452 var rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold); 8453 return { 8454 segs: this.sliceEventRanges(rangeRes.fg, component, extraArgs), 8455 affectedInstances: interaction.affectedEvents.instances, 8456 isEvent: interaction.isEvent, 8457 sourceSeg: interaction.origSeg 8458 }; 8459 }; 8460 Slicer.prototype._sliceDateSpan = function (dateSpan, eventUiBases, component) { 8461 var extraArgs = []; 8462 for (var _i = 3; _i < arguments.length; _i++) { 8463 extraArgs[_i - 3] = arguments[_i]; 8464 } 8465 if (!dateSpan) { 8466 return []; 8467 } 8468 var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.calendar); 8469 var segs = this.sliceRange.apply(this, [dateSpan.range].concat(extraArgs)); 8470 for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) { 8471 var seg = segs_1[_a]; 8472 seg.component = component; 8473 seg.eventRange = eventRange; 8474 } 8475 return segs; 8476 }; 8477 /* 8478 "complete" seg means it has component and eventRange 8479 */ 8480 Slicer.prototype.sliceEventRanges = function (eventRanges, component, // TODO: kill 8481 extraArgs) { 8482 var segs = []; 8483 for (var _i = 0, eventRanges_1 = eventRanges; _i < eventRanges_1.length; _i++) { 8484 var eventRange = eventRanges_1[_i]; 8485 segs.push.apply(segs, this.sliceEventRange(eventRange, component, extraArgs)); 8486 } 8487 return segs; 8488 }; 8489 /* 8490 "complete" seg means it has component and eventRange 8491 */ 8492 Slicer.prototype.sliceEventRange = function (eventRange, component, // TODO: kill 8493 extraArgs) { 8494 var segs = this.sliceRange.apply(this, [eventRange.range].concat(extraArgs)); 8495 for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) { 8496 var seg = segs_2[_i]; 8497 seg.component = component; 8498 seg.eventRange = eventRange; 8499 seg.isStart = eventRange.isStart && seg.isStart; 8500 seg.isEnd = eventRange.isEnd && seg.isEnd; 8501 } 8502 return segs; 8503 }; 8504 return Slicer; 8505 }()); 8506 /* 8507 for incorporating minTime/maxTime if appropriate 8508 TODO: should be part of DateProfile! 8509 TimelineDateProfile already does this btw 8510 */ 8511 function computeActiveRange(dateProfile, isComponentAllDay) { 8512 var range = dateProfile.activeRange; 8513 if (isComponentAllDay) { 8514 return range; 8515 } 8516 return { 8517 start: addMs(range.start, dateProfile.minTime.milliseconds), 8518 end: addMs(range.end, dateProfile.maxTime.milliseconds - 864e5) // 864e5 = ms in a day 8519 }; 8520 } 8521 8522 // exports 8523 // -------------------------------------------------------------------------------------------------- 8524 var version = '4.2.0'; 8525 8526 exports.Calendar = Calendar; 8527 exports.Component = Component; 8528 exports.DateComponent = DateComponent; 8529 exports.DateEnv = DateEnv; 8530 exports.DateProfileGenerator = DateProfileGenerator; 8531 exports.DayHeader = DayHeader; 8532 exports.DaySeries = DaySeries; 8533 exports.DayTable = DayTable; 8534 exports.ElementDragging = ElementDragging; 8535 exports.ElementScrollController = ElementScrollController; 8536 exports.EmitterMixin = EmitterMixin; 8537 exports.EventApi = EventApi; 8538 exports.FgEventRenderer = FgEventRenderer;
8539 exports.FillRenderer = FillRenderer; 8540 exports.Interaction = Interaction; 8541 exports.Mixin = Mixin; 8542 exports.NamedTimeZoneImpl = NamedTimeZoneImpl; 8543 exports.PositionCache = PositionCache; 8544 exports.ScrollComponent = ScrollComponent; 8545 exports.ScrollController = ScrollController; 8546 exports.Slicer = Slicer; 8547 exports.Splitter = Splitter; 8548 exports.Theme = Theme; 8549 exports.View = View; 8550 exports.WindowScrollController = WindowScrollController; 8551 exports.addDays = addDays; 8552 exports.addDurations = addDurations; 8553 exports.addMs = addMs; 8554 exports.addWeeks = addWeeks; 8555 exports.allowContextMenu = allowContextMenu; 8556 exports.allowSelection = allowSelection; 8557 exports.appendToElement = appendToElement; 8558 exports.applyAll = applyAll; 8559 exports.applyMutationToEventStore = applyMutationToEventStore; 8560 exports.applyStyle = applyStyle; 8561 exports.applyStyleProp = applyStyleProp; 8562 exports.asRoughMinutes = asRoughMinutes; 8563 exports.asRoughMs = asRoughMs; 8564 exports.asRoughSeconds = asRoughSeconds; 8565 exports.buildGotoAnchorHtml = buildGotoAnchorHtml; 8566 exports.buildSegCompareObj = buildSegCompareObj; 8567 exports.capitaliseFirstLetter = capitaliseFirstLetter; 8568 exports.combineEventUis = combineEventUis; 8569 exports.compareByFieldSpec = compareByFieldSpec; 8570 exports.compareByFieldSpecs = compareByFieldSpecs; 8571 exports.compareNumbers = compareNumbers; 8572 exports.compensateScroll = compensateScroll; 8573 exports.computeClippingRect = computeClippingRect; 8574 exports.computeEdges = computeEdges; 8575 exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat; 8576 exports.computeHeightAndMargins = computeHeightAndMargins; 8577 exports.computeInnerRect = computeInnerRect; 8578 exports.computeRect = computeRect; 8579 exports.computeVisibleDayRange = computeVisibleDayRange; 8580 exports.config = config; 8581 exports.constrainPoint = constrainPoint; 8582 exports.createDuration = createDuration; 8583 exports.createElement = createElement; 8584 exports.createEmptyEventStore = createEmptyEventStore; 8585 exports.createEventInstance = createEventInstance; 8586 exports.createFormatter = createFormatter; 8587 exports.createPlugin = createPlugin; 8588 exports.cssToStr = cssToStr; 8589 exports.debounce = debounce; 8590 exports.diffDates = diffDates; 8591 exports.diffDayAndTime = diffDayAndTime; 8592 exports.diffDays = diffDays; 8593 exports.diffPoints = diffPoints; 8594 exports.diffWeeks = diffWeeks; 8595 exports.diffWholeDays = diffWholeDays; 8596 exports.diffWholeWeeks = diffWholeWeeks; 8597 exports.disableCursor = disableCursor; 8598 exports.distributeHeight = distributeHeight; 8599 exports.elementClosest = elementClosest; 8600 exports.elementMatches = elementMatches; 8601 exports.enableCursor = enableCursor; 8602 exports.eventTupleToStore = eventTupleToStore; 8603 exports.filterEventStoreDefs = filterEventStoreDefs; 8604 exports.filterHash = filterHash; 8605 exports.findChildren = findChildren; 8606 exports.findElements = findElements; 8607 exports.flexibleCompare = flexibleCompare; 8608 exports.forceClassName = forceClassName; 8609 exports.formatDate = formatDate; 8610 exports.formatIsoTimeString = formatIsoTimeString; 8611 exports.formatRange = formatRange; 8612 exports.getAllDayHtml = getAllDayHtml; 8613 exports.getClippingParents = getClippingParents; 8614 exports.getDayClasses = getDayClasses; 8615 exports.getElSeg = getElSeg; 8616 exports.getRectCenter = getRectCenter; 8617 exports.getRelevantEvents = getRelevantEvents; 8618 exports.globalDefaults = globalDefaults; 8619 exports.greatestDurationDenominator = greatestDurationDenominator; 8620 exports.hasBgRendering = hasBgRendering; 8621 exports.htmlEscape = htmlEscape; 8622 exports.htmlToElement = htmlToElement; 8623 exports.insertAfterElement = insertAfterElement; 8624 exports.interactionSettingsStore = interactionSettingsStore; 8625 exports.interactionSettingsToStore = interactionSettingsToStore; 8626 exports.intersectRanges = intersectRanges; 8627 exports.intersectRects = intersectRects; 8628 exports.isArraysEqual = isArraysEqual; 8629 exports.isDateSpansEqual = isDateSpansEqual; 8630 exports.isInt = isInt; 8631 exports.isInteractionValid = isInteractionValid; 8632 exports.isMultiDayRange = isMultiDayRange; 8633 exports.isPropsEqual = isPropsEqual; 8634 exports.isPropsValid = isPropsValid; 8635 exports.isSingleDay = isSingleDay; 8636 exports.isValidDate = isValidDate; 8637 exports.listenBySelector = listenBySelector; 8638 exports.mapHash = mapHash;
8639 exports.matchCellWidths = matchCellWidths; 8640 exports.memoize = memoize; 8641 exports.memoizeOutput = memoizeOutput; 8642 exports.memoizeRendering = memoizeRendering; 8643 exports.mergeEventStores = mergeEventStores; 8644 exports.multiplyDuration = multiplyDuration; 8645 exports.padStart = padStart; 8646 exports.parseBusinessHours = parseBusinessHours; 8647 exports.parseDragMeta = parseDragMeta; 8648 exports.parseEventDef = parseEventDef; 8649 exports.parseFieldSpecs = parseFieldSpecs; 8650 exports.parseMarker = parse; 8651 exports.pointInsideRect = pointInsideRect; 8652 exports.prependToElement = prependToElement; 8653 exports.preventContextMenu = preventContextMenu; 8654 exports.preventDefault = preventDefault; 8655 exports.preventSelection = preventSelection; 8656 exports.processScopedUiProps = processScopedUiProps; 8657 exports.rangeContainsMarker = rangeContainsMarker; 8658 exports.rangeContainsRange = rangeContainsRange; 8659 exports.rangesEqual = rangesEqual; 8660 exports.rangesIntersect = rangesIntersect; 8661 exports.refineProps = refineProps; 8662 exports.removeElement = removeElement; 8663 exports.removeExact = removeExact; 8664 exports.renderDateCell = renderDateCell; 8665 exports.requestJson = requestJson; 8666 exports.sliceEventStore = sliceEventStore; 8667 exports.startOfDay = startOfDay; 8668 exports.subtractInnerElHeight = subtractInnerElHeight; 8669 exports.translateRect = translateRect; 8670 exports.uncompensateScroll = uncompensateScroll; 8671 exports.undistributeHeight = undistributeHeight; 8672 exports.unpromisify = unpromisify; 8673 exports.version = version; 8674 exports.whenTransitionDone = whenTransitionDone; 8675 exports.wholeDivideDurations = wholeDivideDurations; 8676 8677 Object.defineProperty(exports, '__esModule', { value: true }); 8678 8679}));
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.