main.js 94 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030
  1. /*!
  2. FullCalendar Timeline Plugin v4.4.3
  3. Docs & License: https://fullcalendar.io/scheduler
  4. (c) 2019 Adam Shaw
  5. */
  6. (function (global, factory) {
  7. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
  8. typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
  9. (global = global || self, factory(global.FullCalendarTimeline = {}, global.FullCalendar));
  10. }(this, function (exports, core) { 'use strict';
  11. /*! *****************************************************************************
  12. Copyright (c) Microsoft Corporation.
  13. Permission to use, copy, modify, and/or distribute this software for any
  14. purpose with or without fee is hereby granted.
  15. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  16. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  17. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  18. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  19. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  20. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. PERFORMANCE OF THIS SOFTWARE.
  22. ***************************************************************************** */
  23. /* global Reflect, Promise */
  24. var extendStatics = function(d, b) {
  25. extendStatics = Object.setPrototypeOf ||
  26. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  27. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  28. return extendStatics(d, b);
  29. };
  30. function __extends(d, b) {
  31. extendStatics(d, b);
  32. function __() { this.constructor = d; }
  33. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  34. }
  35. var __assign = function() {
  36. __assign = Object.assign || function __assign(t) {
  37. for (var s, i = 1, n = arguments.length; i < n; i++) {
  38. s = arguments[i];
  39. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  40. }
  41. return t;
  42. };
  43. return __assign.apply(this, arguments);
  44. };
  45. /*
  46. A rectangular area of content that lives within a Scroller.
  47. Can have "gutters", areas of dead spacing around the perimeter.
  48. Also very useful for forcing a width, which a Scroller cannot do alone.
  49. Has a content area that lives above a background area.
  50. */
  51. var ScrollerCanvas = /** @class */ (function () {
  52. function ScrollerCanvas() {
  53. this.gutters = {};
  54. this.el = core.htmlToElement("<div class=\"fc-scroller-canvas\"> <div class=\"fc-content\"></div> <div class=\"fc-bg\"></div> </div>");
  55. this.contentEl = this.el.querySelector('.fc-content');
  56. this.bgEl = this.el.querySelector('.fc-bg');
  57. }
  58. /*
  59. If falsy, resets all the gutters to 0
  60. */
  61. ScrollerCanvas.prototype.setGutters = function (gutters) {
  62. if (!gutters) {
  63. this.gutters = {};
  64. }
  65. else {
  66. __assign(this.gutters, gutters);
  67. }
  68. this.updateSize();
  69. };
  70. ScrollerCanvas.prototype.setWidth = function (width) {
  71. this.width = width;
  72. this.updateSize();
  73. };
  74. ScrollerCanvas.prototype.setMinWidth = function (minWidth) {
  75. this.minWidth = minWidth;
  76. this.updateSize();
  77. };
  78. ScrollerCanvas.prototype.clearWidth = function () {
  79. this.width = null;
  80. this.minWidth = null;
  81. this.updateSize();
  82. };
  83. ScrollerCanvas.prototype.updateSize = function () {
  84. var _a = this, gutters = _a.gutters, el = _a.el;
  85. // is border-box (width includes padding)
  86. core.forceClassName(el, 'fc-gutter-left', gutters.left);
  87. core.forceClassName(el, 'fc-gutter-right', gutters.right);
  88. core.forceClassName(el, 'fc-gutter-top', gutters.top);
  89. core.forceClassName(el, 'fc-gutter-bottom', gutters.bottom);
  90. core.applyStyle(el, {
  91. paddingLeft: gutters.left || '',
  92. paddingRight: gutters.right || '',
  93. paddingTop: gutters.top || '',
  94. paddingBottom: gutters.bottom || '',
  95. width: (this.width != null) ?
  96. this.width + (gutters.left || 0) + (gutters.right || 0) :
  97. '',
  98. minWidth: (this.minWidth != null) ?
  99. this.minWidth + (gutters.left || 0) + (gutters.right || 0) :
  100. ''
  101. });
  102. core.applyStyle(this.bgEl, {
  103. left: gutters.left || '',
  104. right: gutters.right || '',
  105. top: gutters.top || '',
  106. bottom: gutters.bottom || ''
  107. });
  108. };
  109. return ScrollerCanvas;
  110. }());
  111. var EnhancedScroller = /** @class */ (function (_super) {
  112. __extends(EnhancedScroller, _super);
  113. function EnhancedScroller(overflowX, overflowY) {
  114. var _this = _super.call(this, overflowX, overflowY) || this;
  115. // Scroll Events
  116. // ----------------------------------------------------------------------------------------------
  117. _this.reportScroll = function () {
  118. if (!_this.isScrolling) {
  119. _this.reportScrollStart();
  120. }
  121. _this.trigger('scroll');
  122. _this.isMoving = true;
  123. _this.requestMovingEnd();
  124. };
  125. _this.reportScrollStart = function () {
  126. if (!_this.isScrolling) {
  127. _this.isScrolling = true;
  128. _this.trigger('scrollStart', _this.isTouching); // created in constructor
  129. }
  130. };
  131. // Touch Events
  132. // ----------------------------------------------------------------------------------------------
  133. // will fire *before* the scroll event is fired
  134. _this.reportTouchStart = function () {
  135. _this.isTouching = true;
  136. };
  137. _this.reportTouchEnd = function () {
  138. if (_this.isTouching) {
  139. _this.isTouching = false;
  140. // if touch scrolling was re-enabled during a recent touch scroll
  141. // then unbind the handlers that are preventing it from happening.
  142. if (_this.isTouchScrollEnabled) {
  143. _this.unbindPreventTouchScroll(); // won't do anything if not bound
  144. }
  145. // if the user ended their touch, and the scroll area wasn't moving,
  146. // we consider this to be the end of the scroll.
  147. if (!_this.isMoving) {
  148. _this.reportScrollEnd(); // won't fire if already ended
  149. }
  150. }
  151. };
  152. _this.isScrolling = false;
  153. _this.isTouching = false;
  154. _this.isMoving = false;
  155. _this.isTouchScrollEnabled = true;
  156. _this.requestMovingEnd = core.debounce(_this.reportMovingEnd, 500);
  157. _this.canvas = new ScrollerCanvas();
  158. _this.el.appendChild(_this.canvas.el);
  159. _this.applyOverflow();
  160. _this.bindHandlers();
  161. return _this;
  162. }
  163. EnhancedScroller.prototype.destroy = function () {
  164. _super.prototype.destroy.call(this);
  165. this.unbindHandlers();
  166. };
  167. // Touch scroll prevention
  168. // ----------------------------------------------------------------------------------------------
  169. EnhancedScroller.prototype.disableTouchScroll = function () {
  170. this.isTouchScrollEnabled = false;
  171. this.bindPreventTouchScroll(); // will be unbound in enableTouchScroll or reportTouchEnd
  172. };
  173. EnhancedScroller.prototype.enableTouchScroll = function () {
  174. this.isTouchScrollEnabled = true;
  175. // only immediately unbind if a touch event is NOT in progress.
  176. // otherwise, it will be handled by reportTouchEnd.
  177. if (!this.isTouching) {
  178. this.unbindPreventTouchScroll();
  179. }
  180. };
  181. EnhancedScroller.prototype.bindPreventTouchScroll = function () {
  182. if (!this.preventTouchScrollHandler) {
  183. this.el.addEventListener('touchmove', (this.preventTouchScrollHandler = core.preventDefault));
  184. }
  185. };
  186. EnhancedScroller.prototype.unbindPreventTouchScroll = function () {
  187. if (this.preventTouchScrollHandler) {
  188. this.el.removeEventListener('touchmove', this.preventTouchScrollHandler);
  189. this.preventTouchScrollHandler = null;
  190. }
  191. };
  192. // Handlers
  193. // ----------------------------------------------------------------------------------------------
  194. EnhancedScroller.prototype.bindHandlers = function () {
  195. this.el.addEventListener('scroll', this.reportScroll);
  196. this.el.addEventListener('touchstart', this.reportTouchStart, { passive: true });
  197. this.el.addEventListener('touchend', this.reportTouchEnd);
  198. };
  199. EnhancedScroller.prototype.unbindHandlers = function () {
  200. this.el.removeEventListener('scroll', this.reportScroll);
  201. this.el.removeEventListener('touchstart', this.reportTouchStart, { passive: true });
  202. this.el.removeEventListener('touchend', this.reportTouchEnd);
  203. };
  204. EnhancedScroller.prototype.reportMovingEnd = function () {
  205. this.isMoving = false;
  206. // only end the scroll if not currently touching.
  207. // if touching, the scrolling will end later, on touchend.
  208. if (!this.isTouching) {
  209. this.reportScrollEnd();
  210. }
  211. };
  212. EnhancedScroller.prototype.reportScrollEnd = function () {
  213. if (this.isScrolling) {
  214. this.trigger('scrollEnd');
  215. this.isScrolling = false;
  216. }
  217. };
  218. // Horizontal Scroll Normalization
  219. // ----------------------------------------------------------------------------------------------
  220. // http://stackoverflow.com/questions/24276619/better-way-to-get-the-viewport-of-a-scrollable-div-in-rtl-mode/24394376#24394376
  221. // TODO: move all this to util functions
  222. /*
  223. If RTL, and scrolled to the left, returns NEGATIVE value (like Firefox)
  224. */
  225. EnhancedScroller.prototype.getScrollLeft = function () {
  226. var el = this.el;
  227. var direction = window.getComputedStyle(el).direction;
  228. var val = el.scrollLeft;
  229. if (direction === 'rtl') {
  230. switch (getRtlScrollSystem()) {
  231. case 'positive':
  232. val = (val + el.clientWidth) - el.scrollWidth;
  233. break;
  234. case 'reverse':
  235. val = -val;
  236. break;
  237. }
  238. }
  239. return val;
  240. };
  241. /*
  242. Accepts a NEGATIVE value for when scrolled in RTL
  243. */
  244. EnhancedScroller.prototype.setScrollLeft = function (val) {
  245. var el = this.el;
  246. var direction = window.getComputedStyle(el).direction;
  247. if (direction === 'rtl') {
  248. switch (getRtlScrollSystem()) {
  249. case 'positive':
  250. val = (val - el.clientWidth) + el.scrollWidth;
  251. break;
  252. case 'reverse':
  253. val = -val;
  254. break;
  255. }
  256. }
  257. el.scrollLeft = val;
  258. };
  259. /*
  260. Always returns the number of pixels scrolled from the leftmost position (even if RTL).
  261. Always positive.
  262. */
  263. EnhancedScroller.prototype.getScrollFromLeft = function () {
  264. var el = this.el;
  265. var direction = window.getComputedStyle(el).direction;
  266. var val = el.scrollLeft;
  267. if (direction === 'rtl') {
  268. switch (getRtlScrollSystem()) {
  269. case 'negative':
  270. val = (val - el.clientWidth) + el.scrollWidth;
  271. break;
  272. case 'reverse':
  273. val = (-val - el.clientWidth) + el.scrollWidth;
  274. break;
  275. }
  276. }
  277. return val;
  278. };
  279. return EnhancedScroller;
  280. }(core.ScrollComponent));
  281. core.EmitterMixin.mixInto(EnhancedScroller);
  282. // Horizontal Scroll System Detection
  283. // ----------------------------------------------------------------------------------------------
  284. var _rtlScrollSystem;
  285. function getRtlScrollSystem() {
  286. return _rtlScrollSystem || (_rtlScrollSystem = detectRtlScrollSystem());
  287. }
  288. function detectRtlScrollSystem() {
  289. var el = core.htmlToElement("<div style=\" position: absolute; top: -1000px; width: 1px; height: 1px; overflow: scroll; direction: rtl; font-size: 100px; \">A</div>");
  290. document.body.appendChild(el);
  291. var system;
  292. if (el.scrollLeft > 0) {
  293. system = 'positive';
  294. }
  295. else {
  296. el.scrollLeft = 1;
  297. if (el.scrollLeft > 0) {
  298. system = 'reverse';
  299. }
  300. else {
  301. system = 'negative';
  302. }
  303. }
  304. core.removeElement(el);
  305. return system;
  306. }
  307. /*
  308. A Scroller, but with a wrapping div that allows "clipping" away of native scrollbars,
  309. giving the appearance that there are no scrollbars.
  310. */
  311. var ClippedScroller = /** @class */ (function () {
  312. /*
  313. Received overflows can be set to 'clipped', meaning scrollbars shouldn't be visible
  314. to the user, but the area should still scroll.
  315. */
  316. function ClippedScroller(overflowX, overflowY, parentEl) {
  317. this.isHScrollbarsClipped = false;
  318. this.isVScrollbarsClipped = false;
  319. if (overflowX === 'clipped-scroll') {
  320. overflowX = 'scroll';
  321. this.isHScrollbarsClipped = true;
  322. }
  323. if (overflowY === 'clipped-scroll') {
  324. overflowY = 'scroll';
  325. this.isVScrollbarsClipped = true;
  326. }
  327. this.enhancedScroll = new EnhancedScroller(overflowX, overflowY);
  328. parentEl.appendChild(this.el = core.createElement('div', {
  329. className: 'fc-scroller-clip'
  330. }));
  331. this.el.appendChild(this.enhancedScroll.el);
  332. }
  333. ClippedScroller.prototype.destroy = function () {
  334. core.removeElement(this.el);
  335. };
  336. ClippedScroller.prototype.updateSize = function () {
  337. var enhancedScroll = this.enhancedScroll;
  338. var scrollEl = enhancedScroll.el;
  339. var edges = core.computeEdges(scrollEl);
  340. var cssProps = { marginLeft: 0, marginRight: 0, marginTop: 0, marginBottom: 0 };
  341. // give the inner scrolling div negative margins so that its scrollbars
  342. // are nudged outside of the bounding box of the wrapper, which is overflow:hidden
  343. if (this.isVScrollbarsClipped) {
  344. cssProps.marginLeft = -edges.scrollbarLeft;
  345. cssProps.marginRight = -edges.scrollbarRight;
  346. }
  347. if (this.isHScrollbarsClipped) {
  348. cssProps.marginBottom = -edges.scrollbarBottom;
  349. }
  350. core.applyStyle(scrollEl, cssProps);
  351. // if we are attempting to hide the scrollbars offscreen, OSX/iOS will still
  352. // display the floating scrollbars. attach a className to force-hide them.
  353. if ((this.isHScrollbarsClipped || (enhancedScroll.overflowX === 'hidden')) && // should never show?
  354. (this.isVScrollbarsClipped || (enhancedScroll.overflowY === 'hidden')) && // should never show?
  355. !( // doesn't have any scrollbar mass
  356. edges.scrollbarLeft ||
  357. edges.scrollbarRight ||
  358. edges.scrollbarBottom)) {
  359. scrollEl.classList.add('fc-no-scrollbars');
  360. }
  361. else {
  362. scrollEl.classList.remove('fc-no-scrollbars');
  363. }
  364. };
  365. ClippedScroller.prototype.setHeight = function (height) {
  366. this.enhancedScroll.setHeight(height);
  367. };
  368. /*
  369. Accounts for 'clipped' scrollbars
  370. */
  371. ClippedScroller.prototype.getScrollbarWidths = function () {
  372. var widths = this.enhancedScroll.getScrollbarWidths();
  373. if (this.isVScrollbarsClipped) {
  374. widths.left = 0;
  375. widths.right = 0;
  376. }
  377. if (this.isHScrollbarsClipped) {
  378. widths.bottom = 0;
  379. }
  380. return widths;
  381. };
  382. return ClippedScroller;
  383. }());
  384. var ScrollJoiner = /** @class */ (function () {
  385. function ScrollJoiner(axis, scrollers) {
  386. this.axis = axis;
  387. this.scrollers = scrollers;
  388. for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
  389. var scroller = _a[_i];
  390. this.initScroller(scroller);
  391. }
  392. }
  393. ScrollJoiner.prototype.initScroller = function (scroller) {
  394. var _this = this;
  395. var enhancedScroll = scroller.enhancedScroll;
  396. // when the user scrolls via mousewheel, we know for sure the target
  397. // scroller should be the master. capture the various x-browser events that fire.
  398. var onScroll = function () {
  399. _this.assignMasterScroller(scroller);
  400. };
  401. 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ').forEach(function (evName) {
  402. enhancedScroll.el.addEventListener(evName, onScroll);
  403. });
  404. enhancedScroll
  405. .on('scrollStart', function () {
  406. if (!_this.masterScroller) {
  407. _this.assignMasterScroller(scroller);
  408. }
  409. })
  410. .on('scroll', function () {
  411. if (scroller === _this.masterScroller) {
  412. for (var _i = 0, _a = _this.scrollers; _i < _a.length; _i++) {
  413. var otherScroller = _a[_i];
  414. if (otherScroller !== scroller) {
  415. switch (_this.axis) {
  416. case 'horizontal':
  417. otherScroller.enhancedScroll.el.scrollLeft = enhancedScroll.el.scrollLeft;
  418. break;
  419. case 'vertical':
  420. otherScroller.enhancedScroll.setScrollTop(enhancedScroll.getScrollTop());
  421. break;
  422. }
  423. }
  424. }
  425. }
  426. })
  427. .on('scrollEnd', function () {
  428. if (scroller === _this.masterScroller) {
  429. _this.unassignMasterScroller();
  430. }
  431. });
  432. };
  433. ScrollJoiner.prototype.assignMasterScroller = function (scroller) {
  434. this.unassignMasterScroller();
  435. this.masterScroller = scroller;
  436. for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
  437. var otherScroller = _a[_i];
  438. if (otherScroller !== scroller) {
  439. otherScroller.enhancedScroll.disableTouchScroll();
  440. }
  441. }
  442. };
  443. ScrollJoiner.prototype.unassignMasterScroller = function () {
  444. if (this.masterScroller) {
  445. for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
  446. var otherScroller = _a[_i];
  447. otherScroller.enhancedScroll.enableTouchScroll();
  448. }
  449. this.masterScroller = null;
  450. }
  451. };
  452. ScrollJoiner.prototype.update = function () {
  453. var allWidths = this.scrollers.map(function (scroller) { return scroller.getScrollbarWidths(); });
  454. var maxLeft = 0;
  455. var maxRight = 0;
  456. var maxTop = 0;
  457. var maxBottom = 0;
  458. var widths;
  459. var i;
  460. for (var _i = 0, allWidths_1 = allWidths; _i < allWidths_1.length; _i++) {
  461. widths = allWidths_1[_i];
  462. maxLeft = Math.max(maxLeft, widths.left);
  463. maxRight = Math.max(maxRight, widths.right);
  464. maxTop = Math.max(maxTop, widths.top);
  465. maxBottom = Math.max(maxBottom, widths.bottom);
  466. }
  467. for (i = 0; i < this.scrollers.length; i++) {
  468. var scroller = this.scrollers[i];
  469. widths = allWidths[i];
  470. scroller.enhancedScroll.canvas.setGutters(this.axis === 'horizontal' ?
  471. {
  472. left: maxLeft - widths.left,
  473. right: maxRight - widths.right
  474. } :
  475. {
  476. top: maxTop - widths.top,
  477. bottom: maxBottom - widths.bottom
  478. });
  479. }
  480. };
  481. return ScrollJoiner;
  482. }());
  483. var HeaderBodyLayout = /** @class */ (function () {
  484. /*
  485. verticalScroll = 'auto' | 'clipped-scroll'
  486. */
  487. function HeaderBodyLayout(headerContainerEl, bodyContainerEl, verticalScroll) {
  488. this.headerScroller = new ClippedScroller('clipped-scroll', 'hidden', headerContainerEl);
  489. this.bodyScroller = new ClippedScroller('auto', verticalScroll, bodyContainerEl);
  490. this.scrollJoiner = new ScrollJoiner('horizontal', [
  491. this.headerScroller,
  492. this.bodyScroller
  493. ]);
  494. }
  495. HeaderBodyLayout.prototype.destroy = function () {
  496. this.headerScroller.destroy();
  497. this.bodyScroller.destroy();
  498. };
  499. HeaderBodyLayout.prototype.setHeight = function (totalHeight, isAuto) {
  500. var bodyHeight;
  501. if (isAuto) {
  502. bodyHeight = 'auto';
  503. }
  504. else {
  505. bodyHeight = totalHeight - this.queryHeadHeight();
  506. }
  507. this.bodyScroller.setHeight(bodyHeight);
  508. this.headerScroller.updateSize(); // adjusts gutters and classNames
  509. this.bodyScroller.updateSize(); // adjusts gutters and classNames
  510. this.scrollJoiner.update();
  511. };
  512. HeaderBodyLayout.prototype.queryHeadHeight = function () {
  513. return this.headerScroller.enhancedScroll.canvas.contentEl.getBoundingClientRect().height;
  514. };
  515. return HeaderBodyLayout;
  516. }());
  517. var TimelineHeader = /** @class */ (function (_super) {
  518. __extends(TimelineHeader, _super);
  519. function TimelineHeader(parentEl) {
  520. var _this = _super.call(this) || this;
  521. _this.parentEl = parentEl;
  522. return _this;
  523. }
  524. TimelineHeader.prototype.firstContext = function (context) {
  525. this.parentEl.appendChild(this.tableEl = core.createElement('table', {
  526. className: context.theme.getClass('tableGrid')
  527. }));
  528. };
  529. TimelineHeader.prototype.destroy = function () {
  530. core.removeElement(this.tableEl);
  531. _super.prototype.destroy.call(this);
  532. };
  533. TimelineHeader.prototype.render = function (props) {
  534. this.renderDates(props.tDateProfile);
  535. };
  536. TimelineHeader.prototype.renderDates = function (tDateProfile) {
  537. var _a = this.context, dateEnv = _a.dateEnv, theme = _a.theme;
  538. var cellRows = tDateProfile.cellRows;
  539. var lastRow = cellRows[cellRows.length - 1];
  540. var isChrono = core.asRoughMs(tDateProfile.labelInterval) > core.asRoughMs(tDateProfile.slotDuration);
  541. var oneDay = core.isSingleDay(tDateProfile.slotDuration);
  542. var html = '<colgroup>';
  543. // needs to be a col for each body slat. header cells will have colspans
  544. for (var i = tDateProfile.slotCnt - 1; i >= 0; i--) {
  545. html += '<col/>';
  546. }
  547. html += '</colgroup>';
  548. html += '<tbody>';
  549. for (var _i = 0, cellRows_1 = cellRows; _i < cellRows_1.length; _i++) {
  550. var rowCells = cellRows_1[_i];
  551. var isLast = rowCells === lastRow;
  552. html += '<tr' + (isChrono && isLast ? ' class="fc-chrono"' : '') + '>';
  553. for (var _b = 0, rowCells_1 = rowCells; _b < rowCells_1.length; _b++) {
  554. var cell = rowCells_1[_b];
  555. var headerCellClassNames = [theme.getClass('widgetHeader')];
  556. if (cell.isWeekStart) {
  557. headerCellClassNames.push('fc-em-cell');
  558. }
  559. if (oneDay) {
  560. headerCellClassNames = headerCellClassNames.concat(core.getDayClasses(cell.date, this.props.dateProfile, this.context, true) // adds "today" class and other day-based classes
  561. );
  562. }
  563. html +=
  564. '<th class="' + headerCellClassNames.join(' ') + '"' +
  565. ' data-date="' + dateEnv.formatIso(cell.date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' +
  566. (cell.colspan > 1 ? ' colspan="' + cell.colspan + '"' : '') +
  567. '>' +
  568. '<div class="fc-cell-content">' +
  569. cell.spanHtml +
  570. '</div>' +
  571. '</th>';
  572. }
  573. html += '</tr>';
  574. }
  575. html += '</tbody>';
  576. this.tableEl.innerHTML = html; // TODO: does this work cross-browser?
  577. this.slatColEls = core.findElements(this.tableEl, 'col');
  578. this.innerEls = core.findElements(this.tableEl.querySelector('tr:last-child'), // compound selector won't work because of query-root problem
  579. 'th .fc-cell-text');
  580. core.findElements(this.tableEl.querySelectorAll('tr:not(:last-child)'), // compound selector won't work because of query-root problem
  581. 'th .fc-cell-text').forEach(function (innerEl) {
  582. innerEl.classList.add('fc-sticky');
  583. });
  584. };
  585. return TimelineHeader;
  586. }(core.Component));
  587. var TimelineSlats = /** @class */ (function (_super) {
  588. __extends(TimelineSlats, _super);
  589. function TimelineSlats(parentEl) {
  590. var _this = _super.call(this) || this;
  591. parentEl.appendChild(_this.el = core.createElement('div', { className: 'fc-slats' }));
  592. return _this;
  593. }
  594. TimelineSlats.prototype.destroy = function () {
  595. core.removeElement(this.el);
  596. _super.prototype.destroy.call(this);
  597. };
  598. TimelineSlats.prototype.render = function (props) {
  599. this.renderDates(props.tDateProfile);
  600. };
  601. TimelineSlats.prototype.renderDates = function (tDateProfile) {
  602. var _a = this.context, calendar = _a.calendar, view = _a.view, theme = _a.theme, dateEnv = _a.dateEnv;
  603. var slotDates = tDateProfile.slotDates, isWeekStarts = tDateProfile.isWeekStarts;
  604. var html = '<table class="' + theme.getClass('tableGrid') + '">' +
  605. '<colgroup>';
  606. for (var i = 0; i < slotDates.length; i++) {
  607. html += '<col/>';
  608. }
  609. html += '</colgroup>';
  610. html += '<tbody><tr>';
  611. for (var i = 0; i < slotDates.length; i++) {
  612. html += this.slatCellHtml(slotDates[i], isWeekStarts[i], tDateProfile);
  613. }
  614. html += '</tr></tbody></table>';
  615. this.el.innerHTML = html;
  616. this.slatColEls = core.findElements(this.el, 'col');
  617. this.slatEls = core.findElements(this.el, 'td');
  618. for (var i = 0; i < slotDates.length; i++) {
  619. calendar.publiclyTrigger('dayRender', [
  620. {
  621. date: dateEnv.toDate(slotDates[i]),
  622. el: this.slatEls[i],
  623. view: view
  624. }
  625. ]);
  626. }
  627. this.outerCoordCache = new core.PositionCache(this.el, this.slatEls, true, // isHorizontal
  628. false // isVertical
  629. );
  630. // for the inner divs within the slats
  631. // used for event rendering and scrollTime, to disregard slat border
  632. this.innerCoordCache = new core.PositionCache(this.el, core.findChildren(this.slatEls, 'div'), true, // isHorizontal
  633. false // isVertical
  634. );
  635. };
  636. TimelineSlats.prototype.slatCellHtml = function (date, isEm, tDateProfile) {
  637. var _a = this.context, theme = _a.theme, dateEnv = _a.dateEnv;
  638. var classes;
  639. if (tDateProfile.isTimeScale) {
  640. classes = [];
  641. classes.push(core.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval)) ?
  642. 'fc-major' :
  643. 'fc-minor');
  644. }
  645. else {
  646. classes = core.getDayClasses(date, this.props.dateProfile, this.context);
  647. classes.push('fc-day');
  648. }
  649. classes.unshift(theme.getClass('widgetContent'));
  650. if (isEm) {
  651. classes.push('fc-em-cell');
  652. }
  653. return '<td class="' + classes.join(' ') + '"' +
  654. ' data-date="' + dateEnv.formatIso(date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' +
  655. '><div></div></td>';
  656. };
  657. TimelineSlats.prototype.updateSize = function () {
  658. this.outerCoordCache.build();
  659. this.innerCoordCache.build();
  660. };
  661. TimelineSlats.prototype.positionToHit = function (leftPosition) {
  662. var outerCoordCache = this.outerCoordCache;
  663. var _a = this.context, dateEnv = _a.dateEnv, isRtl = _a.isRtl;
  664. var tDateProfile = this.props.tDateProfile;
  665. var slatIndex = outerCoordCache.leftToIndex(leftPosition);
  666. if (slatIndex != null) {
  667. // somewhat similar to what TimeGrid does. consolidate?
  668. var slatWidth = outerCoordCache.getWidth(slatIndex);
  669. var partial = isRtl ?
  670. (outerCoordCache.rights[slatIndex] - leftPosition) / slatWidth :
  671. (leftPosition - outerCoordCache.lefts[slatIndex]) / slatWidth;
  672. var localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot);
  673. var start = dateEnv.add(tDateProfile.slotDates[slatIndex], core.multiplyDuration(tDateProfile.snapDuration, localSnapIndex));
  674. var end = dateEnv.add(start, tDateProfile.snapDuration);
  675. return {
  676. dateSpan: {
  677. range: { start: start, end: end },
  678. allDay: !this.props.tDateProfile.isTimeScale
  679. },
  680. dayEl: this.slatColEls[slatIndex],
  681. left: outerCoordCache.lefts[slatIndex],
  682. right: outerCoordCache.rights[slatIndex]
  683. };
  684. }
  685. return null;
  686. };
  687. return TimelineSlats;
  688. }(core.Component));
  689. var MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours
  690. var MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour
  691. var MAX_AUTO_CELLS = 200; // allows 4-days to have a :30 slot duration
  692. core.config.MAX_TIMELINE_SLOTS = 1000;
  693. // potential nice values for slot-duration and interval-duration
  694. var STOCK_SUB_DURATIONS = [
  695. { years: 1 },
  696. { months: 1 },
  697. { days: 1 },
  698. { hours: 1 },
  699. { minutes: 30 },
  700. { minutes: 15 },
  701. { minutes: 10 },
  702. { minutes: 5 },
  703. { minutes: 1 },
  704. { seconds: 30 },
  705. { seconds: 15 },
  706. { seconds: 10 },
  707. { seconds: 5 },
  708. { seconds: 1 },
  709. { milliseconds: 500 },
  710. { milliseconds: 100 },
  711. { milliseconds: 10 },
  712. { milliseconds: 1 }
  713. ];
  714. function buildTimelineDateProfile(dateProfile, dateEnv, allOptions, dateProfileGenerator) {
  715. var tDateProfile = {
  716. labelInterval: queryDurationOption(allOptions, 'slotLabelInterval'),
  717. slotDuration: queryDurationOption(allOptions, 'slotDuration')
  718. };
  719. validateLabelAndSlot(tDateProfile, dateProfile, dateEnv); // validate after computed grid duration
  720. ensureLabelInterval(tDateProfile, dateProfile, dateEnv);
  721. ensureSlotDuration(tDateProfile, dateProfile, dateEnv);
  722. var input = allOptions.slotLabelFormat;
  723. var rawFormats = Array.isArray(input) ?
  724. input
  725. : (input != null) ?
  726. [input]
  727. :
  728. computeHeaderFormats(tDateProfile, dateProfile, dateEnv, allOptions);
  729. tDateProfile.headerFormats = rawFormats.map(function (rawFormat) {
  730. return core.createFormatter(rawFormat);
  731. });
  732. tDateProfile.isTimeScale = Boolean(tDateProfile.slotDuration.milliseconds);
  733. var largeUnit = null;
  734. if (!tDateProfile.isTimeScale) {
  735. var slotUnit = core.greatestDurationDenominator(tDateProfile.slotDuration).unit;
  736. if (/year|month|week/.test(slotUnit)) {
  737. largeUnit = slotUnit;
  738. }
  739. }
  740. tDateProfile.largeUnit = largeUnit;
  741. tDateProfile.emphasizeWeeks =
  742. core.isSingleDay(tDateProfile.slotDuration) &&
  743. currentRangeAs('weeks', dateProfile, dateEnv) >= 2 &&
  744. !allOptions.businessHours;
  745. /*
  746. console.log('label interval =', timelineView.labelInterval.humanize())
  747. console.log('slot duration =', timelineView.slotDuration.humanize())
  748. console.log('header formats =', timelineView.headerFormats)
  749. console.log('isTimeScale', timelineView.isTimeScale)
  750. console.log('largeUnit', timelineView.largeUnit)
  751. */
  752. var rawSnapDuration = allOptions.snapDuration;
  753. var snapDuration;
  754. var snapsPerSlot;
  755. if (rawSnapDuration) {
  756. snapDuration = core.createDuration(rawSnapDuration);
  757. snapsPerSlot = core.wholeDivideDurations(tDateProfile.slotDuration, snapDuration);
  758. // ^ TODO: warning if not whole?
  759. }
  760. if (snapsPerSlot == null) {
  761. snapDuration = tDateProfile.slotDuration;
  762. snapsPerSlot = 1;
  763. }
  764. tDateProfile.snapDuration = snapDuration;
  765. tDateProfile.snapsPerSlot = snapsPerSlot;
  766. // more...
  767. var timeWindowMs = core.asRoughMs(dateProfile.maxTime) - core.asRoughMs(dateProfile.minTime);
  768. // TODO: why not use normalizeRange!?
  769. var normalizedStart = normalizeDate(dateProfile.renderRange.start, tDateProfile, dateEnv);
  770. var normalizedEnd = normalizeDate(dateProfile.renderRange.end, tDateProfile, dateEnv);
  771. // apply minTime/maxTime
  772. // TODO: View should be responsible.
  773. if (tDateProfile.isTimeScale) {
  774. normalizedStart = dateEnv.add(normalizedStart, dateProfile.minTime);
  775. normalizedEnd = dateEnv.add(core.addDays(normalizedEnd, -1), dateProfile.maxTime);
  776. }
  777. tDateProfile.timeWindowMs = timeWindowMs;
  778. tDateProfile.normalizedRange = { start: normalizedStart, end: normalizedEnd };
  779. var slotDates = [];
  780. var date = normalizedStart;
  781. while (date < normalizedEnd) {
  782. if (isValidDate(date, tDateProfile, dateProfile, dateProfileGenerator)) {
  783. slotDates.push(date);
  784. }
  785. date = dateEnv.add(date, tDateProfile.slotDuration);
  786. }
  787. tDateProfile.slotDates = slotDates;
  788. // more...
  789. var snapIndex = -1;
  790. var snapDiff = 0; // index of the diff :(
  791. var snapDiffToIndex = [];
  792. var snapIndexToDiff = [];
  793. date = normalizedStart;
  794. while (date < normalizedEnd) {
  795. if (isValidDate(date, tDateProfile, dateProfile, dateProfileGenerator)) {
  796. snapIndex++;
  797. snapDiffToIndex.push(snapIndex);
  798. snapIndexToDiff.push(snapDiff);
  799. }
  800. else {
  801. snapDiffToIndex.push(snapIndex + 0.5);
  802. }
  803. date = dateEnv.add(date, tDateProfile.snapDuration);
  804. snapDiff++;
  805. }
  806. tDateProfile.snapDiffToIndex = snapDiffToIndex;
  807. tDateProfile.snapIndexToDiff = snapIndexToDiff;
  808. tDateProfile.snapCnt = snapIndex + 1; // is always one behind
  809. tDateProfile.slotCnt = tDateProfile.snapCnt / tDateProfile.snapsPerSlot;
  810. // more...
  811. tDateProfile.isWeekStarts = buildIsWeekStarts(tDateProfile, dateEnv);
  812. tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv, allOptions);
  813. return tDateProfile;
  814. }
  815. /*
  816. snaps to appropriate unit
  817. */
  818. function normalizeDate(date, tDateProfile, dateEnv) {
  819. var normalDate = date;
  820. if (!tDateProfile.isTimeScale) {
  821. normalDate = core.startOfDay(normalDate);
  822. if (tDateProfile.largeUnit) {
  823. normalDate = dateEnv.startOf(normalDate, tDateProfile.largeUnit);
  824. }
  825. }
  826. return normalDate;
  827. }
  828. /*
  829. snaps to appropriate unit
  830. */
  831. function normalizeRange(range, tDateProfile, dateEnv) {
  832. if (!tDateProfile.isTimeScale) {
  833. range = core.computeVisibleDayRange(range);
  834. if (tDateProfile.largeUnit) {
  835. var dayRange = range; // preserve original result
  836. range = {
  837. start: dateEnv.startOf(range.start, tDateProfile.largeUnit),
  838. end: dateEnv.startOf(range.end, tDateProfile.largeUnit)
  839. };
  840. // if date is partially through the interval, or is in the same interval as the start,
  841. // make the exclusive end be the *next* interval
  842. if (range.end.valueOf() !== dayRange.end.valueOf() || range.end <= range.start) {
  843. range = {
  844. start: range.start,
  845. end: dateEnv.add(range.end, tDateProfile.slotDuration)
  846. };
  847. }
  848. }
  849. }
  850. return range;
  851. }
  852. function isValidDate(date, tDateProfile, dateProfile, dateProfileGenerator) {
  853. if (dateProfileGenerator.isHiddenDay(date)) {
  854. return false;
  855. }
  856. else if (tDateProfile.isTimeScale) {
  857. // determine if the time is within minTime/maxTime, which may have wacky values
  858. var day = core.startOfDay(date);
  859. var timeMs = date.valueOf() - day.valueOf();
  860. var ms = timeMs - core.asRoughMs(dateProfile.minTime); // milliseconds since minTime
  861. ms = ((ms % 86400000) + 86400000) % 86400000; // make negative values wrap to 24hr clock
  862. return ms < tDateProfile.timeWindowMs; // before the maxTime?
  863. }
  864. else {
  865. return true;
  866. }
  867. }
  868. function queryDurationOption(allOptions, name) {
  869. var input = allOptions[name];
  870. if (input != null) {
  871. return core.createDuration(input);
  872. }
  873. }
  874. function validateLabelAndSlot(tDateProfile, dateProfile, dateEnv) {
  875. var currentRange = dateProfile.currentRange;
  876. // make sure labelInterval doesn't exceed the max number of cells
  877. if (tDateProfile.labelInterval) {
  878. var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.labelInterval);
  879. if (labelCnt > core.config.MAX_TIMELINE_SLOTS) {
  880. console.warn('slotLabelInterval results in too many cells');
  881. tDateProfile.labelInterval = null;
  882. }
  883. }
  884. // make sure slotDuration doesn't exceed the maximum number of cells
  885. if (tDateProfile.slotDuration) {
  886. var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.slotDuration);
  887. if (slotCnt > core.config.MAX_TIMELINE_SLOTS) {
  888. console.warn('slotDuration results in too many cells');
  889. tDateProfile.slotDuration = null;
  890. }
  891. }
  892. // make sure labelInterval is a multiple of slotDuration
  893. if (tDateProfile.labelInterval && tDateProfile.slotDuration) {
  894. var slotsPerLabel = core.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
  895. if (slotsPerLabel === null || slotsPerLabel < 1) {
  896. console.warn('slotLabelInterval must be a multiple of slotDuration');
  897. tDateProfile.slotDuration = null;
  898. }
  899. }
  900. }
  901. function ensureLabelInterval(tDateProfile, dateProfile, dateEnv) {
  902. var currentRange = dateProfile.currentRange;
  903. var labelInterval = tDateProfile.labelInterval;
  904. if (!labelInterval) {
  905. // compute based off the slot duration
  906. // find the largest label interval with an acceptable slots-per-label
  907. var input = void 0;
  908. if (tDateProfile.slotDuration) {
  909. for (var _i = 0, STOCK_SUB_DURATIONS_1 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_1.length; _i++) {
  910. input = STOCK_SUB_DURATIONS_1[_i];
  911. var tryLabelInterval = core.createDuration(input);
  912. var slotsPerLabel = core.wholeDivideDurations(tryLabelInterval, tDateProfile.slotDuration);
  913. if (slotsPerLabel !== null && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
  914. labelInterval = tryLabelInterval;
  915. break;
  916. }
  917. }
  918. // use the slot duration as a last resort
  919. if (!labelInterval) {
  920. labelInterval = tDateProfile.slotDuration;
  921. }
  922. // compute based off the view's duration
  923. // find the largest label interval that yields the minimum number of labels
  924. }
  925. else {
  926. for (var _a = 0, STOCK_SUB_DURATIONS_2 = STOCK_SUB_DURATIONS; _a < STOCK_SUB_DURATIONS_2.length; _a++) {
  927. input = STOCK_SUB_DURATIONS_2[_a];
  928. labelInterval = core.createDuration(input);
  929. var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, labelInterval);
  930. if (labelCnt >= MIN_AUTO_LABELS) {
  931. break;
  932. }
  933. }
  934. }
  935. tDateProfile.labelInterval = labelInterval;
  936. }
  937. return labelInterval;
  938. }
  939. function ensureSlotDuration(tDateProfile, dateProfile, dateEnv) {
  940. var currentRange = dateProfile.currentRange;
  941. var slotDuration = tDateProfile.slotDuration;
  942. if (!slotDuration) {
  943. var labelInterval = ensureLabelInterval(tDateProfile, dateProfile, dateEnv); // will compute if necessary
  944. // compute based off the label interval
  945. // find the largest slot duration that is different from labelInterval, but still acceptable
  946. for (var _i = 0, STOCK_SUB_DURATIONS_3 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_3.length; _i++) {
  947. var input = STOCK_SUB_DURATIONS_3[_i];
  948. var trySlotDuration = core.createDuration(input);
  949. var slotsPerLabel = core.wholeDivideDurations(labelInterval, trySlotDuration);
  950. if (slotsPerLabel !== null && slotsPerLabel > 1 && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
  951. slotDuration = trySlotDuration;
  952. break;
  953. }
  954. }
  955. // only allow the value if it won't exceed the view's # of slots limit
  956. if (slotDuration) {
  957. var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, slotDuration);
  958. if (slotCnt > MAX_AUTO_CELLS) {
  959. slotDuration = null;
  960. }
  961. }
  962. // use the label interval as a last resort
  963. if (!slotDuration) {
  964. slotDuration = labelInterval;
  965. }
  966. tDateProfile.slotDuration = slotDuration;
  967. }
  968. return slotDuration;
  969. }
  970. function computeHeaderFormats(tDateProfile, dateProfile, dateEnv, allOptions) {
  971. var format1;
  972. var format2;
  973. var labelInterval = tDateProfile.labelInterval;
  974. var unit = core.greatestDurationDenominator(labelInterval).unit;
  975. var weekNumbersVisible = allOptions.weekNumbers;
  976. var format0 = (format1 = (format2 = null));
  977. // NOTE: weekNumber computation function wont work
  978. if ((unit === 'week') && !weekNumbersVisible) {
  979. unit = 'day';
  980. }
  981. switch (unit) {
  982. case 'year':
  983. format0 = { year: 'numeric' }; // '2015'
  984. break;
  985. case 'month':
  986. if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
  987. format0 = { year: 'numeric' }; // '2015'
  988. }
  989. format1 = { month: 'short' }; // 'Jan'
  990. break;
  991. case 'week':
  992. if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
  993. format0 = { year: 'numeric' }; // '2015'
  994. }
  995. format1 = { week: 'narrow' }; // 'Wk4'
  996. break;
  997. case 'day':
  998. if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
  999. format0 = { year: 'numeric', month: 'long' }; // 'January 2014'
  1000. }
  1001. else if (currentRangeAs('months', dateProfile, dateEnv) > 1) {
  1002. format0 = { month: 'long' }; // 'January'
  1003. }
  1004. if (weekNumbersVisible) {
  1005. format1 = { week: 'short' }; // 'Wk 4'
  1006. }
  1007. format2 = { weekday: 'narrow', day: 'numeric' }; // 'Su 9'
  1008. break;
  1009. case 'hour':
  1010. if (weekNumbersVisible) {
  1011. format0 = { week: 'short' }; // 'Wk 4'
  1012. }
  1013. if (currentRangeAs('days', dateProfile, dateEnv) > 1) {
  1014. format1 = { weekday: 'short', day: 'numeric', month: 'numeric', omitCommas: true }; // Sat 4/7
  1015. }
  1016. format2 = {
  1017. hour: 'numeric',
  1018. minute: '2-digit',
  1019. omitZeroMinute: true,
  1020. meridiem: 'short'
  1021. };
  1022. break;
  1023. case 'minute':
  1024. // sufficiently large number of different minute cells?
  1025. if ((core.asRoughMinutes(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
  1026. format0 = {
  1027. hour: 'numeric',
  1028. meridiem: 'short'
  1029. };
  1030. format1 = function (params) {
  1031. return ':' + core.padStart(params.date.minute, 2); // ':30'
  1032. };
  1033. }
  1034. else {
  1035. format0 = {
  1036. hour: 'numeric',
  1037. minute: 'numeric',
  1038. meridiem: 'short'
  1039. };
  1040. }
  1041. break;
  1042. case 'second':
  1043. // sufficiently large number of different second cells?
  1044. if ((core.asRoughSeconds(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
  1045. format0 = { hour: 'numeric', minute: '2-digit', meridiem: 'lowercase' }; // '8:30 PM'
  1046. format1 = function (params) {
  1047. return ':' + core.padStart(params.date.second, 2); // ':30'
  1048. };
  1049. }
  1050. else {
  1051. format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
  1052. }
  1053. break;
  1054. case 'millisecond':
  1055. format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
  1056. format1 = function (params) {
  1057. return '.' + core.padStart(params.millisecond, 3);
  1058. };
  1059. break;
  1060. }
  1061. return [].concat(format0 || [], format1 || [], format2 || []);
  1062. }
  1063. // Compute the number of the give units in the "current" range.
  1064. // Won't go more precise than days.
  1065. // Will return `0` if there's not a clean whole interval.
  1066. function currentRangeAs(unit, dateProfile, dateEnv) {
  1067. var range = dateProfile.currentRange;
  1068. var res = null;
  1069. if (unit === 'years') {
  1070. res = dateEnv.diffWholeYears(range.start, range.end);
  1071. }
  1072. else if (unit === 'months') {
  1073. res = dateEnv.diffWholeMonths(range.start, range.end);
  1074. }
  1075. else if (unit === 'weeks') {
  1076. res = dateEnv.diffWholeMonths(range.start, range.end);
  1077. }
  1078. else if (unit === 'days') {
  1079. res = core.diffWholeDays(range.start, range.end);
  1080. }
  1081. return res || 0;
  1082. }
  1083. function buildIsWeekStarts(tDateProfile, dateEnv) {
  1084. var slotDates = tDateProfile.slotDates, emphasizeWeeks = tDateProfile.emphasizeWeeks;
  1085. var prevWeekNumber = null;
  1086. var isWeekStarts = [];
  1087. for (var _i = 0, slotDates_1 = slotDates; _i < slotDates_1.length; _i++) {
  1088. var slotDate = slotDates_1[_i];
  1089. var weekNumber = dateEnv.computeWeekNumber(slotDate);
  1090. var isWeekStart = emphasizeWeeks && (prevWeekNumber !== null) && (prevWeekNumber !== weekNumber);
  1091. prevWeekNumber = weekNumber;
  1092. isWeekStarts.push(isWeekStart);
  1093. }
  1094. return isWeekStarts;
  1095. }
  1096. function buildCellRows(tDateProfile, dateEnv, allOptions) {
  1097. var slotDates = tDateProfile.slotDates;
  1098. var formats = tDateProfile.headerFormats;
  1099. var cellRows = formats.map(function (format) { return []; }); // indexed by row,col
  1100. // specifically for navclicks
  1101. var rowUnits = formats.map(function (format) {
  1102. return format.getLargestUnit ? format.getLargestUnit() : null;
  1103. });
  1104. // builds cellRows and slotCells
  1105. for (var i = 0; i < slotDates.length; i++) {
  1106. var date = slotDates[i];
  1107. var isWeekStart = tDateProfile.isWeekStarts[i];
  1108. for (var row = 0; row < formats.length; row++) {
  1109. var format = formats[row];
  1110. var rowCells = cellRows[row];
  1111. var leadingCell = rowCells[rowCells.length - 1];
  1112. var isSuperRow = (formats.length > 1) && (row < (formats.length - 1)); // more than one row and not the last
  1113. var newCell = null;
  1114. if (isSuperRow) {
  1115. var text = dateEnv.format(date, format);
  1116. if (!leadingCell || (leadingCell.text !== text)) {
  1117. newCell = buildCellObject(date, text, rowUnits[row], allOptions, dateEnv);
  1118. }
  1119. else {
  1120. leadingCell.colspan += 1;
  1121. }
  1122. }
  1123. else {
  1124. if (!leadingCell ||
  1125. core.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval))) {
  1126. var text = dateEnv.format(date, format);
  1127. newCell = buildCellObject(date, text, rowUnits[row], allOptions, dateEnv);
  1128. }
  1129. else {
  1130. leadingCell.colspan += 1;
  1131. }
  1132. }
  1133. if (newCell) {
  1134. newCell.weekStart = isWeekStart;
  1135. rowCells.push(newCell);
  1136. }
  1137. }
  1138. }
  1139. return cellRows;
  1140. }
  1141. function buildCellObject(date, text, rowUnit, allOptions, dateEnv) {
  1142. var spanHtml = core.buildGotoAnchorHtml(allOptions, dateEnv, {
  1143. date: date,
  1144. type: rowUnit,
  1145. forceOff: !rowUnit
  1146. }, {
  1147. 'class': 'fc-cell-text'
  1148. }, core.htmlEscape(text));
  1149. return { text: text, spanHtml: spanHtml, date: date, colspan: 1, isWeekStart: false };
  1150. }
  1151. var TimelineNowIndicator = /** @class */ (function () {
  1152. function TimelineNowIndicator(headParent, bodyParent) {
  1153. this.headParent = headParent;
  1154. this.bodyParent = bodyParent;
  1155. }
  1156. TimelineNowIndicator.prototype.render = function (coord, isRtl) {
  1157. var styleProps = isRtl ? { right: -coord } : { left: coord };
  1158. this.headParent.appendChild(this.arrowEl = core.createElement('div', {
  1159. className: 'fc-now-indicator fc-now-indicator-arrow',
  1160. style: styleProps
  1161. }));
  1162. this.bodyParent.appendChild(this.lineEl = core.createElement('div', {
  1163. className: 'fc-now-indicator fc-now-indicator-line',
  1164. style: styleProps
  1165. }));
  1166. };
  1167. TimelineNowIndicator.prototype.unrender = function () {
  1168. if (this.arrowEl) {
  1169. core.removeElement(this.arrowEl);
  1170. }
  1171. if (this.lineEl) {
  1172. core.removeElement(this.lineEl);
  1173. }
  1174. };
  1175. return TimelineNowIndicator;
  1176. }());
  1177. var STICKY_PROP_VAL = computeStickyPropVal(); // if null, means not supported at all
  1178. var IS_MS_EDGE = /Edge/.test(navigator.userAgent);
  1179. var IS_SAFARI = STICKY_PROP_VAL === '-webkit-sticky'; // good b/c doesn't confuse chrome
  1180. var STICKY_CLASSNAME = 'fc-sticky';
  1181. /*
  1182. useful beyond the native position:sticky for these reasons:
  1183. - support in IE11
  1184. - nice centering support
  1185. */
  1186. var StickyScroller = /** @class */ (function () {
  1187. function StickyScroller(scroller, isRtl, isVertical) {
  1188. var _this = this;
  1189. this.usingRelative = null;
  1190. /*
  1191. known bug: called twice on init. problem when mixing with ScrollJoiner
  1192. */
  1193. this.updateSize = function () {
  1194. var els = Array.prototype.slice.call(_this.scroller.canvas.el.querySelectorAll('.' + STICKY_CLASSNAME));
  1195. var elGeoms = _this.queryElGeoms(els);
  1196. var viewportWidth = _this.scroller.el.clientWidth;
  1197. if (_this.usingRelative) {
  1198. var elDestinations = _this.computeElDestinations(elGeoms, viewportWidth); // read before prepPositioning
  1199. assignRelativePositions(els, elGeoms, elDestinations);
  1200. }
  1201. else {
  1202. assignStickyPositions(els, elGeoms, viewportWidth);
  1203. }
  1204. };
  1205. this.scroller = scroller;
  1206. this.usingRelative =
  1207. !STICKY_PROP_VAL || // IE11
  1208. (IS_MS_EDGE && isRtl) || // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/18883305/
  1209. ((IS_MS_EDGE || IS_SAFARI) && isVertical); // because doesn't work with rowspan in tables, our only vertial use
  1210. if (this.usingRelative) {
  1211. scroller.on('scrollEnd', this.updateSize);
  1212. }
  1213. }
  1214. StickyScroller.prototype.destroy = function () {
  1215. this.scroller.off('scrollEnd', this.updateSize);
  1216. };
  1217. StickyScroller.prototype.queryElGeoms = function (els) {
  1218. var canvasOrigin = this.scroller.canvas.el.getBoundingClientRect();
  1219. var elGeoms = [];
  1220. for (var _i = 0, els_1 = els; _i < els_1.length; _i++) {
  1221. var el = els_1[_i];
  1222. var parentBound = core.translateRect(el.parentNode.getBoundingClientRect(), -canvasOrigin.left, -canvasOrigin.top);
  1223. var elRect = el.getBoundingClientRect();
  1224. var computedStyles = window.getComputedStyle(el);
  1225. var computedTextAlign = window.getComputedStyle(el.parentNode).textAlign; // ask the parent
  1226. var intendedTextAlign = computedTextAlign;
  1227. var naturalBound = null;
  1228. if (computedStyles.position !== 'sticky') {
  1229. naturalBound = core.translateRect(elRect, -canvasOrigin.left - (parseFloat(computedStyles.left) || 0), // could be 'auto'
  1230. -canvasOrigin.top - (parseFloat(computedStyles.top) || 0));
  1231. }
  1232. if (el.hasAttribute('data-sticky-center')) {
  1233. intendedTextAlign = 'center';
  1234. }
  1235. elGeoms.push({
  1236. parentBound: parentBound,
  1237. naturalBound: naturalBound,
  1238. elWidth: elRect.width,
  1239. elHeight: elRect.height,
  1240. computedTextAlign: computedTextAlign,
  1241. intendedTextAlign: intendedTextAlign
  1242. });
  1243. }
  1244. return elGeoms;
  1245. };
  1246. StickyScroller.prototype.computeElDestinations = function (elGeoms, viewportWidth) {
  1247. var viewportLeft = this.scroller.getScrollFromLeft();
  1248. var viewportTop = this.scroller.getScrollTop();
  1249. var viewportRight = viewportLeft + viewportWidth;
  1250. return elGeoms.map(function (elGeom) {
  1251. var elWidth = elGeom.elWidth, elHeight = elGeom.elHeight, parentBound = elGeom.parentBound, naturalBound = elGeom.naturalBound;
  1252. var destLeft; // relative to canvas topleft
  1253. var destTop; // "
  1254. switch (elGeom.intendedTextAlign) {
  1255. case 'left':
  1256. destLeft = viewportLeft;
  1257. break;
  1258. case 'right':
  1259. destLeft = viewportRight - elWidth;
  1260. break;
  1261. case 'center':
  1262. destLeft = (viewportLeft + viewportRight) / 2 - elWidth / 2;
  1263. break;
  1264. }
  1265. destLeft = Math.min(destLeft, parentBound.right - elWidth);
  1266. destLeft = Math.max(destLeft, parentBound.left);
  1267. destTop = viewportTop;
  1268. destTop = Math.min(destTop, parentBound.bottom - elHeight);
  1269. destTop = Math.max(destTop, naturalBound.top); // better to use natural top for upper bound
  1270. return { left: destLeft, top: destTop };
  1271. });
  1272. };
  1273. return StickyScroller;
  1274. }());
  1275. function assignRelativePositions(els, elGeoms, elDestinations) {
  1276. els.forEach(function (el, i) {
  1277. var naturalBound = elGeoms[i].naturalBound;
  1278. core.applyStyle(el, {
  1279. position: 'relative',
  1280. left: elDestinations[i].left - naturalBound.left,
  1281. top: elDestinations[i].top - naturalBound.top
  1282. });
  1283. });
  1284. }
  1285. function assignStickyPositions(els, elGeoms, viewportWidth) {
  1286. els.forEach(function (el, i) {
  1287. var stickyLeft = 0;
  1288. if (elGeoms[i].intendedTextAlign === 'center') {
  1289. stickyLeft = (viewportWidth - elGeoms[i].elWidth) / 2;
  1290. // needs to be forced to left?
  1291. if (elGeoms[i].computedTextAlign === 'center') {
  1292. el.setAttribute('data-sticky-center', '') // remember for next queryElGeoms
  1293. ;
  1294. el.parentNode.style.textAlign = 'left';
  1295. }
  1296. }
  1297. core.applyStyle(el, {
  1298. position: STICKY_PROP_VAL,
  1299. left: stickyLeft,
  1300. right: 0,
  1301. top: 0
  1302. });
  1303. });
  1304. }
  1305. function computeStickyPropVal() {
  1306. var el = core.htmlToElement('<div style="position:-webkit-sticky;position:sticky"></div>');
  1307. var val = el.style.position;
  1308. if (val.indexOf('sticky') !== -1) {
  1309. return val;
  1310. }
  1311. else {
  1312. return null;
  1313. }
  1314. }
  1315. var TimeAxis = /** @class */ (function (_super) {
  1316. __extends(TimeAxis, _super);
  1317. function TimeAxis(headerContainerEl, bodyContainerEl) {
  1318. var _this = _super.call(this) || this;
  1319. _this.renderSkeleton = core.memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
  1320. _this.layout = new HeaderBodyLayout(headerContainerEl, bodyContainerEl, 'auto');
  1321. return _this;
  1322. }
  1323. TimeAxis.prototype.render = function (props, context) {
  1324. var tDateProfile = this.tDateProfile =
  1325. buildTimelineDateProfile(props.dateProfile, context.dateEnv, context.options, props.dateProfileGenerator); // TODO: cache
  1326. this.renderSkeleton(context);
  1327. this.header.receiveProps({
  1328. dateProfile: props.dateProfile,
  1329. tDateProfile: tDateProfile
  1330. }, context);
  1331. this.slats.receiveProps({
  1332. dateProfile: props.dateProfile,
  1333. tDateProfile: tDateProfile
  1334. }, context);
  1335. };
  1336. TimeAxis.prototype.destroy = function () {
  1337. this.renderSkeleton.unrender();
  1338. this.layout.destroy();
  1339. _super.prototype.destroy.call(this);
  1340. };
  1341. TimeAxis.prototype._renderSkeleton = function (context) {
  1342. var layout = this.layout;
  1343. var headerEnhancedScroller = layout.headerScroller.enhancedScroll;
  1344. var bodyEnhancedScroller = layout.bodyScroller.enhancedScroll;
  1345. // needs to go after layout, which has ScrollJoiner
  1346. this.headStickyScroller = new StickyScroller(headerEnhancedScroller, context.isRtl, false); // isVertical=false
  1347. this.bodyStickyScroller = new StickyScroller(bodyEnhancedScroller, context.isRtl, false); // isVertical=false
  1348. this.header = new TimelineHeader(headerEnhancedScroller.canvas.contentEl);
  1349. this.slats = new TimelineSlats(bodyEnhancedScroller.canvas.bgEl);
  1350. this.nowIndicator = new TimelineNowIndicator(headerEnhancedScroller.canvas.el, bodyEnhancedScroller.canvas.el);
  1351. };
  1352. TimeAxis.prototype._unrenderSkeleton = function () {
  1353. this.header.destroy();
  1354. this.slats.destroy();
  1355. this.nowIndicator.unrender();
  1356. this.headStickyScroller.destroy();
  1357. this.bodyStickyScroller.destroy();
  1358. };
  1359. // Now Indicator
  1360. // ------------------------------------------------------------------------------------------
  1361. TimeAxis.prototype.getNowIndicatorUnit = function (dateProfile, dateProfileGenerator) {
  1362. var context = this.context;
  1363. // yuck
  1364. var tDateProfile = this.tDateProfile =
  1365. buildTimelineDateProfile(dateProfile, context.dateEnv, context.options, dateProfileGenerator); // TODO: cache
  1366. if (tDateProfile.isTimeScale) {
  1367. return core.greatestDurationDenominator(tDateProfile.slotDuration).unit;
  1368. }
  1369. };
  1370. // will only execute if isTimeScale
  1371. TimeAxis.prototype.renderNowIndicator = function (date) {
  1372. if (core.rangeContainsMarker(this.tDateProfile.normalizedRange, date)) {
  1373. this.nowIndicator.render(this.dateToCoord(date), this.context.isRtl);
  1374. }
  1375. };
  1376. // will only execute if isTimeScale
  1377. TimeAxis.prototype.unrenderNowIndicator = function () {
  1378. this.nowIndicator.unrender();
  1379. };
  1380. // Sizing
  1381. // ------------------------------------------------------------------------------------------
  1382. TimeAxis.prototype.updateSize = function (isResize, totalHeight, isAuto) {
  1383. this.applySlotWidth(this.computeSlotWidth());
  1384. // adjusts gutters. do after slot widths set
  1385. this.layout.setHeight(totalHeight, isAuto);
  1386. // pretty much just queries coords. do last
  1387. this.slats.updateSize();
  1388. };
  1389. TimeAxis.prototype.updateStickyScrollers = function () {
  1390. this.headStickyScroller.updateSize();
  1391. this.bodyStickyScroller.updateSize();
  1392. };
  1393. TimeAxis.prototype.computeSlotWidth = function () {
  1394. var slotWidth = this.context.options.slotWidth || '';
  1395. if (slotWidth === '') {
  1396. slotWidth = this.computeDefaultSlotWidth(this.tDateProfile);
  1397. }
  1398. return slotWidth;
  1399. };
  1400. TimeAxis.prototype.computeDefaultSlotWidth = function (tDateProfile) {
  1401. var maxInnerWidth = 0; // TODO: harness core's `matchCellWidths` for this
  1402. this.header.innerEls.forEach(function (innerEl, i) {
  1403. maxInnerWidth = Math.max(maxInnerWidth, innerEl.getBoundingClientRect().width);
  1404. });
  1405. var headingCellWidth = Math.ceil(maxInnerWidth) + 1; // assume no padding, and one pixel border
  1406. // in TimelineView.defaults we ensured that labelInterval is an interval of slotDuration
  1407. // TODO: rename labelDuration?
  1408. var slotsPerLabel = core.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
  1409. var slotWidth = Math.ceil(headingCellWidth / slotsPerLabel);
  1410. var minWidth = window.getComputedStyle(this.header.slatColEls[0]).minWidth;
  1411. if (minWidth) {
  1412. minWidth = parseInt(minWidth, 10);
  1413. if (minWidth) {
  1414. slotWidth = Math.max(slotWidth, minWidth);
  1415. }
  1416. }
  1417. return slotWidth;
  1418. };
  1419. TimeAxis.prototype.applySlotWidth = function (slotWidth) {
  1420. var _a = this, layout = _a.layout, tDateProfile = _a.tDateProfile;
  1421. var containerWidth = '';
  1422. var containerMinWidth = '';
  1423. var nonLastSlotWidth = '';
  1424. if (slotWidth !== '') {
  1425. slotWidth = Math.round(slotWidth);
  1426. containerWidth = slotWidth * tDateProfile.slotDates.length;
  1427. containerMinWidth = '';
  1428. nonLastSlotWidth = slotWidth;
  1429. var availableWidth = layout.bodyScroller.enhancedScroll.getClientWidth();
  1430. if (availableWidth > containerWidth) {
  1431. containerMinWidth = availableWidth;
  1432. containerWidth = '';
  1433. nonLastSlotWidth = Math.floor(availableWidth / tDateProfile.slotDates.length);
  1434. }
  1435. }
  1436. layout.headerScroller.enhancedScroll.canvas.setWidth(containerWidth);
  1437. layout.headerScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth);
  1438. layout.bodyScroller.enhancedScroll.canvas.setWidth(containerWidth);
  1439. layout.bodyScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth);
  1440. if (nonLastSlotWidth !== '') {
  1441. this.header.slatColEls.slice(0, -1).concat(this.slats.slatColEls.slice(0, -1)).forEach(function (el) {
  1442. el.style.width = nonLastSlotWidth + 'px';
  1443. el.style.minWidth = '0'; // prevent the browser from using the actual min-width (issue #6338)
  1444. });
  1445. }
  1446. };
  1447. // returned value is between 0 and the number of snaps
  1448. TimeAxis.prototype.computeDateSnapCoverage = function (date) {
  1449. var tDateProfile = this.tDateProfile;
  1450. var dateEnv = this.context.dateEnv;
  1451. var snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
  1452. if (snapDiff < 0) {
  1453. return 0;
  1454. }
  1455. else if (snapDiff >= tDateProfile.snapDiffToIndex.length) {
  1456. return tDateProfile.snapCnt;
  1457. }
  1458. else {
  1459. var snapDiffInt = Math.floor(snapDiff);
  1460. var snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt];
  1461. if (core.isInt(snapCoverage)) { // not an in-between value
  1462. snapCoverage += snapDiff - snapDiffInt; // add the remainder
  1463. }
  1464. else {
  1465. // a fractional value, meaning the date is not visible
  1466. // always round up in this case. works for start AND end dates in a range.
  1467. snapCoverage = Math.ceil(snapCoverage);
  1468. }
  1469. return snapCoverage;
  1470. }
  1471. };
  1472. // for LTR, results range from 0 to width of area
  1473. // for RTL, results range from negative width of area to 0
  1474. TimeAxis.prototype.dateToCoord = function (date) {
  1475. var tDateProfile = this.tDateProfile;
  1476. var snapCoverage = this.computeDateSnapCoverage(date);
  1477. var slotCoverage = snapCoverage / tDateProfile.snapsPerSlot;
  1478. var slotIndex = Math.floor(slotCoverage);
  1479. slotIndex = Math.min(slotIndex, tDateProfile.slotCnt - 1);
  1480. var partial = slotCoverage - slotIndex;
  1481. var _a = this.slats, innerCoordCache = _a.innerCoordCache, outerCoordCache = _a.outerCoordCache;
  1482. if (this.context.isRtl) {
  1483. return (outerCoordCache.rights[slotIndex] -
  1484. (innerCoordCache.getWidth(slotIndex) * partial)) - outerCoordCache.originClientRect.width;
  1485. }
  1486. else {
  1487. return (outerCoordCache.lefts[slotIndex] +
  1488. (innerCoordCache.getWidth(slotIndex) * partial));
  1489. }
  1490. };
  1491. TimeAxis.prototype.rangeToCoords = function (range) {
  1492. if (this.context.isRtl) {
  1493. return { right: this.dateToCoord(range.start), left: this.dateToCoord(range.end) };
  1494. }
  1495. else {
  1496. return { left: this.dateToCoord(range.start), right: this.dateToCoord(range.end) };
  1497. }
  1498. };
  1499. // Scrolling
  1500. // ------------------------------------------------------------------------------------------
  1501. TimeAxis.prototype.computeDateScroll = function (duration) {
  1502. var _a = this.context, dateEnv = _a.dateEnv, isRtl = _a.isRtl;
  1503. var dateProfile = this.props.dateProfile;
  1504. var left = 0;
  1505. if (dateProfile) {
  1506. left = this.dateToCoord(dateEnv.add(core.startOfDay(dateProfile.activeRange.start), // startOfDay needed?
  1507. duration));
  1508. // hack to overcome the left borders of non-first slat
  1509. if (!isRtl && left) {
  1510. left += 1;
  1511. }
  1512. }
  1513. return { left: left };
  1514. };
  1515. TimeAxis.prototype.queryDateScroll = function () {
  1516. var enhancedScroll = this.layout.bodyScroller.enhancedScroll;
  1517. return {
  1518. left: enhancedScroll.getScrollLeft()
  1519. };
  1520. };
  1521. TimeAxis.prototype.applyDateScroll = function (scroll) {
  1522. // TODO: lame we have to update both. use the scrolljoiner instead maybe
  1523. this.layout.bodyScroller.enhancedScroll.setScrollLeft(scroll.left || 0);
  1524. this.layout.headerScroller.enhancedScroll.setScrollLeft(scroll.left || 0);
  1525. };
  1526. return TimeAxis;
  1527. }(core.Component));
  1528. var TimelineLaneEventRenderer = /** @class */ (function (_super) {
  1529. __extends(TimelineLaneEventRenderer, _super);
  1530. function TimelineLaneEventRenderer(masterContainerEl, timeAxis) {
  1531. var _this = _super.call(this) || this;
  1532. _this.masterContainerEl = masterContainerEl;
  1533. _this.timeAxis = timeAxis;
  1534. return _this;
  1535. }
  1536. TimelineLaneEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
  1537. var context = this.context;
  1538. var eventRange = seg.eventRange;
  1539. var eventDef = eventRange.def;
  1540. var eventUi = eventRange.ui;
  1541. var isDraggable = core.computeEventDraggable(context, eventDef, eventUi);
  1542. var isResizableFromStart = seg.isStart && core.computeEventStartResizable(context, eventDef, eventUi);
  1543. var isResizableFromEnd = seg.isEnd && core.computeEventEndResizable(context, eventDef, eventUi);
  1544. var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo);
  1545. classes.unshift('fc-timeline-event', 'fc-h-event');
  1546. var timeText = this.getTimeText(eventRange);
  1547. return '<a class="' + classes.join(' ') + '" style="' + core.cssToStr(this.getSkinCss(eventUi)) + '"' +
  1548. (eventDef.url ?
  1549. ' href="' + core.htmlEscape(eventDef.url) + '"' :
  1550. '') +
  1551. '>' +
  1552. (timeText ?
  1553. '<span class="fc-time-wrap">' +
  1554. '<span class="fc-time">' +
  1555. core.htmlEscape(timeText) +
  1556. '</span>' +
  1557. '</span>'
  1558. :
  1559. '') +
  1560. '<span class="fc-title-wrap">' +
  1561. '<span class="fc-title fc-sticky">' +
  1562. (eventDef.title ? core.htmlEscape(eventDef.title) : '&nbsp;') +
  1563. '</span>' +
  1564. '</span>' +
  1565. (isResizableFromStart ?
  1566. '<div class="fc-resizer fc-start-resizer"></div>' :
  1567. '') +
  1568. (isResizableFromEnd ?
  1569. '<div class="fc-resizer fc-end-resizer"></div>' :
  1570. '') +
  1571. '</a>';
  1572. };
  1573. TimelineLaneEventRenderer.prototype.computeDisplayEventTime = function () {
  1574. return !this.timeAxis.tDateProfile.isTimeScale; // because times should be obvious via axis
  1575. };
  1576. TimelineLaneEventRenderer.prototype.computeDisplayEventEnd = function () {
  1577. return false;
  1578. };
  1579. // Computes a default event time formatting string if `timeFormat` is not explicitly defined
  1580. TimelineLaneEventRenderer.prototype.computeEventTimeFormat = function () {
  1581. return {
  1582. hour: 'numeric',
  1583. minute: '2-digit',
  1584. omitZeroMinute: true,
  1585. meridiem: 'narrow'
  1586. };
  1587. };
  1588. TimelineLaneEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
  1589. if (!this.el && this.masterContainerEl) {
  1590. this.el = core.createElement('div', { className: 'fc-event-container' });
  1591. if (mirrorInfo) {
  1592. this.el.classList.add('fc-mirror-container');
  1593. }
  1594. this.masterContainerEl.appendChild(this.el);
  1595. }
  1596. if (this.el) {
  1597. for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
  1598. var seg = segs_1[_i];
  1599. this.el.appendChild(seg.el);
  1600. }
  1601. }
  1602. };
  1603. TimelineLaneEventRenderer.prototype.detachSegs = function (segs) {
  1604. for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
  1605. var seg = segs_2[_i];
  1606. core.removeElement(seg.el);
  1607. }
  1608. };
  1609. // computes AND assigns (assigns the left/right at least). bad
  1610. TimelineLaneEventRenderer.prototype.computeSegSizes = function (segs) {
  1611. var timeAxis = this.timeAxis;
  1612. for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
  1613. var seg = segs_3[_i];
  1614. var coords = timeAxis.rangeToCoords(seg); // works because Seg has start/end
  1615. core.applyStyle(seg.el, {
  1616. left: (seg.left = coords.left),
  1617. right: -(seg.right = coords.right)
  1618. });
  1619. }
  1620. };
  1621. TimelineLaneEventRenderer.prototype.assignSegSizes = function (segs) {
  1622. if (!this.el) {
  1623. return;
  1624. }
  1625. // compute seg verticals
  1626. for (var _i = 0, segs_4 = segs; _i < segs_4.length; _i++) {
  1627. var seg = segs_4[_i];
  1628. seg.height = core.computeHeightAndMargins(seg.el);
  1629. }
  1630. this.buildSegLevels(segs); // populates above/below props for computeOffsetForSegs
  1631. var totalHeight = computeOffsetForSegs(segs); // also assigns seg.top
  1632. core.applyStyleProp(this.el, 'height', totalHeight);
  1633. // assign seg verticals
  1634. for (var _a = 0, segs_5 = segs; _a < segs_5.length; _a++) {
  1635. var seg = segs_5[_a];
  1636. core.applyStyleProp(seg.el, 'top', seg.top);
  1637. }
  1638. };
  1639. TimelineLaneEventRenderer.prototype.buildSegLevels = function (segs) {
  1640. var segLevels = [];
  1641. segs = this.sortEventSegs(segs);
  1642. for (var _i = 0, segs_6 = segs; _i < segs_6.length; _i++) {
  1643. var unplacedSeg = segs_6[_i];
  1644. unplacedSeg.above = [];
  1645. // determine the first level with no collisions
  1646. var level = 0; // level index
  1647. while (level < segLevels.length) {
  1648. var isLevelCollision = false;
  1649. // determine collisions
  1650. for (var _a = 0, _b = segLevels[level]; _a < _b.length; _a++) {
  1651. var placedSeg = _b[_a];
  1652. if (timeRowSegsCollide(unplacedSeg, placedSeg)) {
  1653. unplacedSeg.above.push(placedSeg);
  1654. isLevelCollision = true;
  1655. }
  1656. }
  1657. if (isLevelCollision) {
  1658. level += 1;
  1659. }
  1660. else {
  1661. break;
  1662. }
  1663. }
  1664. // insert into the first non-colliding level. create if necessary
  1665. (segLevels[level] || (segLevels[level] = []))
  1666. .push(unplacedSeg);
  1667. // record possible colliding segments below (TODO: automated test for this)
  1668. level += 1;
  1669. while (level < segLevels.length) {
  1670. for (var _c = 0, _d = segLevels[level]; _c < _d.length; _c++) {
  1671. var belowSeg = _d[_c];
  1672. if (timeRowSegsCollide(unplacedSeg, belowSeg)) {
  1673. belowSeg.above.push(unplacedSeg);
  1674. }
  1675. }
  1676. level += 1;
  1677. }
  1678. }
  1679. return segLevels;
  1680. };
  1681. return TimelineLaneEventRenderer;
  1682. }(core.FgEventRenderer));
  1683. function computeOffsetForSegs(segs) {
  1684. var max = 0;
  1685. for (var _i = 0, segs_7 = segs; _i < segs_7.length; _i++) {
  1686. var seg = segs_7[_i];
  1687. max = Math.max(max, computeOffsetForSeg(seg));
  1688. }
  1689. return max;
  1690. }
  1691. function computeOffsetForSeg(seg) {
  1692. if ((seg.top == null)) {
  1693. seg.top = computeOffsetForSegs(seg.above);
  1694. }
  1695. return seg.top + seg.height;
  1696. }
  1697. function timeRowSegsCollide(seg0, seg1) {
  1698. return (seg0.left < seg1.right) && (seg0.right > seg1.left);
  1699. }
  1700. var TimelineLaneFillRenderer = /** @class */ (function (_super) {
  1701. __extends(TimelineLaneFillRenderer, _super);
  1702. function TimelineLaneFillRenderer(masterContainerEl, timeAxis) {
  1703. var _this = _super.call(this) || this;
  1704. _this.masterContainerEl = masterContainerEl;
  1705. _this.timeAxis = timeAxis;
  1706. return _this;
  1707. }
  1708. TimelineLaneFillRenderer.prototype.attachSegs = function (type, segs) {
  1709. if (segs.length) {
  1710. var className = void 0;
  1711. if (type === 'businessHours') {
  1712. className = 'bgevent';
  1713. }
  1714. else {
  1715. className = type.toLowerCase();
  1716. }
  1717. // making a new container each time is OKAY
  1718. // all types of segs (background or business hours or whatever) are rendered in one pass
  1719. var containerEl = core.createElement('div', { className: 'fc-' + className + '-container' });
  1720. this.masterContainerEl.appendChild(containerEl);
  1721. for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
  1722. var seg = segs_1[_i];
  1723. containerEl.appendChild(seg.el);
  1724. }
  1725. return [containerEl]; // return value
  1726. }
  1727. };
  1728. TimelineLaneFillRenderer.prototype.computeSegSizes = function (segs) {
  1729. var timeAxis = this.timeAxis;
  1730. for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
  1731. var seg = segs_2[_i];
  1732. var coords = timeAxis.rangeToCoords(seg);
  1733. seg.left = coords.left;
  1734. seg.right = coords.right;
  1735. }
  1736. };
  1737. TimelineLaneFillRenderer.prototype.assignSegSizes = function (segs) {
  1738. for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
  1739. var seg = segs_3[_i];
  1740. core.applyStyle(seg.el, {
  1741. left: seg.left,
  1742. right: -seg.right
  1743. });
  1744. }
  1745. };
  1746. return TimelineLaneFillRenderer;
  1747. }(core.FillRenderer));
  1748. var TimelineLane = /** @class */ (function (_super) {
  1749. __extends(TimelineLane, _super);
  1750. function TimelineLane(fgContainerEl, bgContainerEl, timeAxis) {
  1751. var _this = _super.call(this, bgContainerEl) || this;
  1752. _this.slicer = new TimelineLaneSlicer();
  1753. _this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag);
  1754. _this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize);
  1755. _this.fgContainerEl = fgContainerEl;
  1756. _this.timeAxis = timeAxis;
  1757. var fillRenderer = _this.fillRenderer = new TimelineLaneFillRenderer(bgContainerEl, timeAxis);
  1758. var eventRenderer = _this.eventRenderer = new TimelineLaneEventRenderer(fgContainerEl, timeAxis);
  1759. _this.mirrorRenderer = new TimelineLaneEventRenderer(fgContainerEl, timeAxis);
  1760. _this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'));
  1761. _this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'));
  1762. _this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'));
  1763. _this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer));
  1764. _this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
  1765. return _this;
  1766. }
  1767. TimelineLane.prototype.render = function (props, context) {
  1768. var timeAxis = this.timeAxis;
  1769. var slicedProps = this.slicer.sliceProps(props, props.dateProfile, timeAxis.tDateProfile.isTimeScale ? null : props.nextDayThreshold, context.calendar, this, timeAxis);
  1770. this.renderBusinessHours(context, slicedProps.businessHourSegs);
  1771. this.renderDateSelection(context, slicedProps.dateSelectionSegs);
  1772. this.renderBgEvents(context, slicedProps.bgEventSegs);
  1773. this.renderFgEvents(context, slicedProps.fgEventSegs);
  1774. this.renderEventSelection(slicedProps.eventSelection);
  1775. this.renderEventDrag(slicedProps.eventDrag);
  1776. this.renderEventResize(slicedProps.eventResize);
  1777. };
  1778. TimelineLane.prototype.destroy = function () {
  1779. _super.prototype.destroy.call(this);
  1780. this.renderBusinessHours.unrender();
  1781. this.renderDateSelection.unrender();
  1782. this.renderBgEvents.unrender();
  1783. this.renderFgEvents.unrender();
  1784. this.renderEventSelection.unrender();
  1785. this.renderEventDrag.unrender();
  1786. this.renderEventResize.unrender();
  1787. };
  1788. TimelineLane.prototype._renderEventDrag = function (state) {
  1789. if (state) {
  1790. this.eventRenderer.hideByHash(state.affectedInstances);
  1791. this.mirrorRenderer.renderSegs(this.context, state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
  1792. }
  1793. };
  1794. TimelineLane.prototype._unrenderEventDrag = function (state) {
  1795. if (state) {
  1796. this.eventRenderer.showByHash(state.affectedInstances);
  1797. this.mirrorRenderer.unrender(this.context, state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
  1798. }
  1799. };
  1800. TimelineLane.prototype._renderEventResize = function (state) {
  1801. if (state) {
  1802. // HACK. eventRenderer and fillRenderer both use these segs. would compete over seg.el
  1803. var segsForHighlight = state.segs.map(function (seg) {
  1804. return __assign({}, seg);
  1805. });
  1806. this.eventRenderer.hideByHash(state.affectedInstances);
  1807. this.fillRenderer.renderSegs('highlight', this.context, segsForHighlight);
  1808. this.mirrorRenderer.renderSegs(this.context, state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
  1809. }
  1810. };
  1811. TimelineLane.prototype._unrenderEventResize = function (state) {
  1812. if (state) {
  1813. this.eventRenderer.showByHash(state.affectedInstances);
  1814. this.fillRenderer.unrender('highlight', this.context);
  1815. this.mirrorRenderer.unrender(this.context, state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
  1816. }
  1817. };
  1818. TimelineLane.prototype.updateSize = function (isResize) {
  1819. var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
  1820. fillRenderer.computeSizes(isResize);
  1821. eventRenderer.computeSizes(isResize);
  1822. mirrorRenderer.computeSizes(isResize);
  1823. fillRenderer.assignSizes(isResize);
  1824. eventRenderer.assignSizes(isResize);
  1825. mirrorRenderer.assignSizes(isResize);
  1826. };
  1827. return TimelineLane;
  1828. }(core.DateComponent));
  1829. var TimelineLaneSlicer = /** @class */ (function (_super) {
  1830. __extends(TimelineLaneSlicer, _super);
  1831. function TimelineLaneSlicer() {
  1832. return _super !== null && _super.apply(this, arguments) || this;
  1833. }
  1834. TimelineLaneSlicer.prototype.sliceRange = function (origRange, timeAxis) {
  1835. var tDateProfile = timeAxis.tDateProfile;
  1836. var _a = timeAxis.props, dateProfile = _a.dateProfile, dateProfileGenerator = _a.dateProfileGenerator;
  1837. var dateEnv = timeAxis.context.dateEnv;
  1838. var normalRange = normalizeRange(origRange, tDateProfile, dateEnv);
  1839. var segs = [];
  1840. // protect against when the span is entirely in an invalid date region
  1841. if (timeAxis.computeDateSnapCoverage(normalRange.start) < timeAxis.computeDateSnapCoverage(normalRange.end)) {
  1842. // intersect the footprint's range with the grid's range
  1843. var slicedRange = core.intersectRanges(normalRange, tDateProfile.normalizedRange);
  1844. if (slicedRange) {
  1845. segs.push({
  1846. start: slicedRange.start,
  1847. end: slicedRange.end,
  1848. isStart: slicedRange.start.valueOf() === normalRange.start.valueOf() && isValidDate(slicedRange.start, tDateProfile, dateProfile, dateProfileGenerator),
  1849. isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf() && isValidDate(core.addMs(slicedRange.end, -1), tDateProfile, dateProfile, dateProfileGenerator)
  1850. });
  1851. }
  1852. }
  1853. return segs;
  1854. };
  1855. return TimelineLaneSlicer;
  1856. }(core.Slicer));
  1857. var TimelineView = /** @class */ (function (_super) {
  1858. __extends(TimelineView, _super);
  1859. function TimelineView() {
  1860. var _this = _super !== null && _super.apply(this, arguments) || this;
  1861. _this.renderSkeleton = core.memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
  1862. _this.startInteractive = core.memoizeRendering(_this._startInteractive, _this._stopInteractive);
  1863. return _this;
  1864. }
  1865. TimelineView.prototype._startInteractive = function (timeAxisEl) {
  1866. this.context.calendar.registerInteractiveComponent(this, {
  1867. el: timeAxisEl
  1868. });
  1869. };
  1870. TimelineView.prototype._stopInteractive = function () {
  1871. this.context.calendar.unregisterInteractiveComponent(this);
  1872. };
  1873. TimelineView.prototype.render = function (props, context) {
  1874. _super.prototype.render.call(this, props, context); // flags for updateSize, addScroll. and _renderSkeleton/_unrenderSkeleton
  1875. this.renderSkeleton(this.context);
  1876. this.timeAxis.receiveProps({
  1877. dateProfileGenerator: props.dateProfileGenerator,
  1878. dateProfile: props.dateProfile
  1879. }, context);
  1880. this.startInteractive(this.timeAxis.slats.el);
  1881. this.lane.receiveProps(__assign({}, props, { nextDayThreshold: this.context.nextDayThreshold }), context);
  1882. this.startNowIndicator(props.dateProfile, props.dateProfileGenerator);
  1883. };
  1884. TimelineView.prototype.destroy = function () {
  1885. this.startInteractive.unrender(); // "unrender" a weird name
  1886. this.renderSkeleton.unrender();
  1887. _super.prototype.destroy.call(this);
  1888. };
  1889. TimelineView.prototype._renderSkeleton = function (context) {
  1890. this.el.classList.add('fc-timeline');
  1891. if (context.options.eventOverlap === false) {
  1892. this.el.classList.add('fc-no-overlap');
  1893. }
  1894. this.el.innerHTML = this.renderSkeletonHtml();
  1895. this.timeAxis = new TimeAxis(this.el.querySelector('thead .fc-time-area'), this.el.querySelector('tbody .fc-time-area'));
  1896. this.lane = new TimelineLane(this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl, this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, this.timeAxis);
  1897. };
  1898. TimelineView.prototype._unrenderSkeleton = function () {
  1899. this.el.classList.remove('fc-timeline');
  1900. this.el.classList.remove('fc-no-overlap');
  1901. this.timeAxis.destroy();
  1902. this.lane.destroy();
  1903. };
  1904. TimelineView.prototype.renderSkeletonHtml = function () {
  1905. var theme = this.context.theme;
  1906. return "<table class=\"" + theme.getClass('tableGrid') + "\"> <thead class=\"fc-head\"> <tr> <td class=\"fc-time-area " + theme.getClass('widgetHeader') + "\"></td> </tr> </thead> <tbody class=\"fc-body\"> <tr> <td class=\"fc-time-area " + theme.getClass('widgetContent') + "\"></td> </tr> </tbody> </table>";
  1907. };
  1908. TimelineView.prototype.updateSize = function (isResize, totalHeight, isAuto) {
  1909. this.timeAxis.updateSize(isResize, totalHeight, isAuto);
  1910. this.lane.updateSize(isResize);
  1911. };
  1912. // Now Indicator
  1913. // ------------------------------------------------------------------------------------------
  1914. TimelineView.prototype.getNowIndicatorUnit = function (dateProfile, dateProfileGenerator) {
  1915. return this.timeAxis.getNowIndicatorUnit(dateProfile, dateProfileGenerator);
  1916. };
  1917. TimelineView.prototype.renderNowIndicator = function (date) {
  1918. this.timeAxis.renderNowIndicator(date);
  1919. };
  1920. TimelineView.prototype.unrenderNowIndicator = function () {
  1921. this.timeAxis.unrenderNowIndicator();
  1922. };
  1923. // Scroll System
  1924. // ------------------------------------------------------------------------------------------
  1925. TimelineView.prototype.computeDateScroll = function (duration) {
  1926. return this.timeAxis.computeDateScroll(duration);
  1927. };
  1928. TimelineView.prototype.applyScroll = function (scroll, isResize) {
  1929. _super.prototype.applyScroll.call(this, scroll, isResize); // will call applyDateScroll
  1930. var calendar = this.context.calendar;
  1931. // avoid updating stickyscroll too often
  1932. // TODO: repeat code as ResourceTimelineView::updateSize
  1933. if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) {
  1934. this.timeAxis.updateStickyScrollers();
  1935. }
  1936. };
  1937. TimelineView.prototype.applyDateScroll = function (scroll) {
  1938. this.timeAxis.applyDateScroll(scroll);
  1939. };
  1940. TimelineView.prototype.queryScroll = function () {
  1941. var enhancedScroll = this.timeAxis.layout.bodyScroller.enhancedScroll;
  1942. return {
  1943. top: enhancedScroll.getScrollTop(),
  1944. left: enhancedScroll.getScrollLeft()
  1945. };
  1946. };
  1947. // Hit System
  1948. // ------------------------------------------------------------------------------------------
  1949. TimelineView.prototype.buildPositionCaches = function () {
  1950. this.timeAxis.slats.updateSize();
  1951. };
  1952. TimelineView.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
  1953. var slatHit = this.timeAxis.slats.positionToHit(positionLeft);
  1954. if (slatHit) {
  1955. return {
  1956. component: this,
  1957. dateSpan: slatHit.dateSpan,
  1958. rect: {
  1959. left: slatHit.left,
  1960. right: slatHit.right,
  1961. top: 0,
  1962. bottom: elHeight
  1963. },
  1964. dayEl: slatHit.dayEl,
  1965. layer: 0
  1966. };
  1967. }
  1968. };
  1969. return TimelineView;
  1970. }(core.View));
  1971. var main = core.createPlugin({
  1972. defaultView: 'timelineDay',
  1973. views: {
  1974. timeline: {
  1975. class: TimelineView,
  1976. eventResizableFromStart: true // how is this consumed for TimelineView tho?
  1977. },
  1978. timelineDay: {
  1979. type: 'timeline',
  1980. duration: { days: 1 }
  1981. },
  1982. timelineWeek: {
  1983. type: 'timeline',
  1984. duration: { weeks: 1 }
  1985. },
  1986. timelineMonth: {
  1987. type: 'timeline',
  1988. duration: { months: 1 }
  1989. },
  1990. timelineYear: {
  1991. type: 'timeline',
  1992. duration: { years: 1 }
  1993. }
  1994. }
  1995. });
  1996. exports.HeaderBodyLayout = HeaderBodyLayout;
  1997. exports.ScrollJoiner = ScrollJoiner;
  1998. exports.StickyScroller = StickyScroller;
  1999. exports.TimeAxis = TimeAxis;
  2000. exports.TimelineLane = TimelineLane;
  2001. exports.TimelineView = TimelineView;
  2002. exports.default = main;
  2003. Object.defineProperty(exports, '__esModule', { value: true });
  2004. }));