UNPKG

@fullcalendar/core

Version:

FullCalendar core package for rendering a calendar

1,016 lines (1,005 loc) 445 kB
/*! FullCalendar Core v6.1.13 Docs & License: https://fullcalendar.io (c) 2024 Adam Shaw */ var FullCalendar = (function (exports) { 'use strict'; const styleTexts = []; const styleEls = new Map(); function injectStyles(styleText) { styleTexts.push(styleText); styleEls.forEach((styleEl) => { appendStylesTo(styleEl, styleText); }); } function ensureElHasStyles(el) { if (el.isConnected && // sometimes true if SSR system simulates DOM el.getRootNode // sometimes undefined if SSR system simulates DOM ) { registerStylesRoot(el.getRootNode()); } } function registerStylesRoot(rootNode) { let styleEl = styleEls.get(rootNode); if (!styleEl || !styleEl.isConnected) { styleEl = rootNode.querySelector('style[data-fullcalendar]'); if (!styleEl) { styleEl = document.createElement('style'); styleEl.setAttribute('data-fullcalendar', ''); const nonce = getNonceValue(); if (nonce) { styleEl.nonce = nonce; } const parentEl = rootNode === document ? document.head : rootNode; const insertBefore = rootNode === document ? parentEl.querySelector('script,link[rel=stylesheet],link[as=style],style') : parentEl.firstChild; parentEl.insertBefore(styleEl, insertBefore); } styleEls.set(rootNode, styleEl); hydrateStylesRoot(styleEl); } } function hydrateStylesRoot(styleEl) { for (const styleText of styleTexts) { appendStylesTo(styleEl, styleText); } } function appendStylesTo(styleEl, styleText) { const { sheet } = styleEl; const ruleCnt = sheet.cssRules.length; styleText.split('}').forEach((styleStr, i) => { styleStr = styleStr.trim(); if (styleStr) { sheet.insertRule(styleStr + '}', ruleCnt + i); } }); } // nonce // ------------------------------------------------------------------------------------------------- let queriedNonceValue; function getNonceValue() { if (queriedNonceValue === undefined) { queriedNonceValue = queryNonceValue(); } return queriedNonceValue; } /* TODO: discourage meta tag and instead put nonce attribute on placeholder <style> tag */ function queryNonceValue() { const metaWithNonce = document.querySelector('meta[name="csp-nonce"]'); if (metaWithNonce && metaWithNonce.hasAttribute('content')) { return metaWithNonce.getAttribute('content'); } const elWithNonce = document.querySelector('script[nonce]'); if (elWithNonce) { return elWithNonce.nonce || ''; } return ''; } // main // ------------------------------------------------------------------------------------------------- if (typeof document !== 'undefined') { registerStylesRoot(document); } var css_248z = ":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\"data:application/x-font-ttf;charset=utf-8;base64,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\") format(\"truetype\")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\"\\e900\"}.fc-icon-chevron-right:before{content:\"\\e901\"}.fc-icon-chevrons-left:before{content:\"\\e902\"}.fc-icon-chevrons-right:before{content:\"\\e903\"}.fc-icon-minus-square:before{content:\"\\e904\"}.fc-icon-plus-square:before{content:\"\\e905\"}.fc-icon-x:before{content:\"\\e906\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:\"\";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:\"\";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}"; injectStyles(css_248z); function removeElement(el) { if (el.parentNode) { el.parentNode.removeChild(el); } } // Querying // ---------------------------------------------------------------------------------------------------------------- function elementClosest(el, selector) { if (el.closest) { return el.closest(selector); // really bad fallback for IE // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest } if (!document.documentElement.contains(el)) { return null; } do { if (elementMatches(el, selector)) { return el; } el = (el.parentElement || el.parentNode); } while (el !== null && el.nodeType === 1); return null; } function elementMatches(el, selector) { let method = el.matches || el.matchesSelector || el.msMatchesSelector; return method.call(el, selector); } // accepts multiple subject els // returns a real array. good for methods like forEach // TODO: accept the document function findElements(container, selector) { let containers = container instanceof HTMLElement ? [container] : container; let allMatches = []; for (let i = 0; i < containers.length; i += 1) { let matches = containers[i].querySelectorAll(selector); for (let j = 0; j < matches.length; j += 1) { allMatches.push(matches[j]); } } return allMatches; } // accepts multiple subject els // only queries direct child elements // TODO: rename to findDirectChildren! function findDirectChildren(parent, selector) { let parents = parent instanceof HTMLElement ? [parent] : parent; let allMatches = []; for (let i = 0; i < parents.length; i += 1) { let childNodes = parents[i].children; // only ever elements for (let j = 0; j < childNodes.length; j += 1) { let childNode = childNodes[j]; if (!selector || elementMatches(childNode, selector)) { allMatches.push(childNode); } } } return allMatches; } // Style // ---------------------------------------------------------------------------------------------------------------- const PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i; function applyStyle(el, props) { for (let propName in props) { applyStyleProp(el, propName, props[propName]); } } function applyStyleProp(el, name, val) { if (val == null) { el.style[name] = ''; } else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) { el.style[name] = `${val}px`; } else { el.style[name] = val; } } // Event Handling // ---------------------------------------------------------------------------------------------------------------- // if intercepting bubbled events at the document/window/body level, // and want to see originating element (the 'target'), use this util instead // of `ev.target` because it goes within web-component boundaries. function getEventTargetViaRoot(ev) { var _a, _b; return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target; } // Unique ID for DOM attribute let guid$1 = 0; function getUniqueDomId() { guid$1 += 1; return 'fc-dom-' + guid$1; } // Stops a mouse/touch event from doing it's native browser action function preventDefault(ev) { ev.preventDefault(); } // Event Delegation // ---------------------------------------------------------------------------------------------------------------- function buildDelegationHandler(selector, handler) { return (ev) => { let matchedChild = elementClosest(ev.target, selector); if (matchedChild) { handler.call(matchedChild, ev, matchedChild); } }; } function listenBySelector(container, eventType, selector, handler) { let attachedHandler = buildDelegationHandler(selector, handler); container.addEventListener(eventType, attachedHandler); return () => { container.removeEventListener(eventType, attachedHandler); }; } function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) { let currentMatchedChild; return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => { if (matchedChild !== currentMatchedChild) { currentMatchedChild = matchedChild; onMouseEnter(mouseOverEv, matchedChild); let realOnMouseLeave = (mouseLeaveEv) => { currentMatchedChild = null; onMouseLeave(mouseLeaveEv, matchedChild); matchedChild.removeEventListener('mouseleave', realOnMouseLeave); }; // listen to the next mouseleave, and then unattach matchedChild.addEventListener('mouseleave', realOnMouseLeave); } }); } // Animation // ---------------------------------------------------------------------------------------------------------------- const transitionEventNames = [ 'webkitTransitionEnd', 'otransitionend', 'oTransitionEnd', 'msTransitionEnd', 'transitionend', ]; // triggered only when the next single subsequent transition finishes function whenTransitionDone(el, callback) { let realCallback = (ev) => { callback(ev); transitionEventNames.forEach((eventName) => { el.removeEventListener(eventName, realCallback); }); }; transitionEventNames.forEach((eventName) => { el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes }); } // ARIA workarounds // ---------------------------------------------------------------------------------------------------------------- function createAriaClickAttrs(handler) { return Object.assign({ onClick: handler }, createAriaKeyboardAttrs(handler)); } function createAriaKeyboardAttrs(handler) { return { tabIndex: 0, onKeyDown(ev) { if (ev.key === 'Enter' || ev.key === ' ') { handler(ev); ev.preventDefault(); // if space, don't scroll down page } }, }; } let guidNumber = 0; function guid() { guidNumber += 1; return String(guidNumber); } /* FullCalendar-specific DOM Utilities ----------------------------------------------------------------------------------------------------------------------*/ // Make the mouse cursor express that an event is not allowed in the current area function disableCursor() { document.body.classList.add('fc-not-allowed'); } // Returns the mouse cursor to its original look function enableCursor() { document.body.classList.remove('fc-not-allowed'); } /* Selection ----------------------------------------------------------------------------------------------------------------------*/ function preventSelection(el) { el.style.userSelect = 'none'; el.style.webkitUserSelect = 'none'; el.addEventListener('selectstart', preventDefault); } function allowSelection(el) { el.style.userSelect = ''; el.style.webkitUserSelect = ''; el.removeEventListener('selectstart', preventDefault); } /* Context Menu ----------------------------------------------------------------------------------------------------------------------*/ function preventContextMenu(el) { el.addEventListener('contextmenu', preventDefault); } function allowContextMenu(el) { el.removeEventListener('contextmenu', preventDefault); } function parseFieldSpecs(input) { let specs = []; let tokens = []; let i; let token; if (typeof input === 'string') { tokens = input.split(/\s*,\s*/); } else if (typeof input === 'function') { tokens = [input]; } else if (Array.isArray(input)) { tokens = input; } for (i = 0; i < tokens.length; i += 1) { token = tokens[i]; if (typeof token === 'string') { specs.push(token.charAt(0) === '-' ? { field: token.substring(1), order: -1 } : { field: token, order: 1 }); } else if (typeof token === 'function') { specs.push({ func: token }); } } return specs; } function compareByFieldSpecs(obj0, obj1, fieldSpecs) { let i; let cmp; for (i = 0; i < fieldSpecs.length; i += 1) { cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]); if (cmp) { return cmp; } } return 0; } function compareByFieldSpec(obj0, obj1, fieldSpec) { if (fieldSpec.func) { return fieldSpec.func(obj0, obj1); } return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) * (fieldSpec.order || 1); } function flexibleCompare(a, b) { if (!a && !b) { return 0; } if (b == null) { return -1; } if (a == null) { return 1; } if (typeof a === 'string' || typeof b === 'string') { return String(a).localeCompare(String(b)); } return a - b; } /* String Utilities ----------------------------------------------------------------------------------------------------------------------*/ function padStart(val, len) { let s = String(val); return '000'.substr(0, len - s.length) + s; } function formatWithOrdinals(formatter, args, fallbackText) { if (typeof formatter === 'function') { return formatter(...args); } if (typeof formatter === 'string') { // non-blank string return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter); } return fallbackText; } /* Number Utilities ----------------------------------------------------------------------------------------------------------------------*/ function compareNumbers(a, b) { return a - b; } function isInt(n) { return n % 1 === 0; } /* FC-specific DOM dimension stuff ----------------------------------------------------------------------------------------------------------------------*/ function computeSmallestCellWidth(cellEl) { let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame'); let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion'); if (!allWidthEl) { throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const } if (!contentWidthEl) { throw new Error('needs fc-scrollgrid-shrink-cushion className'); } return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border contentWidthEl.getBoundingClientRect().width; } const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds']; const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/; // Parsing and Creation function createDuration(input, unit) { if (typeof input === 'string') { return parseString(input); } if (typeof input === 'object' && input) { // non-null object return parseObject(input); } if (typeof input === 'number') { return parseObject({ [unit || 'milliseconds']: input }); } return null; } function parseString(s) { let m = PARSE_RE.exec(s); if (m) { let sign = m[1] ? -1 : 1; return { years: 0, months: 0, days: sign * (m[2] ? parseInt(m[2], 10) : 0), milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds (m[6] ? parseInt(m[6], 10) : 0) // ms ), }; } return null; } function parseObject(obj) { let duration = { years: obj.years || obj.year || 0, months: obj.months || obj.month || 0, days: obj.days || obj.day || 0, milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes (obj.seconds || obj.second || 0) * 1000 + // seconds (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms }; let weeks = obj.weeks || obj.week; if (weeks) { duration.days += weeks * 7; duration.specifiedWeeks = true; } return duration; } // Equality function durationsEqual(d0, d1) { return d0.years === d1.years && d0.months === d1.months && d0.days === d1.days && d0.milliseconds === d1.milliseconds; } function asCleanDays(dur) { if (!dur.years && !dur.months && !dur.milliseconds) { return dur.days; } return 0; } // Simple Math function addDurations(d0, d1) { return { years: d0.years + d1.years, months: d0.months + d1.months, days: d0.days + d1.days, milliseconds: d0.milliseconds + d1.milliseconds, }; } function subtractDurations(d1, d0) { return { years: d1.years - d0.years, months: d1.months - d0.months, days: d1.days - d0.days, milliseconds: d1.milliseconds - d0.milliseconds, }; } function multiplyDuration(d, n) { return { years: d.years * n, months: d.months * n, days: d.days * n, milliseconds: d.milliseconds * n, }; } // Conversions // "Rough" because they are based on average-case Gregorian months/years function asRoughYears(dur) { return asRoughDays(dur) / 365; } function asRoughMonths(dur) { return asRoughDays(dur) / 30; } function asRoughDays(dur) { return asRoughMs(dur) / 864e5; } function asRoughMinutes(dur) { return asRoughMs(dur) / (1000 * 60); } function asRoughSeconds(dur) { return asRoughMs(dur) / 1000; } function asRoughMs(dur) { return dur.years * (365 * 864e5) + dur.months * (30 * 864e5) + dur.days * 864e5 + dur.milliseconds; } // Advanced Math function wholeDivideDurations(numerator, denominator) { let res = null; for (let i = 0; i < INTERNAL_UNITS.length; i += 1) { let unit = INTERNAL_UNITS[i]; if (denominator[unit]) { let localRes = numerator[unit] / denominator[unit]; if (!isInt(localRes) || (res !== null && res !== localRes)) { return null; } res = localRes; } else if (numerator[unit]) { // needs to divide by something but can't! return null; } } return res; } function greatestDurationDenominator(dur) { let ms = dur.milliseconds; if (ms) { if (ms % 1000 !== 0) { return { unit: 'millisecond', value: ms }; } if (ms % (1000 * 60) !== 0) { return { unit: 'second', value: ms / 1000 }; } if (ms % (1000 * 60 * 60) !== 0) { return { unit: 'minute', value: ms / (1000 * 60) }; } if (ms) { return { unit: 'hour', value: ms / (1000 * 60 * 60) }; } } if (dur.days) { if (dur.specifiedWeeks && dur.days % 7 === 0) { return { unit: 'week', value: dur.days / 7 }; } return { unit: 'day', value: dur.days }; } if (dur.months) { return { unit: 'month', value: dur.months }; } if (dur.years) { return { unit: 'year', value: dur.years }; } return { unit: 'millisecond', value: 0 }; } const { hasOwnProperty } = Object.prototype; // Merges an array of objects into a single object. // The second argument allows for an array of property names who's object values will be merged together. function mergeProps(propObjs, complexPropsMap) { let dest = {}; if (complexPropsMap) { for (let name in complexPropsMap) { if (complexPropsMap[name] === isMaybeObjectsEqual) { // implies that it's object-mergeable let complexObjs = []; // collect the trailing object values, stopping when a non-object is discovered for (let i = propObjs.length - 1; i >= 0; i -= 1) { let val = propObjs[i][name]; if (typeof val === 'object' && val) { // non-null object complexObjs.unshift(val); } else if (val !== undefined) { dest[name] = val; // if there were no objects, this value will be used break; } } // if the trailing values were objects, use the merged value if (complexObjs.length) { dest[name] = mergeProps(complexObjs); } } } } // copy values into the destination, going from last to first for (let i = propObjs.length - 1; i >= 0; i -= 1) { let props = propObjs[i]; for (let name in props) { if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign dest[name] = props[name]; } } } return dest; } function filterHash(hash, func) { let filtered = {}; for (let key in hash) { if (func(hash[key], key)) { filtered[key] = hash[key]; } } return filtered; } function mapHash(hash, func) { let newHash = {}; for (let key in hash) { newHash[key] = func(hash[key], key); } return newHash; } function arrayToHash(a) { let hash = {}; for (let item of a) { hash[item] = true; } return hash; } // TODO: reassess browser support // https://caniuse.com/?search=object.values function hashValuesToArray(obj) { let a = []; for (let key in obj) { a.push(obj[key]); } return a; } function isPropsEqual(obj0, obj1) { if (obj0 === obj1) { return true; } for (let key in obj0) { if (hasOwnProperty.call(obj0, key)) { if (!(key in obj1)) { return false; } } } for (let key in obj1) { if (hasOwnProperty.call(obj1, key)) { if (obj0[key] !== obj1[key]) { return false; } } } return true; } const HANDLER_RE = /^on[A-Z]/; function isNonHandlerPropsEqual(obj0, obj1) { const keys = getUnequalProps(obj0, obj1); for (let key of keys) { if (!HANDLER_RE.test(key)) { return false; } } return true; } function getUnequalProps(obj0, obj1) { let keys = []; for (let key in obj0) { if (hasOwnProperty.call(obj0, key)) { if (!(key in obj1)) { keys.push(key); } } } for (let key in obj1) { if (hasOwnProperty.call(obj1, key)) { if (obj0[key] !== obj1[key]) { keys.push(key); } } } return keys; } function compareObjs(oldProps, newProps, equalityFuncs = {}) { if (oldProps === newProps) { return true; } for (let key in newProps) { if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ; else { return false; } } // check for props that were omitted in the new for (let key in oldProps) { if (!(key in newProps)) { return false; } } return true; } /* assumed "true" equality for handler names like "onReceiveSomething" */ function isObjValsEqual(val0, val1, comparator) { if (val0 === val1 || comparator === true) { return true; } if (comparator) { return comparator(val0, val1); } return false; } function collectFromHash(hash, startIndex = 0, endIndex, step = 1) { let res = []; if (endIndex == null) { endIndex = Object.keys(hash).length; } for (let i = startIndex; i < endIndex; i += step) { let val = hash[i]; if (val !== undefined) { // will disregard undefined for sparse arrays res.push(val); } } return res; } // TODO: new util arrayify? function removeExact(array, exactVal) { let removeCnt = 0; let i = 0; while (i < array.length) { if (array[i] === exactVal) { array.splice(i, 1); removeCnt += 1; } else { i += 1; } } return removeCnt; } function isArraysEqual(a0, a1, equalityFunc) { if (a0 === a1) { return true; } let len = a0.length; let i; if (len !== a1.length) { // not array? or not same length? return false; } for (i = 0; i < len; i += 1) { if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) { return false; } } return true; } const DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; // Adding function addWeeks(m, n) { let a = dateToUtcArray(m); a[2] += n * 7; return arrayToUtcDate(a); } function addDays(m, n) { let a = dateToUtcArray(m); a[2] += n; return arrayToUtcDate(a); } function addMs(m, n) { let a = dateToUtcArray(m); a[6] += n; return arrayToUtcDate(a); } // Diffing (all return floats) // TODO: why not use ranges? function diffWeeks(m0, m1) { return diffDays(m0, m1) / 7; } function diffDays(m0, m1) { return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24); } function diffHours(m0, m1) { return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60); } function diffMinutes(m0, m1) { return (m1.valueOf() - m0.valueOf()) / (1000 * 60); } function diffSeconds(m0, m1) { return (m1.valueOf() - m0.valueOf()) / 1000; } function diffDayAndTime(m0, m1) { let m0day = startOfDay(m0); let m1day = startOfDay(m1); return { years: 0, months: 0, days: Math.round(diffDays(m0day, m1day)), milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()), }; } // Diffing Whole Units function diffWholeWeeks(m0, m1) { let d = diffWholeDays(m0, m1); if (d !== null && d % 7 === 0) { return d / 7; } return null; } function diffWholeDays(m0, m1) { if (timeAsMs(m0) === timeAsMs(m1)) { return Math.round(diffDays(m0, m1)); } return null; } // Start-Of function startOfDay(m) { return arrayToUtcDate([ m.getUTCFullYear(), m.getUTCMonth(), m.getUTCDate(), ]); } function startOfHour(m) { return arrayToUtcDate([ m.getUTCFullYear(), m.getUTCMonth(), m.getUTCDate(), m.getUTCHours(), ]); } function startOfMinute(m) { return arrayToUtcDate([ m.getUTCFullYear(), m.getUTCMonth(), m.getUTCDate(), m.getUTCHours(), m.getUTCMinutes(), ]); } function startOfSecond(m) { return arrayToUtcDate([ m.getUTCFullYear(), m.getUTCMonth(), m.getUTCDate(), m.getUTCHours(), m.getUTCMinutes(), m.getUTCSeconds(), ]); } // Week Computation function weekOfYear(marker, dow, doy) { let y = marker.getUTCFullYear(); let w = weekOfGivenYear(marker, y, dow, doy); if (w < 1) { return weekOfGivenYear(marker, y - 1, dow, doy); } let nextW = weekOfGivenYear(marker, y + 1, dow, doy); if (nextW >= 1) { return Math.min(w, nextW); } return w; } function weekOfGivenYear(marker, year, dow, doy) { let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]); let dayStart = startOfDay(marker); let days = Math.round(diffDays(firstWeekStart, dayStart)); return Math.floor(days / 7) + 1; // zero-indexed } // start-of-first-week - start-of-year function firstWeekOffset(year, dow, doy) { // first-week day -- which january is always in the first week (4 for iso, 1 for other) let fwd = 7 + dow - doy; // first-week day local weekday -- which local weekday is fwd let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7; return -fwdlw + fwd - 1; } // Array Conversion function dateToLocalArray(date) { return [ date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds(), ]; } function arrayToLocalDate(a) { return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month a[3] || 0, a[4] || 0, a[5] || 0); } function dateToUtcArray(date) { return [ date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds(), ]; } function arrayToUtcDate(a) { // according to web standards (and Safari), a month index is required. // massage if only given a year. if (a.length === 1) { a = a.concat([0]); } return new Date(Date.UTC(...a)); } // Other Utils function isValidDate(m) { return !isNaN(m.valueOf()); } function timeAsMs(m) { return m.getUTCHours() * 1000 * 60 * 60 + m.getUTCMinutes() * 1000 * 60 + m.getUTCSeconds() * 1000 + m.getUTCMilliseconds(); } // timeZoneOffset is in minutes function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) { let s = marker.toISOString(); s = s.replace('.000', ''); if (stripZeroTime) { s = s.replace('T00:00:00Z', ''); } if (s.length > 10) { // time part wasn't stripped, can add timezone info if (timeZoneOffset == null) { s = s.replace('Z', ''); } else if (timeZoneOffset !== 0) { s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true)); } // otherwise, its UTC-0 and we want to keep the Z } return s; } // formats the date, but with no time part // TODO: somehow merge with buildIsoString and stripZeroTime // TODO: rename. omit "string" function formatDayString(marker) { return marker.toISOString().replace(/T.*$/, ''); } function formatIsoMonthStr(marker) { return marker.toISOString().match(/^\d{4}-\d{2}/)[0]; } // TODO: use Date::toISOString and use everything after the T? function formatIsoTimeString(marker) { return padStart(marker.getUTCHours(), 2) + ':' + padStart(marker.getUTCMinutes(), 2) + ':' + padStart(marker.getUTCSeconds(), 2); } function formatTimeZoneOffset(minutes, doIso = false) { let sign = minutes < 0 ? '-' : '+'; let abs = Math.abs(minutes); let hours = Math.floor(abs / 60); let mins = Math.round(abs % 60); if (doIso) { return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`; } return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`; } function memoize(workerFunc, resEquality, teardownFunc) { let currentArgs; let currentRes; return function (...newArgs) { if (!currentArgs) { currentRes = workerFunc.apply(this, newArgs); } else if (!isArraysEqual(currentArgs, newArgs)) { if (teardownFunc) { teardownFunc(currentRes); } let res = workerFunc.apply(this, newArgs); if (!resEquality || !resEquality(res, currentRes)) { currentRes = res; } } currentArgs = newArgs; return currentRes; }; } function memoizeObjArg(workerFunc, resEquality, teardownFunc) { let currentArg; let currentRes; return (newArg) => { if (!currentArg) { currentRes = workerFunc.call(this, newArg); } else if (!isPropsEqual(currentArg, newArg)) { if (teardownFunc) { teardownFunc(currentRes); } let res = workerFunc.call(this, newArg); if (!resEquality || !resEquality(res, currentRes)) { currentRes = res; } } currentArg = newArg; return currentRes; }; } function memoizeArraylike(// used at all? workerFunc, resEquality, teardownFunc) { let currentArgSets = []; let currentResults = []; return (newArgSets) => { let currentLen = currentArgSets.length; let newLen = newArgSets.length; let i = 0; for (; i < currentLen; i += 1) { if (!newArgSets[i]) { // one of the old sets no longer exists if (teardownFunc) { teardownFunc(currentResults[i]); } } else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) { if (teardownFunc) { teardownFunc(currentResults[i]); } let res = workerFunc.apply(this, newArgSets[i]); if (!resEquality || !resEquality(res, currentResults[i