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