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