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