提交 | 用户 | 时间
|
1ac2bc
|
1 |
/*! |
懒 |
2 |
FullCalendar Core Package v4.3.1 |
|
3 |
Docs & 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 >= 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"); 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, biggestUnitForPartial); |
|
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, newDate)) { |
|
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-' + 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, sourceInput) { |
|
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 |
})); |