Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • komasolver
  • main
  • renovate/django-5.x
  • renovate/django-debug-toolbar-5.x
  • renovate/django_csp-4.x
  • renovate/djangorestframework-3.x
  • renovate/sphinxcontrib-apidoc-0.x
  • renovate/tzdata-2025.x
  • renovate/uwsgi-2.x
9 results

Target

Select target project
  • konstantin/akplanning
  • matedealer/akplanning
  • kif/akplanning
  • mirco/akplanning
  • lordofthevoid/akplanning
  • voidptr/akplanning
  • xayomer/akplanning-fork
  • mollux/akplanning
  • neumantm/akplanning
  • mmarx/akplanning
  • nerf/akplanning
  • felix_bonn/akplanning
  • sebastian.uschmann/akplanning
13 results
Select Git revision
  • 520-akowner
  • 520-fix-event-wizard-datepicker
  • 520-fix-scheduling
  • 520-improve-scheduling
  • 520-improve-scheduling-2
  • 520-improve-submission
  • 520-improve-trackmanager
  • 520-improve-wall
  • 520-message-resolved
  • 520-status
  • 520-upgrades
  • add_express_interest_to_ak_overview
  • admin-production-color
  • bugfixes
  • csp
  • featire-ical-export
  • feature-ak-requirement-lists
  • feature-akslide-export-better-filename
  • feature-akslides
  • feature-better-admin
  • feature-better-cv-list
  • feature-colors
  • feature-constraint-checking
  • feature-constraint-checking-wip
  • feature-dashboard-history-button
  • feature-event-status
  • feature-event-wizard
  • feature-export-flag
  • feature-improve-admin
  • feature-improve-filters
  • feature-improved-user-creation-workflow
  • feature-interest-view
  • feature-mails
  • feature-modular-status
  • feature-plan-autoreload
  • feature-present-default
  • feature-register-link
  • feature-remaining-constraint-validation
  • feature-room-import
  • feature-scheduler-improve
  • feature-scheduling-2.0
  • feature-special-attention
  • feature-time-input
  • feature-tracker
  • feature-wiki-wishes
  • feature-wish-slots
  • feature-wizard-buttons
  • features-availabilities
  • fix-ak-times-above-folg
  • fix-api
  • fix-constraint-violation-string
  • fix-cv-checking
  • fix-default-slot-length
  • fix-default-slot-localization
  • fix-doc-minor
  • fix-duration-display
  • fix-event-tz-pytz-update
  • fix-history-interest
  • fix-interest-view
  • fix-js
  • fix-pipeline
  • fix-plan-timezone-now
  • fix-room-add
  • fix-scheduling-drag
  • fix-slot-defaultlength
  • fix-timezone
  • fix-translation-scheduling
  • fix-virtual-room-admin
  • fix-wizard-csp
  • font-locally
  • improve-admin
  • improve-online
  • improve-slides
  • improve-submission-coupling
  • interest_restriction
  • main
  • master
  • meta-debug-toolbar
  • meta-export
  • meta-makemessages
  • meta-performance
  • meta-tests
  • meta-tests-gitlab-test
  • meta-upgrades
  • mollux-master-patch-02906
  • port-availabilites-fullcalendar
  • qs
  • remove-tags
  • renovate/configure
  • renovate/django-4.x
  • renovate/django-5.x
  • renovate/django-bootstrap-datepicker-plus-5.x
  • renovate/django-bootstrap5-23.x
  • renovate/django-bootstrap5-24.x
  • renovate/django-compressor-4.x
  • renovate/django-debug-toolbar-4.x
  • renovate/django-registration-redux-2.x
  • renovate/django-simple-history-3.x
  • renovate/django-split-settings-1.x
  • renovate/django-timezone-field-5.x
100 results
Show changes
Showing
with 152 additions and 4989 deletions
@charset "UTF-8";.fc-timeGrid-view .fc-day-grid{position:relative;z-index:2}.fc-timeGrid-view .fc-day-grid .fc-row{min-height:3em}.fc-timeGrid-view .fc-day-grid .fc-row .fc-content-skeleton{padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px;white-space:nowrap}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3;position:relative}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-mirror-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-time-grid-event{margin-bottom:1px}.fc-time-grid-event-inset{-webkit-box-shadow:0 0 0 1px #fff;box-shadow:0 0 0 1px #fff}.fc-time-grid-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-time-grid-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event .fc-content{overflow:hidden;max-height:100%}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em;white-space:nowrap}.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:" - "}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after{content:"="}.fc-time-grid-event.fc-selected .fc-resizer{border-radius:5px;border-width:1px;width:8px;height:8px;border-style:solid;border-color:inherit;background:#fff;left:50%;margin-left:-5px;bottom:-5px}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent}
\ No newline at end of file
/*!
FullCalendar Time Grid Plugin v4.3.0
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core"),require("@fullcalendar/daygrid")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core","@fullcalendar/daygrid"],t):t((e=e||self).FullCalendarTimeGrid={},e.FullCalendar,e.FullCalendarDayGrid)}(this,function(e,t,r){"use strict";var i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function n(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var o=function(){return(o=Object.assign||function(e){for(var t,r=1,i=arguments.length;r<i;r++)for(var n in t=arguments[r])Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e}).apply(this,arguments)},s=function(e){function r(r){var i=e.call(this,r.context)||this;return i.timeGrid=r,i.fullTimeFormat=t.createFormatter({hour:"numeric",minute:"2-digit",separator:i.context.options.defaultRangeSeparator}),i}return n(r,e),r.prototype.attachSegs=function(e,t){for(var r=this.timeGrid.groupSegsByCol(e),i=0;i<r.length;i++)r[i]=this.sortEventSegs(r[i]);this.segsByCol=r,this.timeGrid.attachSegsByCol(r,this.timeGrid.fgContainerEls)},r.prototype.detachSegs=function(e){e.forEach(function(e){t.removeElement(e.el)}),this.segsByCol=null},r.prototype.computeSegSizes=function(e){var t=this.timeGrid,r=this.segsByCol,i=t.colCnt;if(t.computeSegVerticals(e),r)for(var n=0;n<i;n++)this.computeSegHorizontals(r[n])},r.prototype.assignSegSizes=function(e){var t=this.timeGrid,r=this.segsByCol,i=t.colCnt;if(t.assignSegVerticals(e),r)for(var n=0;n<i;n++)this.assignSegCss(r[n])},r.prototype.computeEventTimeFormat=function(){return{hour:"numeric",minute:"2-digit",meridiem:!1}},r.prototype.computeDisplayEventEnd=function(){return!0},r.prototype.renderSegHtml=function(e,r){var i,n,o,s=this.context.view,a=e.eventRange,l=a.def,d=a.ui,c=l.allDay,h=s.computeEventDraggable(l,d),u=e.isStart&&s.computeEventStartResizable(l,d),p=e.isEnd&&s.computeEventEndResizable(l,d),f=this.getSegClasses(e,h,u||p,r),g=t.cssToStr(this.getSkinCss(d));if(f.unshift("fc-time-grid-event"),t.isMultiDayRange(a.range)){if(e.isStart||e.isEnd){var m=e.start,y=e.end;i=this._getTimeText(m,y,c),n=this._getTimeText(m,y,c,this.fullTimeFormat),o=this._getTimeText(m,y,c,null,!1)}}else i=this.getTimeText(a),n=this.getTimeText(a,this.fullTimeFormat),o=this.getTimeText(a,null,!1);return'<a class="'+f.join(" ")+'"'+(l.url?' href="'+t.htmlEscape(l.url)+'"':"")+(g?' style="'+g+'"':"")+'><div class="fc-content">'+(i?'<div class="fc-time" data-start="'+t.htmlEscape(o)+'" data-full="'+t.htmlEscape(n)+'"><span>'+t.htmlEscape(i)+"</span></div>":"")+(l.title?'<div class="fc-title">'+t.htmlEscape(l.title)+"</div>":"")+"</div>"+(p?'<div class="fc-resizer fc-end-resizer"></div>':"")+"</a>"},r.prototype.computeSegHorizontals=function(e){var t,r,i;if(function(e){var t,r,i,n,o;for(t=0;t<e.length;t++)for(r=e[t],i=0;i<r.length;i++)for((n=r[i]).forwardSegs=[],o=t+1;o<e.length;o++)l(n,e[o],n.forwardSegs)}(t=function(e){var t,r,i,n=[];for(t=0;t<e.length;t++){for(r=e[t],i=0;i<n.length&&l(r,n[i]).length;i++);r.level=i,(n[i]||(n[i]=[])).push(r)}return n}(e)),r=t[0]){for(i=0;i<r.length;i++)a(r[i]);for(i=0;i<r.length;i++)this.computeSegForwardBack(r[i],0,0)}},r.prototype.computeSegForwardBack=function(e,t,r){var i,n=e.forwardSegs;if(void 0===e.forwardCoord)for(n.length?(this.sortForwardSegs(n),this.computeSegForwardBack(n[0],t+1,r),e.forwardCoord=n[0].backwardCoord):e.forwardCoord=1,e.backwardCoord=e.forwardCoord-(e.forwardCoord-r)/(t+1),i=0;i<n.length;i++)this.computeSegForwardBack(n[i],0,e.forwardCoord)},r.prototype.sortForwardSegs=function(e){var r=e.map(d),i=[{field:"forwardPressure",order:-1},{field:"backwardCoord",order:1}].concat(this.context.view.eventOrderSpecs);return r.sort(function(e,r){return t.compareByFieldSpecs(e,r,i)}),r.map(function(e){return e._seg})},r.prototype.assignSegCss=function(e){for(var r=0,i=e;r<i.length;r++){var n=i[r];t.applyStyle(n.el,this.generateSegCss(n)),n.level>0&&n.el.classList.add("fc-time-grid-event-inset"),n.eventRange.def.title&&n.bottom-n.top<30&&n.el.classList.add("fc-short")}},r.prototype.generateSegCss=function(e){var t,r,i=this.context.options.slotEventOverlap,n=e.backwardCoord,o=e.forwardCoord,s=this.timeGrid.generateSegVerticalCss(e),a=this.timeGrid.isRtl;return i&&(o=Math.min(1,n+2*(o-n))),a?(t=1-o,r=n):(t=n,r=1-o),s.zIndex=e.level+1,s.left=100*t+"%",s.right=100*r+"%",i&&e.forwardPressure&&(s[a?"marginLeft":"marginRight"]=20),s},r}(t.FgEventRenderer);function a(e){var t,r,i=e.forwardSegs,n=0;if(void 0===e.forwardPressure){for(t=0;t<i.length;t++)a(r=i[t]),n=Math.max(n,1+r.forwardPressure);e.forwardPressure=n}}function l(e,t,r){void 0===r&&(r=[]);for(var i=0;i<t.length;i++)n=e,o=t[i],n.bottom>o.top&&n.top<o.bottom&&r.push(t[i]);var n,o;return r}function d(e){var r=t.buildSegCompareObj(e);return r.forwardPressure=e.forwardPressure,r.backwardCoord=e.backwardCoord,r}var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return n(t,e),t.prototype.attachSegs=function(e,t){this.segsByCol=this.timeGrid.groupSegsByCol(e),this.timeGrid.attachSegsByCol(this.segsByCol,this.timeGrid.mirrorContainerEls),this.sourceSeg=t.sourceSeg},t.prototype.generateSegCss=function(t){var r=e.prototype.generateSegCss.call(this,t),i=this.sourceSeg;if(i&&i.col===t.col){var n=e.prototype.generateSegCss.call(this,i);r.left=n.left,r.right=n.right,r.marginLeft=n.marginLeft,r.marginRight=n.marginRight}return r},t}(s),h=function(e){function t(t){var r=e.call(this,t.context)||this;return r.timeGrid=t,r}return n(t,e),t.prototype.attachSegs=function(e,t){var r,i=this.timeGrid;return"bgEvent"===e?r=i.bgContainerEls:"businessHours"===e?r=i.businessContainerEls:"highlight"===e&&(r=i.highlightContainerEls),i.attachSegsByCol(i.groupSegsByCol(t),r),t.map(function(e){return e.el})},t.prototype.computeSegSizes=function(e){this.timeGrid.computeSegVerticals(e)},t.prototype.assignSegSizes=function(e){this.timeGrid.assignSegVerticals(e)},t}(t.FillRenderer),u=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}],p=function(e){function i(r,i,n){var o=e.call(this,r,i)||this;o.isSlatSizesDirty=!1,o.isColSizesDirty=!1,o.renderSlats=t.memoizeRendering(o._renderSlats);var a=o.eventRenderer=new s(o),l=o.fillRenderer=new h(o);o.mirrorRenderer=new c(o);var d=o.renderColumns=t.memoizeRendering(o._renderColumns,o._unrenderColumns);return o.renderBusinessHours=t.memoizeRendering(l.renderSegs.bind(l,"businessHours"),l.unrender.bind(l,"businessHours"),[d]),o.renderDateSelection=t.memoizeRendering(o._renderDateSelection,o._unrenderDateSelection,[d]),o.renderFgEvents=t.memoizeRendering(a.renderSegs.bind(a),a.unrender.bind(a),[d]),o.renderBgEvents=t.memoizeRendering(l.renderSegs.bind(l,"bgEvent"),l.unrender.bind(l,"bgEvent"),[d]),o.renderEventSelection=t.memoizeRendering(a.selectByInstanceId.bind(a),a.unselectByInstanceId.bind(a),[o.renderFgEvents]),o.renderEventDrag=t.memoizeRendering(o._renderEventDrag,o._unrenderEventDrag,[d]),o.renderEventResize=t.memoizeRendering(o._renderEventResize,o._unrenderEventResize,[d]),o.processOptions(),i.innerHTML='<div class="fc-bg"></div><div class="fc-slats"></div><hr class="fc-divider '+o.theme.getClass("widgetHeader")+'" style="display:none" />',o.rootBgContainerEl=i.querySelector(".fc-bg"),o.slatContainerEl=i.querySelector(".fc-slats"),o.bottomRuleEl=i.querySelector(".fc-divider"),o.renderProps=n,o}return n(i,e),i.prototype.processOptions=function(){var e,r,i=this.opt("slotDuration"),n=this.opt("snapDuration");i=t.createDuration(i),n=n?t.createDuration(n):i,null===(e=t.wholeDivideDurations(i,n))&&(n=i,e=1),this.slotDuration=i,this.snapDuration=n,this.snapsPerSlot=e,r=this.opt("slotLabelFormat"),Array.isArray(r)&&(r=r[r.length-1]),this.labelFormat=t.createFormatter(r||{hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"}),r=this.opt("slotLabelInterval"),this.labelInterval=r?t.createDuration(r):this.computeLabelInterval(i)},i.prototype.computeLabelInterval=function(e){var r,i,n;for(r=u.length-1;r>=0;r--)if(i=t.createDuration(u[r]),null!==(n=t.wholeDivideDurations(i,e))&&n>1)return i;return e},i.prototype.render=function(e){var t=e.cells;this.colCnt=t.length,this.renderSlats(e.dateProfile),this.renderColumns(e.cells,e.dateProfile),this.renderBusinessHours(e.businessHourSegs),this.renderDateSelection(e.dateSelectionSegs),this.renderFgEvents(e.fgEventSegs),this.renderBgEvents(e.bgEventSegs),this.renderEventSelection(e.eventSelection),this.renderEventDrag(e.eventDrag),this.renderEventResize(e.eventResize)},i.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderSlats.unrender(),this.renderColumns.unrender()},i.prototype.updateSize=function(e){var t=this.fillRenderer,r=this.eventRenderer,i=this.mirrorRenderer;(e||this.isSlatSizesDirty)&&(this.buildSlatPositions(),this.isSlatSizesDirty=!1),(e||this.isColSizesDirty)&&(this.buildColPositions(),this.isColSizesDirty=!1),t.computeSizes(e),r.computeSizes(e),i.computeSizes(e),t.assignSizes(e),r.assignSizes(e),i.assignSizes(e)},i.prototype._renderSlats=function(e){var r=this.theme;this.slatContainerEl.innerHTML='<table class="'+r.getClass("tableGrid")+'">'+this.renderSlatRowHtml(e)+"</table>",this.slatEls=t.findElements(this.slatContainerEl,"tr"),this.slatPositions=new t.PositionCache(this.el,this.slatEls,!1,!0),this.isSlatSizesDirty=!0},i.prototype.renderSlatRowHtml=function(e){for(var r,i,n,o=this.dateEnv,s=this.theme,a=this.isRtl,l="",d=t.startOfDay(e.renderRange.start),c=e.minTime,h=t.createDuration(0);t.asRoughMs(c)<t.asRoughMs(e.maxTime);)r=o.add(d,c),i=null!==t.wholeDivideDurations(h,this.labelInterval),n='<td class="fc-axis fc-time '+s.getClass("widgetContent")+'">'+(i?"<span>"+t.htmlEscape(o.format(r,this.labelFormat))+"</span>":"")+"</td>",l+='<tr data-time="'+t.formatIsoTimeString(r)+'"'+(i?"":' class="fc-minor"')+">"+(a?"":n)+'<td class="'+s.getClass("widgetContent")+'"></td>'+(a?n:"")+"</tr>",c=t.addDurations(c,this.slotDuration),h=t.addDurations(h,this.slotDuration);return l},i.prototype._renderColumns=function(e,i){var n=this.theme,o=this.dateEnv,s=this.view,a=new r.DayBgRow(this.context);this.rootBgContainerEl.innerHTML='<table class="'+n.getClass("tableGrid")+'">'+a.renderHtml({cells:e,dateProfile:i,renderIntroHtml:this.renderProps.renderBgIntroHtml})+"</table>",this.colEls=t.findElements(this.el,".fc-day, .fc-disabled-day");for(var l=0;l<this.colCnt;l++)this.publiclyTrigger("dayRender",[{date:o.toDate(e[l].date),el:this.colEls[l],view:s}]);this.isRtl&&this.colEls.reverse(),this.colPositions=new t.PositionCache(this.el,this.colEls,!0,!1),this.renderContentSkeleton(),this.isColSizesDirty=!0},i.prototype._unrenderColumns=function(){this.unrenderContentSkeleton()},i.prototype.renderContentSkeleton=function(){var e,r=[];r.push(this.renderProps.renderIntroHtml());for(var i=0;i<this.colCnt;i++)r.push('<td><div class="fc-content-col"><div class="fc-event-container fc-mirror-container"></div><div class="fc-event-container"></div><div class="fc-highlight-container"></div><div class="fc-bgevent-container"></div><div class="fc-business-container"></div></div></td>');this.isRtl&&r.reverse(),e=this.contentSkeletonEl=t.htmlToElement('<div class="fc-content-skeleton"><table><tr>'+r.join("")+"</tr></table></div>"),this.colContainerEls=t.findElements(e,".fc-content-col"),this.mirrorContainerEls=t.findElements(e,".fc-mirror-container"),this.fgContainerEls=t.findElements(e,".fc-event-container:not(.fc-mirror-container)"),this.bgContainerEls=t.findElements(e,".fc-bgevent-container"),this.highlightContainerEls=t.findElements(e,".fc-highlight-container"),this.businessContainerEls=t.findElements(e,".fc-business-container"),this.isRtl&&(this.colContainerEls.reverse(),this.mirrorContainerEls.reverse(),this.fgContainerEls.reverse(),this.bgContainerEls.reverse(),this.highlightContainerEls.reverse(),this.businessContainerEls.reverse()),this.el.appendChild(e)},i.prototype.unrenderContentSkeleton=function(){t.removeElement(this.contentSkeletonEl)},i.prototype.groupSegsByCol=function(e){var t,r=[];for(t=0;t<this.colCnt;t++)r.push([]);for(t=0;t<e.length;t++)r[e[t].col].push(e[t]);return r},i.prototype.attachSegsByCol=function(e,t){var r,i,n;for(r=0;r<this.colCnt;r++)for(i=e[r],n=0;n<i.length;n++)t[r].appendChild(i[n].el)},i.prototype.getNowIndicatorUnit=function(){return"minute"},i.prototype.renderNowIndicator=function(e,r){if(this.colContainerEls){var i,n=this.computeDateTop(r),o=[];for(i=0;i<e.length;i++){var s=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-line"});s.style.top=n+"px",this.colContainerEls[e[i].col].appendChild(s),o.push(s)}if(e.length>0){var a=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-arrow"});a.style.top=n+"px",this.contentSkeletonEl.appendChild(a),o.push(a)}this.nowIndicatorEls=o}},i.prototype.unrenderNowIndicator=function(){this.nowIndicatorEls&&(this.nowIndicatorEls.forEach(t.removeElement),this.nowIndicatorEls=null)},i.prototype.getTotalSlatHeight=function(){return this.slatContainerEl.getBoundingClientRect().height},i.prototype.computeDateTop=function(e,r){return r||(r=t.startOfDay(e)),this.computeTimeTop(t.createDuration(e.valueOf()-r.valueOf()))},i.prototype.computeTimeTop=function(e){var r,i,n=this.slatEls.length,o=this.props.dateProfile,s=(e.milliseconds-t.asRoughMs(o.minTime))/t.asRoughMs(this.slotDuration);return s=Math.max(0,s),s=Math.min(n,s),r=Math.floor(s),i=s-(r=Math.min(r,n-1)),this.slatPositions.tops[r]+this.slatPositions.getHeight(r)*i},i.prototype.computeSegVerticals=function(e){var t,r,i,n=this.opt("timeGridEventMinHeight");for(t=0;t<e.length;t++)r=e[t],i=this.props.cells[r.col].date,r.top=this.computeDateTop(r.start,i),r.bottom=Math.max(r.top+n,this.computeDateTop(r.end,i))},i.prototype.assignSegVerticals=function(e){var r,i;for(r=0;r<e.length;r++)i=e[r],t.applyStyle(i.el,this.generateSegVerticalCss(i))},i.prototype.generateSegVerticalCss=function(e){return{top:e.top,bottom:-e.bottom}},i.prototype.buildPositionCaches=function(){this.buildColPositions(),this.buildSlatPositions()},i.prototype.buildColPositions=function(){this.colPositions.build()},i.prototype.buildSlatPositions=function(){this.slatPositions.build()},i.prototype.positionToHit=function(e,r){var i=this.dateEnv,n=this.snapsPerSlot,o=this.slatPositions,s=this.colPositions,a=s.leftToIndex(e),l=o.topToIndex(r);if(null!=a&&null!=l){var d=o.tops[l],c=o.getHeight(l),h=(r-d)/c,u=l*n+Math.floor(h*n),p=this.props.cells[a].date,f=t.addDurations(this.props.dateProfile.minTime,t.multiplyDuration(this.snapDuration,u)),g=i.add(p,f);return{col:a,dateSpan:{range:{start:g,end:i.add(g,this.snapDuration)},allDay:!1},dayEl:this.colEls[a],relativeRect:{left:s.lefts[a],right:s.rights[a],top:d,bottom:d+c}}}},i.prototype._renderEventDrag=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),e.isEvent?this.mirrorRenderer.renderSegs(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}):this.fillRenderer.renderSegs("highlight",e.segs))},i.prototype._unrenderEventDrag=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.mirrorRenderer.unrender(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}),this.fillRenderer.unrender("highlight"))},i.prototype._renderEventResize=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),this.mirrorRenderer.renderSegs(e.segs,{isResizing:!0,sourceSeg:e.sourceSeg}))},i.prototype._unrenderEventResize=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.mirrorRenderer.unrender(e.segs,{isResizing:!0,sourceSeg:e.sourceSeg}))},i.prototype._renderDateSelection=function(e){e&&(this.opt("selectMirror")?this.mirrorRenderer.renderSegs(e,{isSelecting:!0}):this.fillRenderer.renderSegs("highlight",e))},i.prototype._unrenderDateSelection=function(e){this.mirrorRenderer.unrender(e,{isSelecting:!0}),this.fillRenderer.unrender("highlight")},i}(t.DateComponent),f=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.getKeyInfo=function(){return{allDay:{},timed:{}}},r.prototype.getKeysForDateSpan=function(e){return e.allDay?["allDay"]:["timed"]},r.prototype.getKeysForEventDef=function(e){return e.allDay?t.hasBgRendering(e)?["timed","allDay"]:["allDay"]:["timed"]},r}(t.Splitter),g=t.createFormatter({week:"short"}),m=function(e){function i(i,n,o,s){var a=e.call(this,i,n,o,s)||this;a.splitter=new f,a.renderHeadIntroHtml=function(){var e,r=a,i=r.theme,n=r.dateEnv,o=a.props.dateProfile.renderRange,s=t.diffDays(o.start,o.end);return a.opt("weekNumbers")?(e=n.format(o.start,g),'<th class="fc-axis fc-week-number '+i.getClass("widgetHeader")+'" '+a.axisStyleAttr()+">"+t.buildGotoAnchorHtml(a,{date:o.start,type:"week",forceOff:s>1},t.htmlEscape(e))+"</th>"):'<th class="fc-axis '+i.getClass("widgetHeader")+'" '+a.axisStyleAttr()+"></th>"},a.renderTimeGridBgIntroHtml=function(){return'<td class="fc-axis '+a.theme.getClass("widgetContent")+'" '+a.axisStyleAttr()+"></td>"},a.renderTimeGridIntroHtml=function(){return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"},a.renderDayGridBgIntroHtml=function(){return'<td class="fc-axis '+a.theme.getClass("widgetContent")+'" '+a.axisStyleAttr()+"><span>"+t.getAllDayHtml(a)+"</span></td>"},a.renderDayGridIntroHtml=function(){return'<td class="fc-axis" '+a.axisStyleAttr()+"></td>"},a.el.classList.add("fc-timeGrid-view"),a.el.innerHTML=a.renderSkeletonHtml(),a.scroller=new t.ScrollComponent("hidden","auto");var l=a.scroller.el;a.el.querySelector(".fc-body > tr > td").appendChild(l),l.classList.add("fc-time-grid-container");var d=t.createElement("div",{className:"fc-time-grid"});if(l.appendChild(d),a.timeGrid=new p(a.context,d,{renderBgIntroHtml:a.renderTimeGridBgIntroHtml,renderIntroHtml:a.renderTimeGridIntroHtml}),a.opt("allDaySlot")){a.dayGrid=new r.DayGrid(a.context,a.el.querySelector(".fc-day-grid"),{renderNumberIntroHtml:a.renderDayGridIntroHtml,renderBgIntroHtml:a.renderDayGridBgIntroHtml,renderIntroHtml:a.renderDayGridIntroHtml,colWeekNumbersVisible:!1,cellWeekNumbersVisible:!1});var c=a.el.querySelector(".fc-divider");a.dayGrid.bottomCoordPadding=c.getBoundingClientRect().height}return a}return n(i,e),i.prototype.destroy=function(){e.prototype.destroy.call(this),this.timeGrid.destroy(),this.dayGrid&&this.dayGrid.destroy(),this.scroller.destroy()},i.prototype.renderSkeletonHtml=function(){var e=this.theme;return'<table class="'+e.getClass("tableGrid")+'">'+(this.opt("columnHeader")?'<thead class="fc-head"><tr><td class="fc-head-container '+e.getClass("widgetHeader")+'">&nbsp;</td></tr></thead>':"")+'<tbody class="fc-body"><tr><td class="'+e.getClass("widgetContent")+'">'+(this.opt("allDaySlot")?'<div class="fc-day-grid"></div><hr class="fc-divider '+e.getClass("widgetHeader")+'" />':"")+"</td></tr></tbody></table>"},i.prototype.getNowIndicatorUnit=function(){return this.timeGrid.getNowIndicatorUnit()},i.prototype.unrenderNowIndicator=function(){this.timeGrid.unrenderNowIndicator()},i.prototype.updateSize=function(t,r,i){e.prototype.updateSize.call(this,t,r,i),this.timeGrid.updateSize(t),this.dayGrid&&this.dayGrid.updateSize(t)},i.prototype.updateBaseSize=function(e,r,i){var n,o,s,a=this;if(this.axisWidth=t.matchCellWidths(t.findElements(this.el,".fc-axis")),this.timeGrid.colEls){var l=t.findElements(this.el,".fc-row").filter(function(e){return!a.scroller.el.contains(e)});this.timeGrid.bottomRuleEl.style.display="none",this.scroller.clear(),l.forEach(t.uncompensateScroll),this.dayGrid&&(this.dayGrid.removeSegPopover(),(n=this.opt("eventLimit"))&&"number"!=typeof n&&(n=5),n&&this.dayGrid.limitRows(n)),i||(o=this.computeScrollerHeight(r),this.scroller.setHeight(o),((s=this.scroller.getScrollbarWidths()).left||s.right)&&(l.forEach(function(e){t.compensateScroll(e,s)}),o=this.computeScrollerHeight(r),this.scroller.setHeight(o)),this.scroller.lockOverflow(s),this.timeGrid.getTotalSlatHeight()<o&&(this.timeGrid.bottomRuleEl.style.display=""))}else i||(o=this.computeScrollerHeight(r),this.scroller.setHeight(o))},i.prototype.computeScrollerHeight=function(e){return e-t.subtractInnerElHeight(this.el,this.scroller.el)},i.prototype.computeDateScroll=function(e){var t=this.timeGrid.computeTimeTop(e);return(t=Math.ceil(t))&&t++,{top:t}},i.prototype.queryDateScroll=function(){return{top:this.scroller.getScrollTop()}},i.prototype.applyDateScroll=function(e){void 0!==e.top&&this.scroller.setScrollTop(e.top)},i.prototype.axisStyleAttr=function(){return null!=this.axisWidth?'style="width:'+this.axisWidth+'px"':""},i}(t.View);m.prototype.usesMinMaxTime=!0;var y=function(e){function r(r,i){var n=e.call(this,r,i.el)||this;return n.buildDayRanges=t.memoize(v),n.slicer=new S,n.timeGrid=i,r.calendar.registerInteractiveComponent(n,{el:n.timeGrid.el}),n}return n(r,e),r.prototype.destroy=function(){e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},r.prototype.render=function(e){var t=e.dateProfile,r=e.dayTable,i=this.dayRanges=this.buildDayRanges(r,t,this.dateEnv);this.timeGrid.receiveProps(o({},this.slicer.sliceProps(e,t,null,this.timeGrid,i),{dateProfile:t,cells:r.cells[0]}))},r.prototype.renderNowIndicator=function(e){this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(e,this.timeGrid,this.dayRanges),e)},r.prototype.buildPositionCaches=function(){this.timeGrid.buildPositionCaches()},r.prototype.queryHit=function(e,t){var r=this.timeGrid.positionToHit(e,t);if(r)return{component:this.timeGrid,dateSpan:r.dateSpan,dayEl:r.dayEl,rect:{left:r.relativeRect.left,right:r.relativeRect.right,top:r.relativeRect.top,bottom:r.relativeRect.bottom},layer:0}},r}(t.DateComponent);function v(e,t,r){for(var i=[],n=0,o=e.headerDates;n<o.length;n++){var s=o[n];i.push({start:r.add(s,t.minTime),end:r.add(s,t.maxTime)})}return i}var S=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.sliceRange=function(e,r){for(var i=[],n=0;n<r.length;n++){var o=t.intersectRanges(e,r[n]);o&&i.push({start:o.start,end:o.end,isStart:o.start.valueOf()===e.start.valueOf(),isEnd:o.end.valueOf()===e.end.valueOf(),col:n})}return i},r}(t.Slicer),C=function(e){function i(i,n,o,s){var a=e.call(this,i,n,o,s)||this;return a.buildDayTable=t.memoize(E),a.opt("columnHeader")&&(a.header=new t.DayHeader(a.context,a.el.querySelector(".fc-head-container"))),a.simpleTimeGrid=new y(a.context,a.timeGrid),a.dayGrid&&(a.simpleDayGrid=new r.SimpleDayGrid(a.context,a.dayGrid)),a}return n(i,e),i.prototype.destroy=function(){e.prototype.destroy.call(this),this.header&&this.header.destroy(),this.simpleTimeGrid.destroy(),this.simpleDayGrid&&this.simpleDayGrid.destroy()},i.prototype.render=function(t){e.prototype.render.call(this,t);var r=this.props.dateProfile,i=this.buildDayTable(r,this.dateProfileGenerator),n=this.splitter.splitProps(t);this.header&&this.header.receiveProps({dateProfile:r,dates:i.headerDates,datesRepDistinctDays:!0,renderIntroHtml:this.renderHeadIntroHtml}),this.simpleTimeGrid.receiveProps(o({},n.timed,{dateProfile:r,dayTable:i})),this.simpleDayGrid&&this.simpleDayGrid.receiveProps(o({},n.allDay,{dateProfile:r,dayTable:i,nextDayThreshold:this.nextDayThreshold,isRigid:!1}))},i.prototype.renderNowIndicator=function(e){this.simpleTimeGrid.renderNowIndicator(e)},i}(m);function E(e,r){var i=new t.DaySeries(e.renderRange,r);return new t.DayTable(i,!1)}var b=t.createPlugin({defaultView:"timeGridWeek",views:{timeGrid:{class:C,allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0},timeGridDay:{type:"timeGrid",duration:{days:1}},timeGridWeek:{type:"timeGrid",duration:{weeks:1}}}});e.AbstractTimeGridView=m,e.TimeGrid=p,e.TimeGridSlicer=S,e.TimeGridView=C,e.buildDayRanges=v,e.buildDayTable=E,e.default=b,Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
{
"name": "@fullcalendar/timegrid",
"version": "4.3.0",
"title": "FullCalendar Time Grid Plugin",
"description": "Display your events on a grid of time slots",
"keywords": [
"calendar",
"event",
"full-sized"
],
"homepage": "https://fullcalendar.io/",
"docs": "https://fullcalendar.io/docs/timegrid-view",
"bugs": "https://fullcalendar.io/reporting-bugs",
"repository": {
"type": "git",
"url": "https://github.com/fullcalendar/fullcalendar.git",
"homepage": "https://github.com/fullcalendar/fullcalendar"
},
"license": "MIT",
"author": {
"name": "Adam Shaw",
"email": "arshaw@arshaw.com",
"url": "http://arshaw.com/"
},
"copyright": "2019 Adam Shaw",
"dependencies": {
"@fullcalendar/daygrid": "~4.3.0"
},
"peerDependencies": {
"@fullcalendar/core": "~4.3.0"
},
"main": "main.js",
"module": "main.esm.js",
"unpkg": "main.min.js",
"types": "main.d.ts"
}
For complete licensing information, visit:
http://fullcalendar.io/scheduler/license
FullCalendar Scheduler is tri-licensed, meaning you must choose
one of three licenses to use. Here is a summary of those licenses:
- Commercial License
(a paid license, meant for commercial use)
http://fullcalendar.io/scheduler/license-details
- Creative Commons Non-Commercial No-Derivatives
(meant for trial and non-commercial use)
https://creativecommons.org/licenses/by-nc-nd/4.0/
- GPLv3 License
(meant for open-source projects)
http://www.gnu.org/licenses/gpl-3.0.en.html
# FullCalendar Timeline Plugin
Display events on a horizontal time axis (without resources)
[View the docs &raquo;](https://fullcalendar.io/docs/timeline-view-no-resources)
This package was created from the [FullCalendar monorepo &raquo;](https://github.com/fullcalendar/fullcalendar-scheduler)
/* Scroller
--------------------------------------------------------------------------------------------------*/
.fc-scroller-clip {
overflow: hidden;
/* for clipping scrollbars */
position: relative;
/* so things like scrollfollowers can attach to this */
}
/* supresses rendering of native scrollbars */
/* on .fc-scroller */
.fc-no-scrollbars {
background: rgba(255, 255, 255, 0);
/* hack for dynamic DOM nodes (in Chrome OSX at least) */
}
.fc-no-scrollbars::-webkit-scrollbar {
width: 0;
height: 0;
}
.fc-scroller-canvas {
position: relative;
/* origin for bg */
box-sizing: border-box;
/* so that padding (for gutter) will be part of height */
min-height: 100%;
}
.fc-scroller-canvas > .fc-bg {
z-index: 1;
/* make default? */
}
.fc-scroller-canvas > .fc-content {
z-index: 2;
/* make default? */
position: relative;
/* origin for inner content */
border-style: solid;
border-width: 0;
}
.fc-scroller-canvas.fc-gutter-left > .fc-content {
border-left-width: 1px;
margin-left: -1px;
}
.fc-scroller-canvas.fc-gutter-right > .fc-content {
border-right-width: 1px;
margin-right: -1px;
}
.fc-scroller-canvas.fc-gutter-top > .fc-content {
border-top-width: 1px;
margin-top: -1px;
}
/* content is responsible for bottom border */
/* View Structure
--------------------------------------------------------------------------------------------------*/
.fc-rtl .fc-timeline {
direction: rtl;
}
.fc-scrolled .fc-head .fc-scroller {
z-index: 2;
/* so drop shadow will go above body panes */
}
.fc-timeline.fc-scrolled .fc-head .fc-scroller {
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.075);
}
.fc-timeline .fc-body .fc-scroller {
z-index: 1;
}
/*
on most tables that expand to the edges, kill the outer border,
because the container elements take care of it.
example tables:
.fc-scroller-canvas .fc-content table
.fc-scroller-canvas .fc-bg .fc-slats table
*/
.fc-timeline .fc-scroller-canvas > div > table,
.fc-timeline .fc-scroller-canvas > div > div > table {
border-style: hidden;
}
/*
for resource rows (in both the spreadsheet and timeline areas),
undo previous rule in order to always show last border.
*/
.fc-timeline .fc-scroller-canvas > .fc-content > .fc-rows > table {
border-bottom-style: none;
}
/* Table Cell Common
--------------------------------------------------------------------------------------------------*/
.fc-timeline th,
.fc-timeline td {
white-space: nowrap;
}
.fc-timeline .fc-cell-content {
overflow: hidden;
}
.fc-timeline .fc-cell-text {
display: inline-block;
padding-left: 4px;
padding-right: 4px;
}
/*
Cells at the start of a week
TODO: figure out better styling
.fc-ltr .fc-timeline .fc-em-cell div {
border-left: 3px solid #eee;
height: 100%;
}
.fc-rtl .fc-timeline .fc-em-cell {
border-right-width: 3px;
}
*/
/* head */
.fc-timeline th {
vertical-align: middle;
}
.fc-timeline .fc-head .fc-cell-content {
padding-top: 3px;
padding-bottom: 3px;
}
.fc-timeline .fc-head .fc-time-area .fc-cell-content {
overflow: visible;
}
/* Time Area
--------------------------------------------------------------------------------------------------*/
.fc-time-area col {
min-width: 2.2em;
/* detected by JS */
}
/* head */
.fc-ltr .fc-time-area .fc-chrono th {
text-align: left;
}
.fc-rtl .fc-time-area .fc-chrono th {
text-align: right;
}
/* body slats (vertical lines) */
.fc-time-area .fc-slats {
/* fc-bg is responsible for a lot of this now! */
position: absolute;
z-index: 1;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.fc-time-area .fc-slats table {
height: 100%;
}
.fc-time-area .fc-slats .fc-minor {
border-style: dotted;
}
.fc-time-area .fc-slats td {
border-width: 0 1px;
/* need to do this. sometimes -1 margin wouldn't hide the dotted */
}
.fc-ltr .fc-time-area .fc-slats td {
border-right-width: 0;
}
.fc-rtl .fc-time-area .fc-slats td {
border-left-width: 0;
}
/* body content containers
can be within rows or directly within the pane's content
*/
.fc-time-area .fc-bgevent-container,
.fc-time-area .fc-highlight-container {
position: absolute;
z-index: 2;
/* only for directly within pane. not for row. overridden later */
top: 0;
bottom: 0;
width: 0;
}
.fc-ltr .fc-time-area .fc-mirror-container,
.fc-ltr .fc-time-area .fc-bgevent-container,
.fc-ltr .fc-time-area .fc-highlight-container {
left: 0;
}
.fc-rtl .fc-time-area .fc-mirror-container,
.fc-rtl .fc-time-area .fc-bgevent-container,
.fc-rtl .fc-time-area .fc-highlight-container {
right: 0;
}
.fc-time-area .fc-bgevent,
.fc-time-area .fc-highlight {
position: absolute;
top: 0;
bottom: 0;
}
/* Now Indicator
--------------------------------------------------------------------------------------------------*/
.fc-timeline .fc-now-indicator {
/* both the arrow and the line */
z-index: 3;
/* one above scroller's fc-content */
top: 0;
}
.fc-time-area .fc-now-indicator-arrow {
margin: 0 -6px;
/* 5, then one more to counteract scroller's negative margins */
/* triangle pointing down... */
border-width: 6px 5px 0 5px;
border-left-color: transparent;
border-right-color: transparent;
}
.fc-time-area .fc-now-indicator-line {
margin: 0 -1px;
/* counteract scroller's negative margins */
bottom: 0;
border-left-width: 1px;
}
/* Event Container
--------------------------------------------------------------------------------------------------*/
.fc-time-area .fc-event-container {
position: relative;
z-index: 2;
/* above bgevent and highlight */
width: 0;
/* for event positioning. will end up on correct side based on dir */
}
.fc-time-area .fc-mirror-container {
/* also an fc-event-container */
position: absolute;
z-index: 3;
top: 0;
}
.fc-time-area .fc-event-container {
padding-bottom: 8px;
top: -1px;
}
.fc-time-area tr:first-child .fc-event-container {
top: 0;
}
.fc-no-overlap .fc-time-area .fc-event-container {
padding-bottom: 0;
top: 0;
}
/* Time Grid Events
--------------------------------------------------------------------------------------------------*/
.fc-timeline-event {
position: absolute;
display: flex;
border-radius: 0;
padding: 2px 1px;
margin-bottom: 1px;
}
.fc-no-overlap .fc-timeline-event {
padding-top: 5px;
padding-bottom: 5px;
margin-bottom: 0;
}
.fc-ltr .fc-timeline-event {
flex-direction: row;
margin-right: 1px;
}
.fc-rtl .fc-timeline-event {
margin-left: 1px;
}
.fc-timeline-event .fc-time-wrap {
flex-shrink: 0;
min-width: 0;
}
.fc-timeline-event .fc-title-wrap {
flex-grow: 1;
min-width: 0;
}
.fc-timeline-event .fc-time,
.fc-timeline-event .fc-title {
display: inline-block;
vertical-align: top;
max-width: 100%;
padding: 0 2px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
}
.fc-timeline-event .fc-time {
font-weight: bold;
}
.fc-timeline-event.fc-not-start:before,
.fc-timeline-event.fc-not-end:after {
content: "";
align-self: center;
width: 0;
height: 0;
margin: 0 1px;
border: 5px solid #000;
border-top-color: transparent;
border-bottom-color: transparent;
opacity: 0.5;
}
.fc-ltr .fc-timeline-event.fc-not-start:before,
.fc-rtl .fc-timeline-event.fc-not-end:after {
border-left: 0;
}
.fc-ltr .fc-timeline-event.fc-not-end:after,
.fc-rtl .fc-timeline-event.fc-not-start:before {
border-right: 0;
}
// Generated by dts-bundle v0.7.3-fork.1
// Dependencies for this module:
// ../../../../../@fullcalendar/core
declare module '@fullcalendar/timeline' {
import TimelineView from '@fullcalendar/timeline/TimelineView';
export { TimelineView };
export { default as TimelineLane } from '@fullcalendar/timeline/TimelineLane';
export { default as ScrollJoiner } from '@fullcalendar/timeline/util/ScrollJoiner';
export { default as StickyScroller } from '@fullcalendar/timeline/util/StickyScroller';
export { default as TimeAxis } from '@fullcalendar/timeline/TimeAxis';
export { default as HeaderBodyLayout } from '@fullcalendar/timeline/HeaderBodyLayout';
const _default: import("@fullcalendar/core").PluginDef;
export default _default;
}
declare module '@fullcalendar/timeline/TimelineView' {
import {
ComponentContext,
DateProfile,
DateProfileGenerator,
Duration,
Hit,
View,
ViewProps,
ViewSpec
} from '@fullcalendar/core';
import TimeAxis from '@fullcalendar/timeline/TimeAxis';
import TimelineLane from '@fullcalendar/timeline/TimelineLane';
export {TimelineView as default, TimelineView};
class TimelineView extends View {
timeAxis: TimeAxis;
lane: TimelineLane;
constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement);
destroy(): void;
renderSkeletonHtml(): string;
render(props: ViewProps): void;
updateSize(isResize: any, totalHeight: any, isAuto: any): void;
getNowIndicatorUnit(dateProfile: DateProfile): string;
renderNowIndicator(date: any): void;
unrenderNowIndicator(): void;
computeDateScroll(duration: Duration): {
left: number;
};
applyScroll(scroll: any, isResize: any): void;
applyDateScroll(scroll: any): void;
queryScroll(): {
top: number;
left: number;
};
buildPositionCaches(): void;
queryHit(positionLeft: number, positionTop: number, elWidth: number, elHeight: number): Hit;
}
}
declare module '@fullcalendar/timeline/TimelineLane' {
import {
ComponentContext,
DateComponent,
DateMarker,
DateProfile,
DateSpan,
Duration,
EventInteractionState,
EventSegUiInteractionState,
EventStore,
EventUiHash,
Seg
} from '@fullcalendar/core';
import TimeAxis from '@fullcalendar/timeline/TimeAxis';
export interface TimelineLaneSeg extends Seg {
start: DateMarker;
end: DateMarker;
}
export interface TimelineLaneProps {
dateProfile: DateProfile;
nextDayThreshold: Duration;
businessHours: EventStore | null;
eventStore: EventStore | null;
eventUiBases: EventUiHash;
dateSelection: DateSpan | null;
eventSelection: string;
eventDrag: EventInteractionState | null;
eventResize: EventInteractionState | null;
}
export { TimelineLane as default, TimelineLane };
class TimelineLane extends DateComponent<TimelineLaneProps> {
timeAxis: TimeAxis;
constructor(context: ComponentContext, fgContainerEl: HTMLElement, bgContainerEl: HTMLElement, timeAxis: TimeAxis);
render(props: TimelineLaneProps): void;
destroy(): void;
_renderEventDrag(state: EventSegUiInteractionState): void;
_unrenderEventDrag(state: EventSegUiInteractionState): void;
_renderEventResize(state: EventSegUiInteractionState): void;
_unrenderEventResize(state: EventSegUiInteractionState): void;
updateSize(isResize: boolean): void;
}
}
declare module '@fullcalendar/timeline/util/ScrollJoiner' {
import ClippedScroller from '@fullcalendar/timeline/util/ClippedScroller';
export { ScrollJoiner as default, ScrollJoiner };
class ScrollJoiner {
axis: any;
scrollers: ClippedScroller[];
masterScroller: ClippedScroller;
constructor(axis: any, scrollers: ClippedScroller[]);
initScroller(scroller: ClippedScroller): void;
assignMasterScroller(scroller: any): void;
unassignMasterScroller(): void;
update(): void;
}
}
declare module '@fullcalendar/timeline/util/StickyScroller' {
import {Point, Rect} from '@fullcalendar/core';
import EnhancedScroller from '@fullcalendar/timeline/util/EnhancedScroller';
interface ElementGeom {
parentBound: Rect;
naturalBound: Rect | null;
elWidth: number;
elHeight: number;
computedTextAlign: string;
intendedTextAlign: string;
}
export { StickyScroller as default, StickyScroller };
class StickyScroller {
scroller: EnhancedScroller;
usingRelative: boolean | null;
constructor(scroller: EnhancedScroller, isRtl: boolean, isVertical: boolean);
destroy(): void;
updateSize: () => void;
queryElGeoms(els: HTMLElement[]): ElementGeom[];
computeElDestinations(elGeoms: ElementGeom[], viewportWidth: number): Point[];
}
export {};
}
declare module '@fullcalendar/timeline/TimeAxis' {
import {Component, ComponentContext, DateMarker, DateProfile, Duration} from '@fullcalendar/core';
import HeaderBodyLayout from '@fullcalendar/timeline/HeaderBodyLayout';
import TimelineHeader from '@fullcalendar/timeline/TimelineHeader';
import TimelineSlats from '@fullcalendar/timeline/TimelineSlats';
import {TimelineDateProfile} from '@fullcalendar/timeline/timeline-date-profile';
import TimelineNowIndicator from '@fullcalendar/timeline/TimelineNowIndicator';
import StickyScroller from '@fullcalendar/timeline/util/StickyScroller';
export interface TimeAxisProps {
dateProfile: DateProfile;
}
export { TimeAxis as default, TimeAxis };
class TimeAxis extends Component<TimeAxisProps> {
layout: HeaderBodyLayout;
header: TimelineHeader;
slats: TimelineSlats;
nowIndicator: TimelineNowIndicator;
headStickyScroller: StickyScroller;
bodyStickyScroller: StickyScroller;
tDateProfile: TimelineDateProfile;
constructor(context: ComponentContext, headerContainerEl: any, bodyContainerEl: any);
destroy(): void;
render(props: TimeAxisProps): void;
getNowIndicatorUnit(dateProfile: DateProfile): string;
renderNowIndicator(date: any): void;
unrenderNowIndicator(): void;
updateSize(isResize: any, totalHeight: any, isAuto: any): void;
updateStickyScrollers(): void;
computeSlotWidth(): any;
computeDefaultSlotWidth(tDateProfile: any): number;
applySlotWidth(slotWidth: number | string): void;
computeDateSnapCoverage(date: DateMarker): number;
dateToCoord(date: any): any;
rangeToCoords(range: any): {
right: any;
left: any;
};
computeDateScroll(duration: Duration): {
left: number;
};
queryDateScroll(): {
left: number;
};
applyDateScroll(scroll: any): void;
}
}
declare module '@fullcalendar/timeline/HeaderBodyLayout' {
import ClippedScroller from '@fullcalendar/timeline/util/ClippedScroller';
import ScrollJoiner from '@fullcalendar/timeline/util/ScrollJoiner';
export { HeaderBodyLayout as default, HeaderBodyLayout };
class HeaderBodyLayout {
headerScroller: ClippedScroller;
bodyScroller: ClippedScroller;
scrollJoiner: ScrollJoiner;
constructor(headerContainerEl: any, bodyContainerEl: any, verticalScroll: any);
destroy(): void;
setHeight(totalHeight: any, isAuto: any): void;
queryHeadHeight(): number;
}
}
declare module '@fullcalendar/timeline/util/ClippedScroller' {
import {ScrollbarWidths} from '@fullcalendar/core';
import EnhancedScroller from '@fullcalendar/timeline/util/EnhancedScroller';
export { ClippedScroller as default, ClippedScroller };
class ClippedScroller {
el: HTMLElement;
enhancedScroll: EnhancedScroller;
isHScrollbarsClipped: boolean;
isVScrollbarsClipped: boolean;
constructor(overflowX: string, overflowY: string, parentEl: HTMLElement);
destroy(): void;
updateSize(): void;
setHeight(height: number | string): void;
getScrollbarWidths(): ScrollbarWidths;
}
}
declare module '@fullcalendar/timeline/util/EnhancedScroller' {
import {EmitterInterface, ScrollComponent} from '@fullcalendar/core';
import ScrollerCanvas from '@fullcalendar/timeline/util/ScrollerCanvas';
export { EnhancedScroller as default, EnhancedScroller };
class EnhancedScroller extends ScrollComponent {
on: EmitterInterface['on'];
one: EmitterInterface['one'];
off: EmitterInterface['off'];
trigger: EmitterInterface['trigger'];
triggerWith: EmitterInterface['triggerWith'];
hasHandlers: EmitterInterface['hasHandlers'];
canvas: ScrollerCanvas;
isScrolling: boolean;
isTouching: boolean;
isMoving: boolean;
isTouchScrollEnabled: boolean;
preventTouchScrollHandler: any;
requestMovingEnd: any;
constructor(overflowX: string, overflowY: string);
destroy(): void;
disableTouchScroll(): void;
enableTouchScroll(): void;
bindPreventTouchScroll(): void;
unbindPreventTouchScroll(): void;
bindHandlers(): void;
unbindHandlers(): void;
reportScroll: () => void;
reportScrollStart: () => void;
reportMovingEnd(): void;
reportScrollEnd(): void;
reportTouchStart: () => void;
reportTouchEnd: () => void;
getScrollLeft(): number;
setScrollLeft(val: any): void;
getScrollFromLeft(): number;
}
}
declare module '@fullcalendar/timeline/TimelineHeader' {
import {Component, ComponentContext, DateProfile} from '@fullcalendar/core';
import {TimelineDateProfile} from '@fullcalendar/timeline/timeline-date-profile';
export interface TimelineHeaderProps {
dateProfile: DateProfile;
tDateProfile: TimelineDateProfile;
}
export {TimelineHeader as default, TimelineHeader};
class TimelineHeader extends Component<TimelineHeaderProps> {
tableEl: HTMLElement;
slatColEls: HTMLElement[];
innerEls: HTMLElement[];
constructor(context: ComponentContext, parentEl: HTMLElement);
destroy(): void;
render(props: TimelineHeaderProps): void;
renderDates(tDateProfile: TimelineDateProfile): void;
}
}
declare module '@fullcalendar/timeline/TimelineSlats' {
import {Component, ComponentContext, DateProfile, PositionCache} from '@fullcalendar/core';
import {TimelineDateProfile} from '@fullcalendar/timeline/timeline-date-profile';
export interface TimelineSlatsProps {
dateProfile: DateProfile;
tDateProfile: TimelineDateProfile;
}
export {TimelineSlats as default, TimelineSlats};
class TimelineSlats extends Component<TimelineSlatsProps> {
el: HTMLElement;
slatColEls: HTMLElement[];
slatEls: HTMLElement[];
outerCoordCache: PositionCache;
innerCoordCache: PositionCache;
constructor(context: ComponentContext, parentEl: HTMLElement);
destroy(): void;
render(props: TimelineSlatsProps): void;
renderDates(tDateProfile: TimelineDateProfile): void;
slatCellHtml(date: any, isEm: any, tDateProfile: TimelineDateProfile): string;
updateSize(): void;
positionToHit(leftPosition: any): {
dateSpan: {
range: {
start: Date;
end: Date;
};
allDay: boolean;
};
dayEl: HTMLElement;
left: any;
right: any;
};
}
}
declare module '@fullcalendar/timeline/timeline-date-profile' {
import {DateEnv, DateMarker, DateProfile, DateRange, Duration, View} from '@fullcalendar/core';
export interface TimelineDateProfile {
labelInterval: Duration;
slotDuration: Duration;
headerFormats: any;
isTimeScale: boolean;
largeUnit: string;
emphasizeWeeks: boolean;
snapDuration: Duration;
snapsPerSlot: number;
normalizedRange: DateRange;
timeWindowMs: number;
slotDates: DateMarker[];
isWeekStarts: boolean[];
snapDiffToIndex: number[];
snapIndexToDiff: number[];
snapCnt: number;
slotCnt: number;
cellRows: TimelineHeaderCell[][];
}
export interface TimelineHeaderCell {
text: string;
spanHtml: string;
date: DateMarker;
colspan: number;
isWeekStart: boolean;
}
export function buildTimelineDateProfile(dateProfile: DateProfile, view: View): TimelineDateProfile;
export function normalizeDate(date: DateMarker, tDateProfile: TimelineDateProfile, dateEnv: DateEnv): DateMarker;
export function normalizeRange(range: DateRange, tDateProfile: TimelineDateProfile, dateEnv: DateEnv): DateRange;
export function isValidDate(date: DateMarker, tDateProfile: TimelineDateProfile, dateProfile: DateProfile, view: View): boolean;
}
declare module '@fullcalendar/timeline/TimelineNowIndicator' {
export { TimelineNowIndicator as default, TimelineNowIndicator };
class TimelineNowIndicator {
headParent: HTMLElement;
bodyParent: HTMLElement;
arrowEl: HTMLElement;
lineEl: HTMLElement;
constructor(headParent: HTMLElement, bodyParent: HTMLElement);
render(coord: number, isRtl: boolean): void;
unrender(): void;
}
}
declare module '@fullcalendar/timeline/util/ScrollerCanvas' {
export { ScrollerCanvas as default, ScrollerCanvas };
class ScrollerCanvas {
el: HTMLElement;
contentEl: HTMLElement;
bgEl: HTMLElement;
gutters: any;
width: any;
minWidth: any;
constructor();
setGutters(gutters: any): void;
setWidth(width: any): void;
setMinWidth(minWidth: any): void;
clearWidth(): void;
updateSize(): void;
}
}
/*!
FullCalendar Timeline Plugin v4.3.0
Docs & License: https://fullcalendar.io/scheduler
(c) 2019 Adam Shaw
*/
import {
addDays,
addMs,
applyStyle,
applyStyleProp,
asRoughMinutes,
asRoughMs,
asRoughSeconds,
buildGotoAnchorHtml,
Component,
computeEdges,
computeHeightAndMargins,
computeVisibleDayRange,
config,
createDuration,
createElement,
createFormatter,
createPlugin,
cssToStr,
DateComponent,
debounce,
diffWholeDays,
EmitterMixin,
FgEventRenderer,
FillRenderer,
findChildren,
findElements,
forceClassName,
getDayClasses,
greatestDurationDenominator,
htmlEscape,
htmlToElement,
intersectRanges,
isInt,
isSingleDay,
memoizeRendering,
multiplyDuration,
padStart,
PositionCache,
preventDefault,
rangeContainsMarker,
removeElement,
ScrollComponent,
Slicer,
startOfDay,
translateRect,
View,
wholeDivideDurations
} from '@fullcalendar/core';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
/*
A rectangular area of content that lives within a Scroller.
Can have "gutters", areas of dead spacing around the perimeter.
Also very useful for forcing a width, which a Scroller cannot do alone.
Has a content area that lives above a background area.
*/
var ScrollerCanvas = /** @class */ (function () {
function ScrollerCanvas() {
this.gutters = {};
this.el = htmlToElement("<div class=\"fc-scroller-canvas\"> <div class=\"fc-content\"></div> <div class=\"fc-bg\"></div> </div>");
this.contentEl = this.el.querySelector('.fc-content');
this.bgEl = this.el.querySelector('.fc-bg');
}
/*
If falsy, resets all the gutters to 0
*/
ScrollerCanvas.prototype.setGutters = function (gutters) {
if (!gutters) {
this.gutters = {};
}
else {
__assign(this.gutters, gutters);
}
this.updateSize();
};
ScrollerCanvas.prototype.setWidth = function (width) {
this.width = width;
this.updateSize();
};
ScrollerCanvas.prototype.setMinWidth = function (minWidth) {
this.minWidth = minWidth;
this.updateSize();
};
ScrollerCanvas.prototype.clearWidth = function () {
this.width = null;
this.minWidth = null;
this.updateSize();
};
ScrollerCanvas.prototype.updateSize = function () {
var _a = this, gutters = _a.gutters, el = _a.el;
// is border-box (width includes padding)
forceClassName(el, 'fc-gutter-left', gutters.left);
forceClassName(el, 'fc-gutter-right', gutters.right);
forceClassName(el, 'fc-gutter-top', gutters.top);
forceClassName(el, 'fc-gutter-bottom', gutters.bottom);
applyStyle(el, {
paddingLeft: gutters.left || '',
paddingRight: gutters.right || '',
paddingTop: gutters.top || '',
paddingBottom: gutters.bottom || '',
width: (this.width != null) ?
this.width + (gutters.left || 0) + (gutters.right || 0) :
'',
minWidth: (this.minWidth != null) ?
this.minWidth + (gutters.left || 0) + (gutters.right || 0) :
''
});
applyStyle(this.bgEl, {
left: gutters.left || '',
right: gutters.right || '',
top: gutters.top || '',
bottom: gutters.bottom || ''
});
};
return ScrollerCanvas;
}());
var EnhancedScroller = /** @class */ (function (_super) {
__extends(EnhancedScroller, _super);
function EnhancedScroller(overflowX, overflowY) {
var _this = _super.call(this, overflowX, overflowY) || this;
// Scroll Events
// ----------------------------------------------------------------------------------------------
_this.reportScroll = function () {
if (!_this.isScrolling) {
_this.reportScrollStart();
}
_this.trigger('scroll');
_this.isMoving = true;
_this.requestMovingEnd();
};
_this.reportScrollStart = function () {
if (!_this.isScrolling) {
_this.isScrolling = true;
_this.trigger('scrollStart', _this.isTouching); // created in constructor
}
};
// Touch Events
// ----------------------------------------------------------------------------------------------
// will fire *before* the scroll event is fired
_this.reportTouchStart = function () {
_this.isTouching = true;
};
_this.reportTouchEnd = function () {
if (_this.isTouching) {
_this.isTouching = false;
// if touch scrolling was re-enabled during a recent touch scroll
// then unbind the handlers that are preventing it from happening.
if (_this.isTouchScrollEnabled) {
_this.unbindPreventTouchScroll(); // won't do anything if not bound
}
// if the user ended their touch, and the scroll area wasn't moving,
// we consider this to be the end of the scroll.
if (!_this.isMoving) {
_this.reportScrollEnd(); // won't fire if already ended
}
}
};
_this.isScrolling = false;
_this.isTouching = false;
_this.isMoving = false;
_this.isTouchScrollEnabled = true;
_this.requestMovingEnd = debounce(_this.reportMovingEnd, 500);
_this.canvas = new ScrollerCanvas();
_this.el.appendChild(_this.canvas.el);
_this.applyOverflow();
_this.bindHandlers();
return _this;
}
EnhancedScroller.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.unbindHandlers();
};
// Touch scroll prevention
// ----------------------------------------------------------------------------------------------
EnhancedScroller.prototype.disableTouchScroll = function () {
this.isTouchScrollEnabled = false;
this.bindPreventTouchScroll(); // will be unbound in enableTouchScroll or reportTouchEnd
};
EnhancedScroller.prototype.enableTouchScroll = function () {
this.isTouchScrollEnabled = true;
// only immediately unbind if a touch event is NOT in progress.
// otherwise, it will be handled by reportTouchEnd.
if (!this.isTouching) {
this.unbindPreventTouchScroll();
}
};
EnhancedScroller.prototype.bindPreventTouchScroll = function () {
if (!this.preventTouchScrollHandler) {
this.el.addEventListener('touchmove', (this.preventTouchScrollHandler = preventDefault));
}
};
EnhancedScroller.prototype.unbindPreventTouchScroll = function () {
if (this.preventTouchScrollHandler) {
this.el.removeEventListener('touchmove', this.preventTouchScrollHandler);
this.preventTouchScrollHandler = null;
}
};
// Handlers
// ----------------------------------------------------------------------------------------------
EnhancedScroller.prototype.bindHandlers = function () {
this.el.addEventListener('scroll', this.reportScroll);
this.el.addEventListener('touchstart', this.reportTouchStart, { passive: true });
this.el.addEventListener('touchend', this.reportTouchEnd);
};
EnhancedScroller.prototype.unbindHandlers = function () {
this.el.removeEventListener('scroll', this.reportScroll);
this.el.removeEventListener('touchstart', this.reportTouchStart, { passive: true });
this.el.removeEventListener('touchend', this.reportTouchEnd);
};
EnhancedScroller.prototype.reportMovingEnd = function () {
this.isMoving = false;
// only end the scroll if not currently touching.
// if touching, the scrolling will end later, on touchend.
if (!this.isTouching) {
this.reportScrollEnd();
}
};
EnhancedScroller.prototype.reportScrollEnd = function () {
if (this.isScrolling) {
this.trigger('scrollEnd');
this.isScrolling = false;
}
};
// Horizontal Scroll Normalization
// ----------------------------------------------------------------------------------------------
// http://stackoverflow.com/questions/24276619/better-way-to-get-the-viewport-of-a-scrollable-div-in-rtl-mode/24394376#24394376
// TODO: move all this to util functions
/*
If RTL, and scrolled to the left, returns NEGATIVE value (like Firefox)
*/
EnhancedScroller.prototype.getScrollLeft = function () {
var el = this.el;
var direction = window.getComputedStyle(el).direction;
var val = el.scrollLeft;
if (direction === 'rtl') {
switch (getRtlScrollSystem()) {
case 'positive':
val = (val + el.clientWidth) - el.scrollWidth;
break;
case 'reverse':
val = -val;
break;
}
}
return val;
};
/*
Accepts a NEGATIVE value for when scrolled in RTL
*/
EnhancedScroller.prototype.setScrollLeft = function (val) {
var el = this.el;
var direction = window.getComputedStyle(el).direction;
if (direction === 'rtl') {
switch (getRtlScrollSystem()) {
case 'positive':
val = (val - el.clientWidth) + el.scrollWidth;
break;
case 'reverse':
val = -val;
break;
}
}
el.scrollLeft = val;
};
/*
Always returns the number of pixels scrolled from the leftmost position (even if RTL).
Always positive.
*/
EnhancedScroller.prototype.getScrollFromLeft = function () {
var el = this.el;
var direction = window.getComputedStyle(el).direction;
var val = el.scrollLeft;
if (direction === 'rtl') {
switch (getRtlScrollSystem()) {
case 'negative':
val = (val - el.clientWidth) + el.scrollWidth;
break;
case 'reverse':
val = (-val - el.clientWidth) + el.scrollWidth;
break;
}
}
return val;
};
return EnhancedScroller;
}(ScrollComponent));
EmitterMixin.mixInto(EnhancedScroller);
// Horizontal Scroll System Detection
// ----------------------------------------------------------------------------------------------
var _rtlScrollSystem;
function getRtlScrollSystem() {
return _rtlScrollSystem || (_rtlScrollSystem = detectRtlScrollSystem());
}
function detectRtlScrollSystem() {
var el = htmlToElement("<div style=\" position: absolute; top: -1000px; width: 1px; height: 1px; overflow: scroll; direction: rtl; font-size: 100px; \">A</div>");
document.body.appendChild(el);
var system;
if (el.scrollLeft > 0) {
system = 'positive';
}
else {
el.scrollLeft = 1;
if (el.scrollLeft > 0) {
system = 'reverse';
}
else {
system = 'negative';
}
}
removeElement(el);
return system;
}
/*
A Scroller, but with a wrapping div that allows "clipping" away of native scrollbars,
giving the appearance that there are no scrollbars.
*/
var ClippedScroller = /** @class */ (function () {
/*
Received overflows can be set to 'clipped', meaning scrollbars shouldn't be visible
to the user, but the area should still scroll.
*/
function ClippedScroller(overflowX, overflowY, parentEl) {
this.isHScrollbarsClipped = false;
this.isVScrollbarsClipped = false;
if (overflowX === 'clipped-scroll') {
overflowX = 'scroll';
this.isHScrollbarsClipped = true;
}
if (overflowY === 'clipped-scroll') {
overflowY = 'scroll';
this.isVScrollbarsClipped = true;
}
this.enhancedScroll = new EnhancedScroller(overflowX, overflowY);
parentEl.appendChild(this.el = createElement('div', {
className: 'fc-scroller-clip'
}));
this.el.appendChild(this.enhancedScroll.el);
}
ClippedScroller.prototype.destroy = function () {
removeElement(this.el);
};
ClippedScroller.prototype.updateSize = function () {
var enhancedScroll = this.enhancedScroll;
var scrollEl = enhancedScroll.el;
var edges = computeEdges(scrollEl);
var cssProps = { marginLeft: 0, marginRight: 0, marginTop: 0, marginBottom: 0 };
// give the inner scrolling div negative margins so that its scrollbars
// are nudged outside of the bounding box of the wrapper, which is overflow:hidden
if (this.isVScrollbarsClipped) {
cssProps.marginLeft = -edges.scrollbarLeft;
cssProps.marginRight = -edges.scrollbarRight;
}
if (this.isHScrollbarsClipped) {
cssProps.marginBottom = -edges.scrollbarBottom;
}
applyStyle(scrollEl, cssProps);
// if we are attempting to hide the scrollbars offscreen, OSX/iOS will still
// display the floating scrollbars. attach a className to force-hide them.
if ((this.isHScrollbarsClipped || (enhancedScroll.overflowX === 'hidden')) && // should never show?
(this.isVScrollbarsClipped || (enhancedScroll.overflowY === 'hidden')) && // should never show?
!( // doesn't have any scrollbar mass
edges.scrollbarLeft ||
edges.scrollbarRight ||
edges.scrollbarBottom)) {
scrollEl.classList.add('fc-no-scrollbars');
}
else {
scrollEl.classList.remove('fc-no-scrollbars');
}
};
ClippedScroller.prototype.setHeight = function (height) {
this.enhancedScroll.setHeight(height);
};
/*
Accounts for 'clipped' scrollbars
*/
ClippedScroller.prototype.getScrollbarWidths = function () {
var widths = this.enhancedScroll.getScrollbarWidths();
if (this.isVScrollbarsClipped) {
widths.left = 0;
widths.right = 0;
}
if (this.isHScrollbarsClipped) {
widths.bottom = 0;
}
return widths;
};
return ClippedScroller;
}());
var ScrollJoiner = /** @class */ (function () {
function ScrollJoiner(axis, scrollers) {
this.axis = axis;
this.scrollers = scrollers;
for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
var scroller = _a[_i];
this.initScroller(scroller);
}
}
ScrollJoiner.prototype.initScroller = function (scroller) {
var _this = this;
var enhancedScroll = scroller.enhancedScroll;
// when the user scrolls via mousewheel, we know for sure the target
// scroller should be the master. capture the various x-browser events that fire.
var onScroll = function () {
_this.assignMasterScroller(scroller);
};
'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ').forEach(function (evName) {
enhancedScroll.el.addEventListener(evName, onScroll);
});
enhancedScroll
.on('scrollStart', function () {
if (!_this.masterScroller) {
_this.assignMasterScroller(scroller);
}
})
.on('scroll', function () {
if (scroller === _this.masterScroller) {
for (var _i = 0, _a = _this.scrollers; _i < _a.length; _i++) {
var otherScroller = _a[_i];
if (otherScroller !== scroller) {
switch (_this.axis) {
case 'horizontal':
otherScroller.enhancedScroll.el.scrollLeft = enhancedScroll.el.scrollLeft;
break;
case 'vertical':
otherScroller.enhancedScroll.setScrollTop(enhancedScroll.getScrollTop());
break;
}
}
}
}
})
.on('scrollEnd', function () {
if (scroller === _this.masterScroller) {
_this.unassignMasterScroller();
}
});
};
ScrollJoiner.prototype.assignMasterScroller = function (scroller) {
this.unassignMasterScroller();
this.masterScroller = scroller;
for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
var otherScroller = _a[_i];
if (otherScroller !== scroller) {
otherScroller.enhancedScroll.disableTouchScroll();
}
}
};
ScrollJoiner.prototype.unassignMasterScroller = function () {
if (this.masterScroller) {
for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
var otherScroller = _a[_i];
otherScroller.enhancedScroll.enableTouchScroll();
}
this.masterScroller = null;
}
};
ScrollJoiner.prototype.update = function () {
var allWidths = this.scrollers.map(function (scroller) { return scroller.getScrollbarWidths(); });
var maxLeft = 0;
var maxRight = 0;
var maxTop = 0;
var maxBottom = 0;
var widths;
var i;
for (var _i = 0, allWidths_1 = allWidths; _i < allWidths_1.length; _i++) {
widths = allWidths_1[_i];
maxLeft = Math.max(maxLeft, widths.left);
maxRight = Math.max(maxRight, widths.right);
maxTop = Math.max(maxTop, widths.top);
maxBottom = Math.max(maxBottom, widths.bottom);
}
for (i = 0; i < this.scrollers.length; i++) {
var scroller = this.scrollers[i];
widths = allWidths[i];
scroller.enhancedScroll.canvas.setGutters(this.axis === 'horizontal' ?
{
left: maxLeft - widths.left,
right: maxRight - widths.right
} :
{
top: maxTop - widths.top,
bottom: maxBottom - widths.bottom
});
}
};
return ScrollJoiner;
}());
var HeaderBodyLayout = /** @class */ (function () {
/*
verticalScroll = 'auto' | 'clipped-scroll'
*/
function HeaderBodyLayout(headerContainerEl, bodyContainerEl, verticalScroll) {
this.headerScroller = new ClippedScroller('clipped-scroll', 'hidden', headerContainerEl);
this.bodyScroller = new ClippedScroller('auto', verticalScroll, bodyContainerEl);
this.scrollJoiner = new ScrollJoiner('horizontal', [
this.headerScroller,
this.bodyScroller
]);
}
HeaderBodyLayout.prototype.destroy = function () {
this.headerScroller.destroy();
this.bodyScroller.destroy();
};
HeaderBodyLayout.prototype.setHeight = function (totalHeight, isAuto) {
var bodyHeight;
if (isAuto) {
bodyHeight = 'auto';
}
else {
bodyHeight = totalHeight - this.queryHeadHeight();
}
this.bodyScroller.setHeight(bodyHeight);
this.headerScroller.updateSize(); // adjusts gutters and classNames
this.bodyScroller.updateSize(); // adjusts gutters and classNames
this.scrollJoiner.update();
};
HeaderBodyLayout.prototype.queryHeadHeight = function () {
return this.headerScroller.enhancedScroll.canvas.contentEl.getBoundingClientRect().height;
};
return HeaderBodyLayout;
}());
var TimelineHeader = /** @class */ (function (_super) {
__extends(TimelineHeader, _super);
function TimelineHeader(context, parentEl) {
var _this = _super.call(this, context) || this;
parentEl.appendChild(_this.tableEl = createElement('table', {
className: _this.theme.getClass('tableGrid')
}));
return _this;
}
TimelineHeader.prototype.destroy = function () {
removeElement(this.tableEl);
_super.prototype.destroy.call(this);
};
TimelineHeader.prototype.render = function (props) {
this.renderDates(props.tDateProfile);
};
TimelineHeader.prototype.renderDates = function (tDateProfile) {
var _a = this, dateEnv = _a.dateEnv, theme = _a.theme;
var cellRows = tDateProfile.cellRows;
var lastRow = cellRows[cellRows.length - 1];
var isChrono = asRoughMs(tDateProfile.labelInterval) > asRoughMs(tDateProfile.slotDuration);
var oneDay = isSingleDay(tDateProfile.slotDuration);
var html = '<colgroup>';
// needs to be a col for each body slat. header cells will have colspans
for (var i = tDateProfile.slotCnt - 1; i >= 0; i--) {
html += '<col/>';
}
html += '</colgroup>';
html += '<tbody>';
for (var _i = 0, cellRows_1 = cellRows; _i < cellRows_1.length; _i++) {
var rowCells = cellRows_1[_i];
var isLast = rowCells === lastRow;
html += '<tr' + (isChrono && isLast ? ' class="fc-chrono"' : '') + '>';
for (var _b = 0, rowCells_1 = rowCells; _b < rowCells_1.length; _b++) {
var cell = rowCells_1[_b];
var headerCellClassNames = [theme.getClass('widgetHeader')];
if (cell.isWeekStart) {
headerCellClassNames.push('fc-em-cell');
}
if (oneDay) {
headerCellClassNames = headerCellClassNames.concat(getDayClasses(cell.date, this.props.dateProfile, this.context, true) // adds "today" class and other day-based classes
);
}
html +=
'<th class="' + headerCellClassNames.join(' ') + '"' +
' data-date="' + dateEnv.formatIso(cell.date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' +
(cell.colspan > 1 ? ' colspan="' + cell.colspan + '"' : '') +
'>' +
'<div class="fc-cell-content">' +
cell.spanHtml +
'</div>' +
'</th>';
}
html += '</tr>';
}
html += '</tbody>';
this.tableEl.innerHTML = html; // TODO: does this work cross-browser?
this.slatColEls = findElements(this.tableEl, 'col');
this.innerEls = findElements(this.tableEl.querySelector('tr:last-child'), // compound selector won't work because of query-root problem
'th .fc-cell-text');
findElements(this.tableEl.querySelectorAll('tr:not(:last-child)'), // compound selector won't work because of query-root problem
'th .fc-cell-text').forEach(function (innerEl) {
innerEl.classList.add('fc-sticky');
});
};
return TimelineHeader;
}(Component));
var TimelineSlats = /** @class */ (function (_super) {
__extends(TimelineSlats, _super);
function TimelineSlats(context, parentEl) {
var _this = _super.call(this, context) || this;
parentEl.appendChild(_this.el = createElement('div', { className: 'fc-slats' }));
return _this;
}
TimelineSlats.prototype.destroy = function () {
removeElement(this.el);
_super.prototype.destroy.call(this);
};
TimelineSlats.prototype.render = function (props) {
this.renderDates(props.tDateProfile);
};
TimelineSlats.prototype.renderDates = function (tDateProfile) {
var _a = this, theme = _a.theme, view = _a.view, dateEnv = _a.dateEnv;
var slotDates = tDateProfile.slotDates, isWeekStarts = tDateProfile.isWeekStarts;
var html = '<table class="' + theme.getClass('tableGrid') + '">' +
'<colgroup>';
for (var i = 0; i < slotDates.length; i++) {
html += '<col/>';
}
html += '</colgroup>';
html += '<tbody><tr>';
for (var i = 0; i < slotDates.length; i++) {
html += this.slatCellHtml(slotDates[i], isWeekStarts[i], tDateProfile);
}
html += '</tr></tbody></table>';
this.el.innerHTML = html;
this.slatColEls = findElements(this.el, 'col');
this.slatEls = findElements(this.el, 'td');
for (var i = 0; i < slotDates.length; i++) {
view.publiclyTrigger('dayRender', [
{
date: dateEnv.toDate(slotDates[i]),
el: this.slatEls[i],
view: view
}
]);
}
this.outerCoordCache = new PositionCache(this.el, this.slatEls, true, // isHorizontal
false // isVertical
);
// for the inner divs within the slats
// used for event rendering and scrollTime, to disregard slat border
this.innerCoordCache = new PositionCache(this.el, findChildren(this.slatEls, 'div'), true, // isHorizontal
false // isVertical
);
};
TimelineSlats.prototype.slatCellHtml = function (date, isEm, tDateProfile) {
var _a = this, theme = _a.theme, dateEnv = _a.dateEnv;
var classes;
if (tDateProfile.isTimeScale) {
classes = [];
classes.push(isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval)) ?
'fc-major' :
'fc-minor');
}
else {
classes = getDayClasses(date, this.props.dateProfile, this.context);
classes.push('fc-day');
}
classes.unshift(theme.getClass('widgetContent'));
if (isEm) {
classes.push('fc-em-cell');
}
return '<td class="' + classes.join(' ') + '"' +
' data-date="' + dateEnv.formatIso(date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' +
'><div></div></td>';
};
TimelineSlats.prototype.updateSize = function () {
this.outerCoordCache.build();
this.innerCoordCache.build();
};
TimelineSlats.prototype.positionToHit = function (leftPosition) {
var outerCoordCache = this.outerCoordCache;
var tDateProfile = this.props.tDateProfile;
var slatIndex = outerCoordCache.leftToIndex(leftPosition);
if (slatIndex != null) {
// somewhat similar to what TimeGrid does. consolidate?
var slatWidth = outerCoordCache.getWidth(slatIndex);
var partial = this.isRtl ?
(outerCoordCache.rights[slatIndex] - leftPosition) / slatWidth :
(leftPosition - outerCoordCache.lefts[slatIndex]) / slatWidth;
var localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot);
var start = this.dateEnv.add(tDateProfile.slotDates[slatIndex], multiplyDuration(tDateProfile.snapDuration, localSnapIndex));
var end = this.dateEnv.add(start, tDateProfile.snapDuration);
return {
dateSpan: {
range: { start: start, end: end },
allDay: !this.props.tDateProfile.isTimeScale
},
dayEl: this.slatColEls[slatIndex],
left: outerCoordCache.lefts[slatIndex],
right: outerCoordCache.rights[slatIndex]
};
}
return null;
};
return TimelineSlats;
}(Component));
var MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours
var MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour
var MAX_AUTO_CELLS = 200; // allows 4-days to have a :30 slot duration
config.MAX_TIMELINE_SLOTS = 1000;
// potential nice values for slot-duration and interval-duration
var STOCK_SUB_DURATIONS = [
{ years: 1 },
{ months: 1 },
{ days: 1 },
{ hours: 1 },
{ minutes: 30 },
{ minutes: 15 },
{ minutes: 10 },
{ minutes: 5 },
{ minutes: 1 },
{ seconds: 30 },
{ seconds: 15 },
{ seconds: 10 },
{ seconds: 5 },
{ seconds: 1 },
{ milliseconds: 500 },
{ milliseconds: 100 },
{ milliseconds: 10 },
{ milliseconds: 1 }
];
function buildTimelineDateProfile(dateProfile, view) {
var dateEnv = view.dateEnv;
var tDateProfile = {
labelInterval: queryDurationOption(view, 'slotLabelInterval'),
slotDuration: queryDurationOption(view, 'slotDuration')
};
validateLabelAndSlot(tDateProfile, dateProfile, dateEnv); // validate after computed grid duration
ensureLabelInterval(tDateProfile, dateProfile, dateEnv);
ensureSlotDuration(tDateProfile, dateProfile, dateEnv);
var input = view.opt('slotLabelFormat');
var rawFormats = Array.isArray(input) ?
input
: (input != null) ?
[input]
:
computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view);
tDateProfile.headerFormats = rawFormats.map(function (rawFormat) {
return createFormatter(rawFormat);
});
tDateProfile.isTimeScale = Boolean(tDateProfile.slotDuration.milliseconds);
var largeUnit = null;
if (!tDateProfile.isTimeScale) {
var slotUnit = greatestDurationDenominator(tDateProfile.slotDuration).unit;
if (/year|month|week/.test(slotUnit)) {
largeUnit = slotUnit;
}
}
tDateProfile.largeUnit = largeUnit;
tDateProfile.emphasizeWeeks =
isSingleDay(tDateProfile.slotDuration) &&
currentRangeAs('weeks', dateProfile, dateEnv) >= 2 &&
!view.opt('businessHours');
/*
console.log('label interval =', timelineView.labelInterval.humanize())
console.log('slot duration =', timelineView.slotDuration.humanize())
console.log('header formats =', timelineView.headerFormats)
console.log('isTimeScale', timelineView.isTimeScale)
console.log('largeUnit', timelineView.largeUnit)
*/
var rawSnapDuration = view.opt('snapDuration');
var snapDuration;
var snapsPerSlot;
if (rawSnapDuration) {
snapDuration = createDuration(rawSnapDuration);
snapsPerSlot = wholeDivideDurations(tDateProfile.slotDuration, snapDuration);
// ^ TODO: warning if not whole?
}
if (snapsPerSlot == null) {
snapDuration = tDateProfile.slotDuration;
snapsPerSlot = 1;
}
tDateProfile.snapDuration = snapDuration;
tDateProfile.snapsPerSlot = snapsPerSlot;
// more...
var timeWindowMs = asRoughMs(dateProfile.maxTime) - asRoughMs(dateProfile.minTime);
// TODO: why not use normalizeRange!?
var normalizedStart = normalizeDate(dateProfile.renderRange.start, tDateProfile, dateEnv);
var normalizedEnd = normalizeDate(dateProfile.renderRange.end, tDateProfile, dateEnv);
// apply minTime/maxTime
// TODO: View should be responsible.
if (tDateProfile.isTimeScale) {
normalizedStart = dateEnv.add(normalizedStart, dateProfile.minTime);
normalizedEnd = dateEnv.add(addDays(normalizedEnd, -1), dateProfile.maxTime);
}
tDateProfile.timeWindowMs = timeWindowMs;
tDateProfile.normalizedRange = { start: normalizedStart, end: normalizedEnd };
var slotDates = [];
var date = normalizedStart;
while (date < normalizedEnd) {
if (isValidDate(date, tDateProfile, dateProfile, view)) {
slotDates.push(date);
}
date = dateEnv.add(date, tDateProfile.slotDuration);
}
tDateProfile.slotDates = slotDates;
// more...
var snapIndex = -1;
var snapDiff = 0; // index of the diff :(
var snapDiffToIndex = [];
var snapIndexToDiff = [];
date = normalizedStart;
while (date < normalizedEnd) {
if (isValidDate(date, tDateProfile, dateProfile, view)) {
snapIndex++;
snapDiffToIndex.push(snapIndex);
snapIndexToDiff.push(snapDiff);
}
else {
snapDiffToIndex.push(snapIndex + 0.5);
}
date = dateEnv.add(date, tDateProfile.snapDuration);
snapDiff++;
}
tDateProfile.snapDiffToIndex = snapDiffToIndex;
tDateProfile.snapIndexToDiff = snapIndexToDiff;
tDateProfile.snapCnt = snapIndex + 1; // is always one behind
tDateProfile.slotCnt = tDateProfile.snapCnt / tDateProfile.snapsPerSlot;
// more...
tDateProfile.isWeekStarts = buildIsWeekStarts(tDateProfile, dateEnv);
tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv, view);
return tDateProfile;
}
/*
snaps to appropriate unit
*/
function normalizeDate(date, tDateProfile, dateEnv) {
var normalDate = date;
if (!tDateProfile.isTimeScale) {
normalDate = startOfDay(normalDate);
if (tDateProfile.largeUnit) {
normalDate = dateEnv.startOf(normalDate, tDateProfile.largeUnit);
}
}
return normalDate;
}
/*
snaps to appropriate unit
*/
function normalizeRange(range, tDateProfile, dateEnv) {
if (!tDateProfile.isTimeScale) {
range = computeVisibleDayRange(range);
if (tDateProfile.largeUnit) {
var dayRange = range; // preserve original result
range = {
start: dateEnv.startOf(range.start, tDateProfile.largeUnit),
end: dateEnv.startOf(range.end, tDateProfile.largeUnit)
};
// if date is partially through the interval, or is in the same interval as the start,
// make the exclusive end be the *next* interval
if (range.end.valueOf() !== dayRange.end.valueOf() || range.end <= range.start) {
range = {
start: range.start,
end: dateEnv.add(range.end, tDateProfile.slotDuration)
};
}
}
}
return range;
}
function isValidDate(date, tDateProfile, dateProfile, view) {
if (view.dateProfileGenerator.isHiddenDay(date)) {
return false;
}
else if (tDateProfile.isTimeScale) {
// determine if the time is within minTime/maxTime, which may have wacky values
var day = startOfDay(date);
var timeMs = date.valueOf() - day.valueOf();
var ms = timeMs - asRoughMs(dateProfile.minTime); // milliseconds since minTime
ms = ((ms % 86400000) + 86400000) % 86400000; // make negative values wrap to 24hr clock
return ms < tDateProfile.timeWindowMs; // before the maxTime?
}
else {
return true;
}
}
function queryDurationOption(view, name) {
var input = view.opt(name);
if (input != null) {
return createDuration(input);
}
}
function validateLabelAndSlot(tDateProfile, dateProfile, dateEnv) {
var currentRange = dateProfile.currentRange;
// make sure labelInterval doesn't exceed the max number of cells
if (tDateProfile.labelInterval) {
var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.labelInterval);
if (labelCnt > config.MAX_TIMELINE_SLOTS) {
console.warn('slotLabelInterval results in too many cells');
tDateProfile.labelInterval = null;
}
}
// make sure slotDuration doesn't exceed the maximum number of cells
if (tDateProfile.slotDuration) {
var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.slotDuration);
if (slotCnt > config.MAX_TIMELINE_SLOTS) {
console.warn('slotDuration results in too many cells');
tDateProfile.slotDuration = null;
}
}
// make sure labelInterval is a multiple of slotDuration
if (tDateProfile.labelInterval && tDateProfile.slotDuration) {
var slotsPerLabel = wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
if (slotsPerLabel === null || slotsPerLabel < 1) {
console.warn('slotLabelInterval must be a multiple of slotDuration');
tDateProfile.slotDuration = null;
}
}
}
function ensureLabelInterval(tDateProfile, dateProfile, dateEnv) {
var currentRange = dateProfile.currentRange;
var labelInterval = tDateProfile.labelInterval;
if (!labelInterval) {
// compute based off the slot duration
// find the largest label interval with an acceptable slots-per-label
var input = void 0;
if (tDateProfile.slotDuration) {
for (var _i = 0, STOCK_SUB_DURATIONS_1 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_1.length; _i++) {
input = STOCK_SUB_DURATIONS_1[_i];
var tryLabelInterval = createDuration(input);
var slotsPerLabel = wholeDivideDurations(tryLabelInterval, tDateProfile.slotDuration);
if (slotsPerLabel !== null && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
labelInterval = tryLabelInterval;
break;
}
}
// use the slot duration as a last resort
if (!labelInterval) {
labelInterval = tDateProfile.slotDuration;
}
// compute based off the view's duration
// find the largest label interval that yields the minimum number of labels
}
else {
for (var _a = 0, STOCK_SUB_DURATIONS_2 = STOCK_SUB_DURATIONS; _a < STOCK_SUB_DURATIONS_2.length; _a++) {
input = STOCK_SUB_DURATIONS_2[_a];
labelInterval = createDuration(input);
var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, labelInterval);
if (labelCnt >= MIN_AUTO_LABELS) {
break;
}
}
}
tDateProfile.labelInterval = labelInterval;
}
return labelInterval;
}
function ensureSlotDuration(tDateProfile, dateProfile, dateEnv) {
var currentRange = dateProfile.currentRange;
var slotDuration = tDateProfile.slotDuration;
if (!slotDuration) {
var labelInterval = ensureLabelInterval(tDateProfile, dateProfile, dateEnv); // will compute if necessary
// compute based off the label interval
// find the largest slot duration that is different from labelInterval, but still acceptable
for (var _i = 0, STOCK_SUB_DURATIONS_3 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_3.length; _i++) {
var input = STOCK_SUB_DURATIONS_3[_i];
var trySlotDuration = createDuration(input);
var slotsPerLabel = wholeDivideDurations(labelInterval, trySlotDuration);
if (slotsPerLabel !== null && slotsPerLabel > 1 && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
slotDuration = trySlotDuration;
break;
}
}
// only allow the value if it won't exceed the view's # of slots limit
if (slotDuration) {
var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, slotDuration);
if (slotCnt > MAX_AUTO_CELLS) {
slotDuration = null;
}
}
// use the label interval as a last resort
if (!slotDuration) {
slotDuration = labelInterval;
}
tDateProfile.slotDuration = slotDuration;
}
return slotDuration;
}
function computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view) {
var format1;
var format2;
var labelInterval = tDateProfile.labelInterval;
var unit = greatestDurationDenominator(labelInterval).unit;
var weekNumbersVisible = view.opt('weekNumbers');
var format0 = (format1 = (format2 = null));
// NOTE: weekNumber computation function wont work
if ((unit === 'week') && !weekNumbersVisible) {
unit = 'day';
}
switch (unit) {
case 'year':
format0 = { year: 'numeric' }; // '2015'
break;
case 'month':
if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
format0 = { year: 'numeric' }; // '2015'
}
format1 = { month: 'short' }; // 'Jan'
break;
case 'week':
if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
format0 = { year: 'numeric' }; // '2015'
}
format1 = { week: 'narrow' }; // 'Wk4'
break;
case 'day':
if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
format0 = { year: 'numeric', month: 'long' }; // 'January 2014'
}
else if (currentRangeAs('months', dateProfile, dateEnv) > 1) {
format0 = { month: 'long' }; // 'January'
}
if (weekNumbersVisible) {
format1 = { week: 'short' }; // 'Wk 4'
}
format2 = { weekday: 'narrow', day: 'numeric' }; // 'Su 9'
break;
case 'hour':
if (weekNumbersVisible) {
format0 = { week: 'short' }; // 'Wk 4'
}
if (currentRangeAs('days', dateProfile, dateEnv) > 1) {
format1 = { weekday: 'short', day: 'numeric', month: 'numeric', omitCommas: true }; // Sat 4/7
}
format2 = {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'short'
};
break;
case 'minute':
// sufficiently large number of different minute cells?
if ((asRoughMinutes(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
format0 = {
hour: 'numeric',
meridiem: 'short'
};
format1 = function (params) {
return ':' + padStart(params.date.minute, 2); // ':30'
};
}
else {
format0 = {
hour: 'numeric',
minute: 'numeric',
meridiem: 'short'
};
}
break;
case 'second':
// sufficiently large number of different second cells?
if ((asRoughSeconds(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
format0 = { hour: 'numeric', minute: '2-digit', meridiem: 'lowercase' }; // '8:30 PM'
format1 = function (params) {
return ':' + padStart(params.date.second, 2); // ':30'
};
}
else {
format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
}
break;
case 'millisecond':
format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
format1 = function (params) {
return '.' + padStart(params.millisecond, 3);
};
break;
}
return [].concat(format0 || [], format1 || [], format2 || []);
}
// Compute the number of the give units in the "current" range.
// Won't go more precise than days.
// Will return `0` if there's not a clean whole interval.
function currentRangeAs(unit, dateProfile, dateEnv) {
var range = dateProfile.currentRange;
var res = null;
if (unit === 'years') {
res = dateEnv.diffWholeYears(range.start, range.end);
}
else if (unit === 'months') {
res = dateEnv.diffWholeMonths(range.start, range.end);
}
else if (unit === 'weeks') {
res = dateEnv.diffWholeMonths(range.start, range.end);
}
else if (unit === 'days') {
res = diffWholeDays(range.start, range.end);
}
return res || 0;
}
function buildIsWeekStarts(tDateProfile, dateEnv) {
var slotDates = tDateProfile.slotDates, emphasizeWeeks = tDateProfile.emphasizeWeeks;
var prevWeekNumber = null;
var isWeekStarts = [];
for (var _i = 0, slotDates_1 = slotDates; _i < slotDates_1.length; _i++) {
var slotDate = slotDates_1[_i];
var weekNumber = dateEnv.computeWeekNumber(slotDate);
var isWeekStart = emphasizeWeeks && (prevWeekNumber !== null) && (prevWeekNumber !== weekNumber);
prevWeekNumber = weekNumber;
isWeekStarts.push(isWeekStart);
}
return isWeekStarts;
}
function buildCellRows(tDateProfile, dateEnv, view) {
var slotDates = tDateProfile.slotDates;
var formats = tDateProfile.headerFormats;
var cellRows = formats.map(function (format) { return []; }); // indexed by row,col
// specifically for navclicks
var rowUnits = formats.map(function (format) {
return format.getLargestUnit ? format.getLargestUnit() : null;
});
// builds cellRows and slotCells
for (var i = 0; i < slotDates.length; i++) {
var date = slotDates[i];
var isWeekStart = tDateProfile.isWeekStarts[i];
for (var row = 0; row < formats.length; row++) {
var format = formats[row];
var rowCells = cellRows[row];
var leadingCell = rowCells[rowCells.length - 1];
var isSuperRow = (formats.length > 1) && (row < (formats.length - 1)); // more than one row and not the last
var newCell = null;
if (isSuperRow) {
var text = dateEnv.format(date, format);
if (!leadingCell || (leadingCell.text !== text)) {
newCell = buildCellObject(date, text, rowUnits[row], view);
}
else {
leadingCell.colspan += 1;
}
}
else {
if (!leadingCell ||
isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval))) {
var text = dateEnv.format(date, format);
newCell = buildCellObject(date, text, rowUnits[row], view);
}
else {
leadingCell.colspan += 1;
}
}
if (newCell) {
newCell.weekStart = isWeekStart;
rowCells.push(newCell);
}
}
}
return cellRows;
}
function buildCellObject(date, text, rowUnit, view) {
var spanHtml = buildGotoAnchorHtml(view, {
date: date,
type: rowUnit,
forceOff: !rowUnit
}, {
'class': 'fc-cell-text'
}, htmlEscape(text));
return { text: text, spanHtml: spanHtml, date: date, colspan: 1, isWeekStart: false };
}
var TimelineNowIndicator = /** @class */ (function () {
function TimelineNowIndicator(headParent, bodyParent) {
this.headParent = headParent;
this.bodyParent = bodyParent;
}
TimelineNowIndicator.prototype.render = function (coord, isRtl) {
var styleProps = isRtl ? { right: -coord } : { left: coord };
this.headParent.appendChild(this.arrowEl = createElement('div', {
className: 'fc-now-indicator fc-now-indicator-arrow',
style: styleProps
}));
this.bodyParent.appendChild(this.lineEl = createElement('div', {
className: 'fc-now-indicator fc-now-indicator-line',
style: styleProps
}));
};
TimelineNowIndicator.prototype.unrender = function () {
if (this.arrowEl) {
removeElement(this.arrowEl);
}
if (this.lineEl) {
removeElement(this.lineEl);
}
};
return TimelineNowIndicator;
}());
var STICKY_PROP_VAL = computeStickyPropVal(); // if null, means not supported at all
var IS_MS_EDGE = /Edge/.test(navigator.userAgent);
var IS_SAFARI = STICKY_PROP_VAL === '-webkit-sticky'; // good b/c doesn't confuse chrome
var STICKY_CLASSNAME = 'fc-sticky';
/*
useful beyond the native position:sticky for these reasons:
- support in IE11
- nice centering support
*/
var StickyScroller = /** @class */ (function () {
function StickyScroller(scroller, isRtl, isVertical) {
var _this = this;
this.usingRelative = null;
/*
known bug: called twice on init. problem when mixing with ScrollJoiner
*/
this.updateSize = function () {
var els = Array.prototype.slice.call(_this.scroller.canvas.el.querySelectorAll('.' + STICKY_CLASSNAME));
var elGeoms = _this.queryElGeoms(els);
var viewportWidth = _this.scroller.el.clientWidth;
if (_this.usingRelative) {
var elDestinations = _this.computeElDestinations(elGeoms, viewportWidth); // read before prepPositioning
assignRelativePositions(els, elGeoms, elDestinations);
}
else {
assignStickyPositions(els, elGeoms, viewportWidth);
}
};
this.scroller = scroller;
this.usingRelative =
!STICKY_PROP_VAL || // IE11
(IS_MS_EDGE && isRtl) || // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/18883305/
((IS_MS_EDGE || IS_SAFARI) && isVertical); // because doesn't work with rowspan in tables, our only vertial use
if (this.usingRelative) {
scroller.on('scrollEnd', this.updateSize);
}
}
StickyScroller.prototype.destroy = function () {
this.scroller.off('scrollEnd', this.updateSize);
};
StickyScroller.prototype.queryElGeoms = function (els) {
var canvasOrigin = this.scroller.canvas.el.getBoundingClientRect();
var elGeoms = [];
for (var _i = 0, els_1 = els; _i < els_1.length; _i++) {
var el = els_1[_i];
var parentBound = translateRect(el.parentNode.getBoundingClientRect(), -canvasOrigin.left, -canvasOrigin.top);
var elRect = el.getBoundingClientRect();
var computedStyles = window.getComputedStyle(el);
var computedTextAlign = window.getComputedStyle(el.parentNode).textAlign; // ask the parent
var intendedTextAlign = computedTextAlign;
var naturalBound = null;
if (computedStyles.position !== 'sticky') {
naturalBound = translateRect(elRect, -canvasOrigin.left - (parseFloat(computedStyles.left) || 0), // could be 'auto'
-canvasOrigin.top - (parseFloat(computedStyles.top) || 0));
}
if (el.hasAttribute('data-sticky-center')) {
intendedTextAlign = 'center';
}
elGeoms.push({
parentBound: parentBound,
naturalBound: naturalBound,
elWidth: elRect.width,
elHeight: elRect.height,
computedTextAlign: computedTextAlign,
intendedTextAlign: intendedTextAlign
});
}
return elGeoms;
};
StickyScroller.prototype.computeElDestinations = function (elGeoms, viewportWidth) {
var viewportLeft = this.scroller.getScrollFromLeft();
var viewportTop = this.scroller.getScrollTop();
var viewportRight = viewportLeft + viewportWidth;
return elGeoms.map(function (elGeom) {
var elWidth = elGeom.elWidth, elHeight = elGeom.elHeight, parentBound = elGeom.parentBound, naturalBound = elGeom.naturalBound;
var destLeft; // relative to canvas topleft
var destTop; // "
switch (elGeom.intendedTextAlign) {
case 'left':
destLeft = viewportLeft;
break;
case 'right':
destLeft = viewportRight - elWidth;
break;
case 'center':
destLeft = (viewportLeft + viewportRight) / 2 - elWidth / 2;
break;
}
destLeft = Math.min(destLeft, parentBound.right - elWidth);
destLeft = Math.max(destLeft, parentBound.left);
destTop = viewportTop;
destTop = Math.min(destTop, parentBound.bottom - elHeight);
destTop = Math.max(destTop, naturalBound.top); // better to use natural top for upper bound
return { left: destLeft, top: destTop };
});
};
return StickyScroller;
}());
function assignRelativePositions(els, elGeoms, elDestinations) {
els.forEach(function (el, i) {
var naturalBound = elGeoms[i].naturalBound;
applyStyle(el, {
position: 'relative',
left: elDestinations[i].left - naturalBound.left,
top: elDestinations[i].top - naturalBound.top
});
});
}
function assignStickyPositions(els, elGeoms, viewportWidth) {
els.forEach(function (el, i) {
var stickyLeft = 0;
if (elGeoms[i].intendedTextAlign === 'center') {
stickyLeft = (viewportWidth - elGeoms[i].elWidth) / 2;
// needs to be forced to left?
if (elGeoms[i].computedTextAlign === 'center') {
el.setAttribute('data-sticky-center', '') // remember for next queryElGeoms
;
el.parentNode.style.textAlign = 'left';
}
}
applyStyle(el, {
position: STICKY_PROP_VAL,
left: stickyLeft,
right: 0,
top: 0
});
});
}
function computeStickyPropVal() {
var el = htmlToElement('<div style="position:-webkit-sticky;position:sticky"></div>');
var val = el.style.position;
if (val.indexOf('sticky') !== -1) {
return val;
}
else {
return null;
}
}
var TimeAxis = /** @class */ (function (_super) {
__extends(TimeAxis, _super);
function TimeAxis(context, headerContainerEl, bodyContainerEl) {
var _this = _super.call(this, context) || this;
var layout = _this.layout = new HeaderBodyLayout(headerContainerEl, bodyContainerEl, 'auto');
var headerEnhancedScroller = layout.headerScroller.enhancedScroll;
var bodyEnhancedScroller = layout.bodyScroller.enhancedScroll;
// needs to go after layout, which has ScrollJoiner
_this.headStickyScroller = new StickyScroller(headerEnhancedScroller, _this.isRtl, false); // isVertical=false
_this.bodyStickyScroller = new StickyScroller(bodyEnhancedScroller, _this.isRtl, false); // isVertical=false
_this.header = new TimelineHeader(context, headerEnhancedScroller.canvas.contentEl);
_this.slats = new TimelineSlats(context, bodyEnhancedScroller.canvas.bgEl);
_this.nowIndicator = new TimelineNowIndicator(headerEnhancedScroller.canvas.el, bodyEnhancedScroller.canvas.el);
return _this;
}
TimeAxis.prototype.destroy = function () {
this.layout.destroy();
this.header.destroy();
this.slats.destroy();
this.nowIndicator.unrender();
this.headStickyScroller.destroy();
this.bodyStickyScroller.destroy();
_super.prototype.destroy.call(this);
};
TimeAxis.prototype.render = function (props) {
var tDateProfile = this.tDateProfile =
buildTimelineDateProfile(props.dateProfile, this.view); // TODO: cache
this.header.receiveProps({
dateProfile: props.dateProfile,
tDateProfile: tDateProfile
});
this.slats.receiveProps({
dateProfile: props.dateProfile,
tDateProfile: tDateProfile
});
};
// Now Indicator
// ------------------------------------------------------------------------------------------
TimeAxis.prototype.getNowIndicatorUnit = function (dateProfile) {
// yuck
var tDateProfile = this.tDateProfile =
buildTimelineDateProfile(dateProfile, this.view); // TODO: cache
if (tDateProfile.isTimeScale) {
return greatestDurationDenominator(tDateProfile.slotDuration).unit;
}
};
// will only execute if isTimeScale
TimeAxis.prototype.renderNowIndicator = function (date) {
if (rangeContainsMarker(this.tDateProfile.normalizedRange, date)) {
this.nowIndicator.render(this.dateToCoord(date), this.isRtl);
}
};
// will only execute if isTimeScale
TimeAxis.prototype.unrenderNowIndicator = function () {
this.nowIndicator.unrender();
};
// Sizing
// ------------------------------------------------------------------------------------------
TimeAxis.prototype.updateSize = function (isResize, totalHeight, isAuto) {
this.applySlotWidth(this.computeSlotWidth());
// adjusts gutters. do after slot widths set
this.layout.setHeight(totalHeight, isAuto);
// pretty much just queries coords. do last
this.slats.updateSize();
};
TimeAxis.prototype.updateStickyScrollers = function () {
this.headStickyScroller.updateSize();
this.bodyStickyScroller.updateSize();
};
TimeAxis.prototype.computeSlotWidth = function () {
var slotWidth = this.opt('slotWidth') || '';
if (slotWidth === '') {
slotWidth = this.computeDefaultSlotWidth(this.tDateProfile);
}
return slotWidth;
};
TimeAxis.prototype.computeDefaultSlotWidth = function (tDateProfile) {
var maxInnerWidth = 0; // TODO: harness core's `matchCellWidths` for this
this.header.innerEls.forEach(function (innerEl, i) {
maxInnerWidth = Math.max(maxInnerWidth, innerEl.getBoundingClientRect().width);
});
var headingCellWidth = Math.ceil(maxInnerWidth) + 1; // assume no padding, and one pixel border
// in TimelineView.defaults we ensured that labelInterval is an interval of slotDuration
// TODO: rename labelDuration?
var slotsPerLabel = wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
var slotWidth = Math.ceil(headingCellWidth / slotsPerLabel);
var minWidth = window.getComputedStyle(this.header.slatColEls[0]).minWidth;
if (minWidth) {
minWidth = parseInt(minWidth, 10);
if (minWidth) {
slotWidth = Math.max(slotWidth, minWidth);
}
}
return slotWidth;
};
TimeAxis.prototype.applySlotWidth = function (slotWidth) {
var _a = this, layout = _a.layout, tDateProfile = _a.tDateProfile;
var containerWidth = '';
var containerMinWidth = '';
var nonLastSlotWidth = '';
if (slotWidth !== '') {
slotWidth = Math.round(slotWidth);
containerWidth = slotWidth * tDateProfile.slotDates.length;
containerMinWidth = '';
nonLastSlotWidth = slotWidth;
var availableWidth = layout.bodyScroller.enhancedScroll.getClientWidth();
if (availableWidth > containerWidth) {
containerMinWidth = availableWidth;
containerWidth = '';
nonLastSlotWidth = Math.floor(availableWidth / tDateProfile.slotDates.length);
}
}
layout.headerScroller.enhancedScroll.canvas.setWidth(containerWidth);
layout.headerScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth);
layout.bodyScroller.enhancedScroll.canvas.setWidth(containerWidth);
layout.bodyScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth);
if (nonLastSlotWidth !== '') {
this.header.slatColEls.slice(0, -1).concat(this.slats.slatColEls.slice(0, -1)).forEach(function (el) {
el.style.width = nonLastSlotWidth + 'px';
});
}
};
// returned value is between 0 and the number of snaps
TimeAxis.prototype.computeDateSnapCoverage = function (date) {
var _a = this, dateEnv = _a.dateEnv, tDateProfile = _a.tDateProfile;
var snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
if (snapDiff < 0) {
return 0;
}
else if (snapDiff >= tDateProfile.snapDiffToIndex.length) {
return tDateProfile.snapCnt;
}
else {
var snapDiffInt = Math.floor(snapDiff);
var snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt];
if (isInt(snapCoverage)) { // not an in-between value
snapCoverage += snapDiff - snapDiffInt; // add the remainder
}
else {
// a fractional value, meaning the date is not visible
// always round up in this case. works for start AND end dates in a range.
snapCoverage = Math.ceil(snapCoverage);
}
return snapCoverage;
}
};
// for LTR, results range from 0 to width of area
// for RTL, results range from negative width of area to 0
TimeAxis.prototype.dateToCoord = function (date) {
var tDateProfile = this.tDateProfile;
var snapCoverage = this.computeDateSnapCoverage(date);
var slotCoverage = snapCoverage / tDateProfile.snapsPerSlot;
var slotIndex = Math.floor(slotCoverage);
slotIndex = Math.min(slotIndex, tDateProfile.slotCnt - 1);
var partial = slotCoverage - slotIndex;
var _a = this.slats, innerCoordCache = _a.innerCoordCache, outerCoordCache = _a.outerCoordCache;
if (this.isRtl) {
return (outerCoordCache.rights[slotIndex] -
(innerCoordCache.getWidth(slotIndex) * partial)) - outerCoordCache.originClientRect.width;
}
else {
return (outerCoordCache.lefts[slotIndex] +
(innerCoordCache.getWidth(slotIndex) * partial));
}
};
TimeAxis.prototype.rangeToCoords = function (range) {
if (this.isRtl) {
return { right: this.dateToCoord(range.start), left: this.dateToCoord(range.end) };
}
else {
return { left: this.dateToCoord(range.start), right: this.dateToCoord(range.end) };
}
};
// Scrolling
// ------------------------------------------------------------------------------------------
TimeAxis.prototype.computeDateScroll = function (duration) {
var dateEnv = this.dateEnv;
var dateProfile = this.props.dateProfile;
var left = 0;
if (dateProfile) {
left = this.dateToCoord(dateEnv.add(startOfDay(dateProfile.activeRange.start), // startOfDay needed?
duration));
// hack to overcome the left borders of non-first slat
if (!this.isRtl && left) {
left += 1;
}
}
return { left: left };
};
TimeAxis.prototype.queryDateScroll = function () {
var enhancedScroll = this.layout.bodyScroller.enhancedScroll;
return {
left: enhancedScroll.getScrollLeft()
};
};
TimeAxis.prototype.applyDateScroll = function (scroll) {
// TODO: lame we have to update both. use the scrolljoiner instead maybe
this.layout.bodyScroller.enhancedScroll.setScrollLeft(scroll.left || 0);
this.layout.headerScroller.enhancedScroll.setScrollLeft(scroll.left || 0);
};
return TimeAxis;
}(Component));
var TimelineLaneEventRenderer = /** @class */ (function (_super) {
__extends(TimelineLaneEventRenderer, _super);
function TimelineLaneEventRenderer(context, masterContainerEl, timeAxis) {
var _this = _super.call(this, context) || this;
_this.masterContainerEl = masterContainerEl;
_this.timeAxis = timeAxis;
return _this;
}
TimelineLaneEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
var view = this.context.view;
var eventRange = seg.eventRange;
var eventDef = eventRange.def;
var eventUi = eventRange.ui;
var isDraggable = view.computeEventDraggable(eventDef, eventUi);
var isResizableFromStart = seg.isStart && view.computeEventStartResizable(eventDef, eventUi);
var isResizableFromEnd = seg.isEnd && view.computeEventEndResizable(eventDef, eventUi);
var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo);
classes.unshift('fc-timeline-event', 'fc-h-event');
var timeText = this.getTimeText(eventRange);
return '<a class="' + classes.join(' ') + '" style="' + cssToStr(this.getSkinCss(eventUi)) + '"' +
(eventDef.url ?
' href="' + htmlEscape(eventDef.url) + '"' :
'') +
'>' +
(timeText ?
'<span class="fc-time-wrap">' +
'<span class="fc-time">' +
htmlEscape(timeText) +
'</span>' +
'</span>'
:
'') +
'<span class="fc-title-wrap">' +
'<span class="fc-title fc-sticky">' +
(eventDef.title ? htmlEscape(eventDef.title) : '&nbsp;') +
'</span>' +
'</span>' +
(isResizableFromStart ?
'<div class="fc-resizer fc-start-resizer"></div>' :
'') +
(isResizableFromEnd ?
'<div class="fc-resizer fc-end-resizer"></div>' :
'') +
'</a>';
};
TimelineLaneEventRenderer.prototype.computeDisplayEventTime = function () {
return !this.timeAxis.tDateProfile.isTimeScale; // because times should be obvious via axis
};
TimelineLaneEventRenderer.prototype.computeDisplayEventEnd = function () {
return false;
};
// Computes a default event time formatting string if `timeFormat` is not explicitly defined
TimelineLaneEventRenderer.prototype.computeEventTimeFormat = function () {
return {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'narrow'
};
};
TimelineLaneEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
if (!this.el && this.masterContainerEl) {
this.el = createElement('div', { className: 'fc-event-container' });
if (mirrorInfo) {
this.el.classList.add('fc-mirror-container');
}
this.masterContainerEl.appendChild(this.el);
}
if (this.el) {
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
this.el.appendChild(seg.el);
}
}
};
TimelineLaneEventRenderer.prototype.detachSegs = function (segs) {
for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
var seg = segs_2[_i];
removeElement(seg.el);
}
};
// computes AND assigns (assigns the left/right at least). bad
TimelineLaneEventRenderer.prototype.computeSegSizes = function (segs) {
var timeAxis = this.timeAxis;
for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
var seg = segs_3[_i];
var coords = timeAxis.rangeToCoords(seg); // works because Seg has start/end
applyStyle(seg.el, {
left: (seg.left = coords.left),
right: -(seg.right = coords.right)
});
}
};
TimelineLaneEventRenderer.prototype.assignSegSizes = function (segs) {
if (!this.el) {
return;
}
// compute seg verticals
for (var _i = 0, segs_4 = segs; _i < segs_4.length; _i++) {
var seg = segs_4[_i];
seg.height = computeHeightAndMargins(seg.el);
}
this.buildSegLevels(segs); // populates above/below props for computeOffsetForSegs
var totalHeight = computeOffsetForSegs(segs); // also assigns seg.top
applyStyleProp(this.el, 'height', totalHeight);
// assign seg verticals
for (var _a = 0, segs_5 = segs; _a < segs_5.length; _a++) {
var seg = segs_5[_a];
applyStyleProp(seg.el, 'top', seg.top);
}
};
TimelineLaneEventRenderer.prototype.buildSegLevels = function (segs) {
var segLevels = [];
segs = this.sortEventSegs(segs);
for (var _i = 0, segs_6 = segs; _i < segs_6.length; _i++) {
var unplacedSeg = segs_6[_i];
unplacedSeg.above = [];
// determine the first level with no collisions
var level = 0; // level index
while (level < segLevels.length) {
var isLevelCollision = false;
// determine collisions
for (var _a = 0, _b = segLevels[level]; _a < _b.length; _a++) {
var placedSeg = _b[_a];
if (timeRowSegsCollide(unplacedSeg, placedSeg)) {
unplacedSeg.above.push(placedSeg);
isLevelCollision = true;
}
}
if (isLevelCollision) {
level += 1;
}
else {
break;
}
}
// insert into the first non-colliding level. create if necessary
(segLevels[level] || (segLevels[level] = []))
.push(unplacedSeg);
// record possible colliding segments below (TODO: automated test for this)
level += 1;
while (level < segLevels.length) {
for (var _c = 0, _d = segLevels[level]; _c < _d.length; _c++) {
var belowSeg = _d[_c];
if (timeRowSegsCollide(unplacedSeg, belowSeg)) {
belowSeg.above.push(unplacedSeg);
}
}
level += 1;
}
}
return segLevels;
};
return TimelineLaneEventRenderer;
}(FgEventRenderer));
function computeOffsetForSegs(segs) {
var max = 0;
for (var _i = 0, segs_7 = segs; _i < segs_7.length; _i++) {
var seg = segs_7[_i];
max = Math.max(max, computeOffsetForSeg(seg));
}
return max;
}
function computeOffsetForSeg(seg) {
if ((seg.top == null)) {
seg.top = computeOffsetForSegs(seg.above);
}
return seg.top + seg.height;
}
function timeRowSegsCollide(seg0, seg1) {
return (seg0.left < seg1.right) && (seg0.right > seg1.left);
}
var TimelineLaneFillRenderer = /** @class */ (function (_super) {
__extends(TimelineLaneFillRenderer, _super);
function TimelineLaneFillRenderer(context, masterContainerEl, timeAxis) {
var _this = _super.call(this, context) || this;
_this.masterContainerEl = masterContainerEl;
_this.timeAxis = timeAxis;
return _this;
}
TimelineLaneFillRenderer.prototype.attachSegs = function (type, segs) {
if (segs.length) {
var className = void 0;
if (type === 'businessHours') {
className = 'bgevent';
}
else {
className = type.toLowerCase();
}
// making a new container each time is OKAY
// all types of segs (background or business hours or whatever) are rendered in one pass
var containerEl = createElement('div', { className: 'fc-' + className + '-container' });
this.masterContainerEl.appendChild(containerEl);
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
containerEl.appendChild(seg.el);
}
return [containerEl]; // return value
}
};
TimelineLaneFillRenderer.prototype.computeSegSizes = function (segs) {
var timeAxis = this.timeAxis;
for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
var seg = segs_2[_i];
var coords = timeAxis.rangeToCoords(seg);
seg.left = coords.left;
seg.right = coords.right;
}
};
TimelineLaneFillRenderer.prototype.assignSegSizes = function (segs) {
for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
var seg = segs_3[_i];
applyStyle(seg.el, {
left: seg.left,
right: -seg.right
});
}
};
return TimelineLaneFillRenderer;
}(FillRenderer));
var TimelineLane = /** @class */ (function (_super) {
__extends(TimelineLane, _super);
function TimelineLane(context, fgContainerEl, bgContainerEl, timeAxis) {
var _this = _super.call(this, context, bgContainerEl) // should el be bgContainerEl???
|| this;
_this.slicer = new TimelineLaneSlicer();
_this.renderEventDrag = memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag);
_this.renderEventResize = memoizeRendering(_this._renderEventResize, _this._unrenderEventResize);
var fillRenderer = _this.fillRenderer = new TimelineLaneFillRenderer(context, bgContainerEl, timeAxis);
var eventRenderer = _this.eventRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis);
_this.mirrorRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis);
_this.renderBusinessHours = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'));
_this.renderDateSelection = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'));
_this.renderBgEvents = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'));
_this.renderFgEvents = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer));
_this.renderEventSelection = memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
_this.timeAxis = timeAxis;
return _this;
}
TimelineLane.prototype.render = function (props) {
var slicedProps = this.slicer.sliceProps(props, props.dateProfile, this.timeAxis.tDateProfile.isTimeScale ? null : props.nextDayThreshold, this, this.timeAxis);
this.renderBusinessHours(slicedProps.businessHourSegs);
this.renderDateSelection(slicedProps.dateSelectionSegs);
this.renderBgEvents(slicedProps.bgEventSegs);
this.renderFgEvents(slicedProps.fgEventSegs);
this.renderEventSelection(slicedProps.eventSelection);
this.renderEventDrag(slicedProps.eventDrag);
this.renderEventResize(slicedProps.eventResize);
};
TimelineLane.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderBusinessHours.unrender();
this.renderDateSelection.unrender();
this.renderBgEvents.unrender();
this.renderFgEvents.unrender();
this.renderEventSelection.unrender();
this.renderEventDrag.unrender();
this.renderEventResize.unrender();
};
TimelineLane.prototype._renderEventDrag = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype._unrenderEventDrag = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype._renderEventResize = function (state) {
if (state) {
// HACK. eventRenderer and fillRenderer both use these segs. would compete over seg.el
var segsForHighlight = state.segs.map(function (seg) {
return __assign({}, seg);
});
this.eventRenderer.hideByHash(state.affectedInstances);
this.fillRenderer.renderSegs('highlight', segsForHighlight);
this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype._unrenderEventResize = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.fillRenderer.unrender('highlight');
this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype.updateSize = function (isResize) {
var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
fillRenderer.computeSizes(isResize);
eventRenderer.computeSizes(isResize);
mirrorRenderer.computeSizes(isResize);
fillRenderer.assignSizes(isResize);
eventRenderer.assignSizes(isResize);
mirrorRenderer.assignSizes(isResize);
};
return TimelineLane;
}(DateComponent));
var TimelineLaneSlicer = /** @class */ (function (_super) {
__extends(TimelineLaneSlicer, _super);
function TimelineLaneSlicer() {
return _super !== null && _super.apply(this, arguments) || this;
}
TimelineLaneSlicer.prototype.sliceRange = function (origRange, timeAxis) {
var tDateProfile = timeAxis.tDateProfile;
var dateProfile = timeAxis.props.dateProfile;
var normalRange = normalizeRange(origRange, tDateProfile, timeAxis.dateEnv);
var segs = [];
// protect against when the span is entirely in an invalid date region
if (timeAxis.computeDateSnapCoverage(normalRange.start) < timeAxis.computeDateSnapCoverage(normalRange.end)) {
// intersect the footprint's range with the grid's range
var slicedRange = intersectRanges(normalRange, tDateProfile.normalizedRange);
if (slicedRange) {
segs.push({
start: slicedRange.start,
end: slicedRange.end,
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf() && isValidDate(slicedRange.start, tDateProfile, dateProfile, timeAxis.view),
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf() && isValidDate(addMs(slicedRange.end, -1), tDateProfile, dateProfile, timeAxis.view)
});
}
}
return segs;
};
return TimelineLaneSlicer;
}(Slicer));
var TimelineView = /** @class */ (function (_super) {
__extends(TimelineView, _super);
function TimelineView(context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.el.classList.add('fc-timeline');
if (_this.opt('eventOverlap') === false) {
_this.el.classList.add('fc-no-overlap');
}
_this.el.innerHTML = _this.renderSkeletonHtml();
_this.timeAxis = new TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area'));
_this.lane = new TimelineLane(_this.context, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis);
context.calendar.registerInteractiveComponent(_this, {
el: _this.timeAxis.slats.el
});
return _this;
}
TimelineView.prototype.destroy = function () {
this.timeAxis.destroy();
this.lane.destroy();
_super.prototype.destroy.call(this);
this.calendar.unregisterInteractiveComponent(this);
};
TimelineView.prototype.renderSkeletonHtml = function () {
var theme = this.theme;
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>";
};
TimelineView.prototype.render = function (props) {
_super.prototype.render.call(this, props); // flags for updateSize, addScroll
this.timeAxis.receiveProps({
dateProfile: props.dateProfile
});
this.lane.receiveProps(__assign({}, props, { nextDayThreshold: this.nextDayThreshold }));
};
TimelineView.prototype.updateSize = function (isResize, totalHeight, isAuto) {
this.timeAxis.updateSize(isResize, totalHeight, isAuto);
this.lane.updateSize(isResize);
};
// Now Indicator
// ------------------------------------------------------------------------------------------
TimelineView.prototype.getNowIndicatorUnit = function (dateProfile) {
return this.timeAxis.getNowIndicatorUnit(dateProfile);
};
TimelineView.prototype.renderNowIndicator = function (date) {
this.timeAxis.renderNowIndicator(date);
};
TimelineView.prototype.unrenderNowIndicator = function () {
this.timeAxis.unrenderNowIndicator();
};
// Scroll System
// ------------------------------------------------------------------------------------------
TimelineView.prototype.computeDateScroll = function (duration) {
return this.timeAxis.computeDateScroll(duration);
};
TimelineView.prototype.applyScroll = function (scroll, isResize) {
_super.prototype.applyScroll.call(this, scroll, isResize); // will call applyDateScroll
// avoid updating stickyscroll too often
// TODO: repeat code as ResourceTimelineView::updateSize
var calendar = this.calendar;
if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) {
this.timeAxis.updateStickyScrollers();
}
};
TimelineView.prototype.applyDateScroll = function (scroll) {
this.timeAxis.applyDateScroll(scroll);
};
TimelineView.prototype.queryScroll = function () {
var enhancedScroll = this.timeAxis.layout.bodyScroller.enhancedScroll;
return {
top: enhancedScroll.getScrollTop(),
left: enhancedScroll.getScrollLeft()
};
};
// Hit System
// ------------------------------------------------------------------------------------------
TimelineView.prototype.buildPositionCaches = function () {
this.timeAxis.slats.updateSize();
};
TimelineView.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
var slatHit = this.timeAxis.slats.positionToHit(positionLeft);
if (slatHit) {
return {
component: this,
dateSpan: slatHit.dateSpan,
rect: {
left: slatHit.left,
right: slatHit.right,
top: 0,
bottom: elHeight
},
dayEl: slatHit.dayEl,
layer: 0
};
}
};
return TimelineView;
}(View));
var main = createPlugin({
defaultView: 'timelineDay',
views: {
timeline: {
class: TimelineView,
eventResizableFromStart: true // how is this consumed for TimelineView tho?
},
timelineDay: {
type: 'timeline',
duration: { days: 1 }
},
timelineWeek: {
type: 'timeline',
duration: { weeks: 1 }
},
timelineMonth: {
type: 'timeline',
duration: { months: 1 }
},
timelineYear: {
type: 'timeline',
duration: { years: 1 }
}
}
});
export default main;
export { HeaderBodyLayout, ScrollJoiner, StickyScroller, TimeAxis, TimelineLane, TimelineView };
/*!
FullCalendar Timeline Plugin v4.3.0
Docs & License: https://fullcalendar.io/scheduler
(c) 2019 Adam Shaw
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
(global = global || self, factory(global.FullCalendarTimeline = {}, global.FullCalendar));
}(this, function (exports, core) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
/*
A rectangular area of content that lives within a Scroller.
Can have "gutters", areas of dead spacing around the perimeter.
Also very useful for forcing a width, which a Scroller cannot do alone.
Has a content area that lives above a background area.
*/
var ScrollerCanvas = /** @class */ (function () {
function ScrollerCanvas() {
this.gutters = {};
this.el = core.htmlToElement("<div class=\"fc-scroller-canvas\"> <div class=\"fc-content\"></div> <div class=\"fc-bg\"></div> </div>");
this.contentEl = this.el.querySelector('.fc-content');
this.bgEl = this.el.querySelector('.fc-bg');
}
/*
If falsy, resets all the gutters to 0
*/
ScrollerCanvas.prototype.setGutters = function (gutters) {
if (!gutters) {
this.gutters = {};
}
else {
__assign(this.gutters, gutters);
}
this.updateSize();
};
ScrollerCanvas.prototype.setWidth = function (width) {
this.width = width;
this.updateSize();
};
ScrollerCanvas.prototype.setMinWidth = function (minWidth) {
this.minWidth = minWidth;
this.updateSize();
};
ScrollerCanvas.prototype.clearWidth = function () {
this.width = null;
this.minWidth = null;
this.updateSize();
};
ScrollerCanvas.prototype.updateSize = function () {
var _a = this, gutters = _a.gutters, el = _a.el;
// is border-box (width includes padding)
core.forceClassName(el, 'fc-gutter-left', gutters.left);
core.forceClassName(el, 'fc-gutter-right', gutters.right);
core.forceClassName(el, 'fc-gutter-top', gutters.top);
core.forceClassName(el, 'fc-gutter-bottom', gutters.bottom);
core.applyStyle(el, {
paddingLeft: gutters.left || '',
paddingRight: gutters.right || '',
paddingTop: gutters.top || '',
paddingBottom: gutters.bottom || '',
width: (this.width != null) ?
this.width + (gutters.left || 0) + (gutters.right || 0) :
'',
minWidth: (this.minWidth != null) ?
this.minWidth + (gutters.left || 0) + (gutters.right || 0) :
''
});
core.applyStyle(this.bgEl, {
left: gutters.left || '',
right: gutters.right || '',
top: gutters.top || '',
bottom: gutters.bottom || ''
});
};
return ScrollerCanvas;
}());
var EnhancedScroller = /** @class */ (function (_super) {
__extends(EnhancedScroller, _super);
function EnhancedScroller(overflowX, overflowY) {
var _this = _super.call(this, overflowX, overflowY) || this;
// Scroll Events
// ----------------------------------------------------------------------------------------------
_this.reportScroll = function () {
if (!_this.isScrolling) {
_this.reportScrollStart();
}
_this.trigger('scroll');
_this.isMoving = true;
_this.requestMovingEnd();
};
_this.reportScrollStart = function () {
if (!_this.isScrolling) {
_this.isScrolling = true;
_this.trigger('scrollStart', _this.isTouching); // created in constructor
}
};
// Touch Events
// ----------------------------------------------------------------------------------------------
// will fire *before* the scroll event is fired
_this.reportTouchStart = function () {
_this.isTouching = true;
};
_this.reportTouchEnd = function () {
if (_this.isTouching) {
_this.isTouching = false;
// if touch scrolling was re-enabled during a recent touch scroll
// then unbind the handlers that are preventing it from happening.
if (_this.isTouchScrollEnabled) {
_this.unbindPreventTouchScroll(); // won't do anything if not bound
}
// if the user ended their touch, and the scroll area wasn't moving,
// we consider this to be the end of the scroll.
if (!_this.isMoving) {
_this.reportScrollEnd(); // won't fire if already ended
}
}
};
_this.isScrolling = false;
_this.isTouching = false;
_this.isMoving = false;
_this.isTouchScrollEnabled = true;
_this.requestMovingEnd = core.debounce(_this.reportMovingEnd, 500);
_this.canvas = new ScrollerCanvas();
_this.el.appendChild(_this.canvas.el);
_this.applyOverflow();
_this.bindHandlers();
return _this;
}
EnhancedScroller.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.unbindHandlers();
};
// Touch scroll prevention
// ----------------------------------------------------------------------------------------------
EnhancedScroller.prototype.disableTouchScroll = function () {
this.isTouchScrollEnabled = false;
this.bindPreventTouchScroll(); // will be unbound in enableTouchScroll or reportTouchEnd
};
EnhancedScroller.prototype.enableTouchScroll = function () {
this.isTouchScrollEnabled = true;
// only immediately unbind if a touch event is NOT in progress.
// otherwise, it will be handled by reportTouchEnd.
if (!this.isTouching) {
this.unbindPreventTouchScroll();
}
};
EnhancedScroller.prototype.bindPreventTouchScroll = function () {
if (!this.preventTouchScrollHandler) {
this.el.addEventListener('touchmove', (this.preventTouchScrollHandler = core.preventDefault));
}
};
EnhancedScroller.prototype.unbindPreventTouchScroll = function () {
if (this.preventTouchScrollHandler) {
this.el.removeEventListener('touchmove', this.preventTouchScrollHandler);
this.preventTouchScrollHandler = null;
}
};
// Handlers
// ----------------------------------------------------------------------------------------------
EnhancedScroller.prototype.bindHandlers = function () {
this.el.addEventListener('scroll', this.reportScroll);
this.el.addEventListener('touchstart', this.reportTouchStart, { passive: true });
this.el.addEventListener('touchend', this.reportTouchEnd);
};
EnhancedScroller.prototype.unbindHandlers = function () {
this.el.removeEventListener('scroll', this.reportScroll);
this.el.removeEventListener('touchstart', this.reportTouchStart, { passive: true });
this.el.removeEventListener('touchend', this.reportTouchEnd);
};
EnhancedScroller.prototype.reportMovingEnd = function () {
this.isMoving = false;
// only end the scroll if not currently touching.
// if touching, the scrolling will end later, on touchend.
if (!this.isTouching) {
this.reportScrollEnd();
}
};
EnhancedScroller.prototype.reportScrollEnd = function () {
if (this.isScrolling) {
this.trigger('scrollEnd');
this.isScrolling = false;
}
};
// Horizontal Scroll Normalization
// ----------------------------------------------------------------------------------------------
// http://stackoverflow.com/questions/24276619/better-way-to-get-the-viewport-of-a-scrollable-div-in-rtl-mode/24394376#24394376
// TODO: move all this to util functions
/*
If RTL, and scrolled to the left, returns NEGATIVE value (like Firefox)
*/
EnhancedScroller.prototype.getScrollLeft = function () {
var el = this.el;
var direction = window.getComputedStyle(el).direction;
var val = el.scrollLeft;
if (direction === 'rtl') {
switch (getRtlScrollSystem()) {
case 'positive':
val = (val + el.clientWidth) - el.scrollWidth;
break;
case 'reverse':
val = -val;
break;
}
}
return val;
};
/*
Accepts a NEGATIVE value for when scrolled in RTL
*/
EnhancedScroller.prototype.setScrollLeft = function (val) {
var el = this.el;
var direction = window.getComputedStyle(el).direction;
if (direction === 'rtl') {
switch (getRtlScrollSystem()) {
case 'positive':
val = (val - el.clientWidth) + el.scrollWidth;
break;
case 'reverse':
val = -val;
break;
}
}
el.scrollLeft = val;
};
/*
Always returns the number of pixels scrolled from the leftmost position (even if RTL).
Always positive.
*/
EnhancedScroller.prototype.getScrollFromLeft = function () {
var el = this.el;
var direction = window.getComputedStyle(el).direction;
var val = el.scrollLeft;
if (direction === 'rtl') {
switch (getRtlScrollSystem()) {
case 'negative':
val = (val - el.clientWidth) + el.scrollWidth;
break;
case 'reverse':
val = (-val - el.clientWidth) + el.scrollWidth;
break;
}
}
return val;
};
return EnhancedScroller;
}(core.ScrollComponent));
core.EmitterMixin.mixInto(EnhancedScroller);
// Horizontal Scroll System Detection
// ----------------------------------------------------------------------------------------------
var _rtlScrollSystem;
function getRtlScrollSystem() {
return _rtlScrollSystem || (_rtlScrollSystem = detectRtlScrollSystem());
}
function detectRtlScrollSystem() {
var el = core.htmlToElement("<div style=\" position: absolute; top: -1000px; width: 1px; height: 1px; overflow: scroll; direction: rtl; font-size: 100px; \">A</div>");
document.body.appendChild(el);
var system;
if (el.scrollLeft > 0) {
system = 'positive';
}
else {
el.scrollLeft = 1;
if (el.scrollLeft > 0) {
system = 'reverse';
}
else {
system = 'negative';
}
}
core.removeElement(el);
return system;
}
/*
A Scroller, but with a wrapping div that allows "clipping" away of native scrollbars,
giving the appearance that there are no scrollbars.
*/
var ClippedScroller = /** @class */ (function () {
/*
Received overflows can be set to 'clipped', meaning scrollbars shouldn't be visible
to the user, but the area should still scroll.
*/
function ClippedScroller(overflowX, overflowY, parentEl) {
this.isHScrollbarsClipped = false;
this.isVScrollbarsClipped = false;
if (overflowX === 'clipped-scroll') {
overflowX = 'scroll';
this.isHScrollbarsClipped = true;
}
if (overflowY === 'clipped-scroll') {
overflowY = 'scroll';
this.isVScrollbarsClipped = true;
}
this.enhancedScroll = new EnhancedScroller(overflowX, overflowY);
parentEl.appendChild(this.el = core.createElement('div', {
className: 'fc-scroller-clip'
}));
this.el.appendChild(this.enhancedScroll.el);
}
ClippedScroller.prototype.destroy = function () {
core.removeElement(this.el);
};
ClippedScroller.prototype.updateSize = function () {
var enhancedScroll = this.enhancedScroll;
var scrollEl = enhancedScroll.el;
var edges = core.computeEdges(scrollEl);
var cssProps = { marginLeft: 0, marginRight: 0, marginTop: 0, marginBottom: 0 };
// give the inner scrolling div negative margins so that its scrollbars
// are nudged outside of the bounding box of the wrapper, which is overflow:hidden
if (this.isVScrollbarsClipped) {
cssProps.marginLeft = -edges.scrollbarLeft;
cssProps.marginRight = -edges.scrollbarRight;
}
if (this.isHScrollbarsClipped) {
cssProps.marginBottom = -edges.scrollbarBottom;
}
core.applyStyle(scrollEl, cssProps);
// if we are attempting to hide the scrollbars offscreen, OSX/iOS will still
// display the floating scrollbars. attach a className to force-hide them.
if ((this.isHScrollbarsClipped || (enhancedScroll.overflowX === 'hidden')) && // should never show?
(this.isVScrollbarsClipped || (enhancedScroll.overflowY === 'hidden')) && // should never show?
!( // doesn't have any scrollbar mass
edges.scrollbarLeft ||
edges.scrollbarRight ||
edges.scrollbarBottom)) {
scrollEl.classList.add('fc-no-scrollbars');
}
else {
scrollEl.classList.remove('fc-no-scrollbars');
}
};
ClippedScroller.prototype.setHeight = function (height) {
this.enhancedScroll.setHeight(height);
};
/*
Accounts for 'clipped' scrollbars
*/
ClippedScroller.prototype.getScrollbarWidths = function () {
var widths = this.enhancedScroll.getScrollbarWidths();
if (this.isVScrollbarsClipped) {
widths.left = 0;
widths.right = 0;
}
if (this.isHScrollbarsClipped) {
widths.bottom = 0;
}
return widths;
};
return ClippedScroller;
}());
var ScrollJoiner = /** @class */ (function () {
function ScrollJoiner(axis, scrollers) {
this.axis = axis;
this.scrollers = scrollers;
for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
var scroller = _a[_i];
this.initScroller(scroller);
}
}
ScrollJoiner.prototype.initScroller = function (scroller) {
var _this = this;
var enhancedScroll = scroller.enhancedScroll;
// when the user scrolls via mousewheel, we know for sure the target
// scroller should be the master. capture the various x-browser events that fire.
var onScroll = function () {
_this.assignMasterScroller(scroller);
};
'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ').forEach(function (evName) {
enhancedScroll.el.addEventListener(evName, onScroll);
});
enhancedScroll
.on('scrollStart', function () {
if (!_this.masterScroller) {
_this.assignMasterScroller(scroller);
}
})
.on('scroll', function () {
if (scroller === _this.masterScroller) {
for (var _i = 0, _a = _this.scrollers; _i < _a.length; _i++) {
var otherScroller = _a[_i];
if (otherScroller !== scroller) {
switch (_this.axis) {
case 'horizontal':
otherScroller.enhancedScroll.el.scrollLeft = enhancedScroll.el.scrollLeft;
break;
case 'vertical':
otherScroller.enhancedScroll.setScrollTop(enhancedScroll.getScrollTop());
break;
}
}
}
}
})
.on('scrollEnd', function () {
if (scroller === _this.masterScroller) {
_this.unassignMasterScroller();
}
});
};
ScrollJoiner.prototype.assignMasterScroller = function (scroller) {
this.unassignMasterScroller();
this.masterScroller = scroller;
for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
var otherScroller = _a[_i];
if (otherScroller !== scroller) {
otherScroller.enhancedScroll.disableTouchScroll();
}
}
};
ScrollJoiner.prototype.unassignMasterScroller = function () {
if (this.masterScroller) {
for (var _i = 0, _a = this.scrollers; _i < _a.length; _i++) {
var otherScroller = _a[_i];
otherScroller.enhancedScroll.enableTouchScroll();
}
this.masterScroller = null;
}
};
ScrollJoiner.prototype.update = function () {
var allWidths = this.scrollers.map(function (scroller) { return scroller.getScrollbarWidths(); });
var maxLeft = 0;
var maxRight = 0;
var maxTop = 0;
var maxBottom = 0;
var widths;
var i;
for (var _i = 0, allWidths_1 = allWidths; _i < allWidths_1.length; _i++) {
widths = allWidths_1[_i];
maxLeft = Math.max(maxLeft, widths.left);
maxRight = Math.max(maxRight, widths.right);
maxTop = Math.max(maxTop, widths.top);
maxBottom = Math.max(maxBottom, widths.bottom);
}
for (i = 0; i < this.scrollers.length; i++) {
var scroller = this.scrollers[i];
widths = allWidths[i];
scroller.enhancedScroll.canvas.setGutters(this.axis === 'horizontal' ?
{
left: maxLeft - widths.left,
right: maxRight - widths.right
} :
{
top: maxTop - widths.top,
bottom: maxBottom - widths.bottom
});
}
};
return ScrollJoiner;
}());
var HeaderBodyLayout = /** @class */ (function () {
/*
verticalScroll = 'auto' | 'clipped-scroll'
*/
function HeaderBodyLayout(headerContainerEl, bodyContainerEl, verticalScroll) {
this.headerScroller = new ClippedScroller('clipped-scroll', 'hidden', headerContainerEl);
this.bodyScroller = new ClippedScroller('auto', verticalScroll, bodyContainerEl);
this.scrollJoiner = new ScrollJoiner('horizontal', [
this.headerScroller,
this.bodyScroller
]);
}
HeaderBodyLayout.prototype.destroy = function () {
this.headerScroller.destroy();
this.bodyScroller.destroy();
};
HeaderBodyLayout.prototype.setHeight = function (totalHeight, isAuto) {
var bodyHeight;
if (isAuto) {
bodyHeight = 'auto';
}
else {
bodyHeight = totalHeight - this.queryHeadHeight();
}
this.bodyScroller.setHeight(bodyHeight);
this.headerScroller.updateSize(); // adjusts gutters and classNames
this.bodyScroller.updateSize(); // adjusts gutters and classNames
this.scrollJoiner.update();
};
HeaderBodyLayout.prototype.queryHeadHeight = function () {
return this.headerScroller.enhancedScroll.canvas.contentEl.getBoundingClientRect().height;
};
return HeaderBodyLayout;
}());
var TimelineHeader = /** @class */ (function (_super) {
__extends(TimelineHeader, _super);
function TimelineHeader(context, parentEl) {
var _this = _super.call(this, context) || this;
parentEl.appendChild(_this.tableEl = core.createElement('table', {
className: _this.theme.getClass('tableGrid')
}));
return _this;
}
TimelineHeader.prototype.destroy = function () {
core.removeElement(this.tableEl);
_super.prototype.destroy.call(this);
};
TimelineHeader.prototype.render = function (props) {
this.renderDates(props.tDateProfile);
};
TimelineHeader.prototype.renderDates = function (tDateProfile) {
var _a = this, dateEnv = _a.dateEnv, theme = _a.theme;
var cellRows = tDateProfile.cellRows;
var lastRow = cellRows[cellRows.length - 1];
var isChrono = core.asRoughMs(tDateProfile.labelInterval) > core.asRoughMs(tDateProfile.slotDuration);
var oneDay = core.isSingleDay(tDateProfile.slotDuration);
var html = '<colgroup>';
// needs to be a col for each body slat. header cells will have colspans
for (var i = tDateProfile.slotCnt - 1; i >= 0; i--) {
html += '<col/>';
}
html += '</colgroup>';
html += '<tbody>';
for (var _i = 0, cellRows_1 = cellRows; _i < cellRows_1.length; _i++) {
var rowCells = cellRows_1[_i];
var isLast = rowCells === lastRow;
html += '<tr' + (isChrono && isLast ? ' class="fc-chrono"' : '') + '>';
for (var _b = 0, rowCells_1 = rowCells; _b < rowCells_1.length; _b++) {
var cell = rowCells_1[_b];
var headerCellClassNames = [theme.getClass('widgetHeader')];
if (cell.isWeekStart) {
headerCellClassNames.push('fc-em-cell');
}
if (oneDay) {
headerCellClassNames = headerCellClassNames.concat(core.getDayClasses(cell.date, this.props.dateProfile, this.context, true) // adds "today" class and other day-based classes
);
}
html +=
'<th class="' + headerCellClassNames.join(' ') + '"' +
' data-date="' + dateEnv.formatIso(cell.date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' +
(cell.colspan > 1 ? ' colspan="' + cell.colspan + '"' : '') +
'>' +
'<div class="fc-cell-content">' +
cell.spanHtml +
'</div>' +
'</th>';
}
html += '</tr>';
}
html += '</tbody>';
this.tableEl.innerHTML = html; // TODO: does this work cross-browser?
this.slatColEls = core.findElements(this.tableEl, 'col');
this.innerEls = core.findElements(this.tableEl.querySelector('tr:last-child'), // compound selector won't work because of query-root problem
'th .fc-cell-text');
core.findElements(this.tableEl.querySelectorAll('tr:not(:last-child)'), // compound selector won't work because of query-root problem
'th .fc-cell-text').forEach(function (innerEl) {
innerEl.classList.add('fc-sticky');
});
};
return TimelineHeader;
}(core.Component));
var TimelineSlats = /** @class */ (function (_super) {
__extends(TimelineSlats, _super);
function TimelineSlats(context, parentEl) {
var _this = _super.call(this, context) || this;
parentEl.appendChild(_this.el = core.createElement('div', { className: 'fc-slats' }));
return _this;
}
TimelineSlats.prototype.destroy = function () {
core.removeElement(this.el);
_super.prototype.destroy.call(this);
};
TimelineSlats.prototype.render = function (props) {
this.renderDates(props.tDateProfile);
};
TimelineSlats.prototype.renderDates = function (tDateProfile) {
var _a = this, theme = _a.theme, view = _a.view, dateEnv = _a.dateEnv;
var slotDates = tDateProfile.slotDates, isWeekStarts = tDateProfile.isWeekStarts;
var html = '<table class="' + theme.getClass('tableGrid') + '">' +
'<colgroup>';
for (var i = 0; i < slotDates.length; i++) {
html += '<col/>';
}
html += '</colgroup>';
html += '<tbody><tr>';
for (var i = 0; i < slotDates.length; i++) {
html += this.slatCellHtml(slotDates[i], isWeekStarts[i], tDateProfile);
}
html += '</tr></tbody></table>';
this.el.innerHTML = html;
this.slatColEls = core.findElements(this.el, 'col');
this.slatEls = core.findElements(this.el, 'td');
for (var i = 0; i < slotDates.length; i++) {
view.publiclyTrigger('dayRender', [
{
date: dateEnv.toDate(slotDates[i]),
el: this.slatEls[i],
view: view
}
]);
}
this.outerCoordCache = new core.PositionCache(this.el, this.slatEls, true, // isHorizontal
false // isVertical
);
// for the inner divs within the slats
// used for event rendering and scrollTime, to disregard slat border
this.innerCoordCache = new core.PositionCache(this.el, core.findChildren(this.slatEls, 'div'), true, // isHorizontal
false // isVertical
);
};
TimelineSlats.prototype.slatCellHtml = function (date, isEm, tDateProfile) {
var _a = this, theme = _a.theme, dateEnv = _a.dateEnv;
var classes;
if (tDateProfile.isTimeScale) {
classes = [];
classes.push(core.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval)) ?
'fc-major' :
'fc-minor');
}
else {
classes = core.getDayClasses(date, this.props.dateProfile, this.context);
classes.push('fc-day');
}
classes.unshift(theme.getClass('widgetContent'));
if (isEm) {
classes.push('fc-em-cell');
}
return '<td class="' + classes.join(' ') + '"' +
' data-date="' + dateEnv.formatIso(date, { omitTime: !tDateProfile.isTimeScale, omitTimeZoneOffset: true }) + '"' +
'><div></div></td>';
};
TimelineSlats.prototype.updateSize = function () {
this.outerCoordCache.build();
this.innerCoordCache.build();
};
TimelineSlats.prototype.positionToHit = function (leftPosition) {
var outerCoordCache = this.outerCoordCache;
var tDateProfile = this.props.tDateProfile;
var slatIndex = outerCoordCache.leftToIndex(leftPosition);
if (slatIndex != null) {
// somewhat similar to what TimeGrid does. consolidate?
var slatWidth = outerCoordCache.getWidth(slatIndex);
var partial = this.isRtl ?
(outerCoordCache.rights[slatIndex] - leftPosition) / slatWidth :
(leftPosition - outerCoordCache.lefts[slatIndex]) / slatWidth;
var localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot);
var start = this.dateEnv.add(tDateProfile.slotDates[slatIndex], core.multiplyDuration(tDateProfile.snapDuration, localSnapIndex));
var end = this.dateEnv.add(start, tDateProfile.snapDuration);
return {
dateSpan: {
range: { start: start, end: end },
allDay: !this.props.tDateProfile.isTimeScale
},
dayEl: this.slatColEls[slatIndex],
left: outerCoordCache.lefts[slatIndex],
right: outerCoordCache.rights[slatIndex]
};
}
return null;
};
return TimelineSlats;
}(core.Component));
var MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours
var MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour
var MAX_AUTO_CELLS = 200; // allows 4-days to have a :30 slot duration
core.config.MAX_TIMELINE_SLOTS = 1000;
// potential nice values for slot-duration and interval-duration
var STOCK_SUB_DURATIONS = [
{ years: 1 },
{ months: 1 },
{ days: 1 },
{ hours: 1 },
{ minutes: 30 },
{ minutes: 15 },
{ minutes: 10 },
{ minutes: 5 },
{ minutes: 1 },
{ seconds: 30 },
{ seconds: 15 },
{ seconds: 10 },
{ seconds: 5 },
{ seconds: 1 },
{ milliseconds: 500 },
{ milliseconds: 100 },
{ milliseconds: 10 },
{ milliseconds: 1 }
];
function buildTimelineDateProfile(dateProfile, view) {
var dateEnv = view.dateEnv;
var tDateProfile = {
labelInterval: queryDurationOption(view, 'slotLabelInterval'),
slotDuration: queryDurationOption(view, 'slotDuration')
};
validateLabelAndSlot(tDateProfile, dateProfile, dateEnv); // validate after computed grid duration
ensureLabelInterval(tDateProfile, dateProfile, dateEnv);
ensureSlotDuration(tDateProfile, dateProfile, dateEnv);
var input = view.opt('slotLabelFormat');
var rawFormats = Array.isArray(input) ?
input
: (input != null) ?
[input]
:
computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view);
tDateProfile.headerFormats = rawFormats.map(function (rawFormat) {
return core.createFormatter(rawFormat);
});
tDateProfile.isTimeScale = Boolean(tDateProfile.slotDuration.milliseconds);
var largeUnit = null;
if (!tDateProfile.isTimeScale) {
var slotUnit = core.greatestDurationDenominator(tDateProfile.slotDuration).unit;
if (/year|month|week/.test(slotUnit)) {
largeUnit = slotUnit;
}
}
tDateProfile.largeUnit = largeUnit;
tDateProfile.emphasizeWeeks =
core.isSingleDay(tDateProfile.slotDuration) &&
currentRangeAs('weeks', dateProfile, dateEnv) >= 2 &&
!view.opt('businessHours');
/*
console.log('label interval =', timelineView.labelInterval.humanize())
console.log('slot duration =', timelineView.slotDuration.humanize())
console.log('header formats =', timelineView.headerFormats)
console.log('isTimeScale', timelineView.isTimeScale)
console.log('largeUnit', timelineView.largeUnit)
*/
var rawSnapDuration = view.opt('snapDuration');
var snapDuration;
var snapsPerSlot;
if (rawSnapDuration) {
snapDuration = core.createDuration(rawSnapDuration);
snapsPerSlot = core.wholeDivideDurations(tDateProfile.slotDuration, snapDuration);
// ^ TODO: warning if not whole?
}
if (snapsPerSlot == null) {
snapDuration = tDateProfile.slotDuration;
snapsPerSlot = 1;
}
tDateProfile.snapDuration = snapDuration;
tDateProfile.snapsPerSlot = snapsPerSlot;
// more...
var timeWindowMs = core.asRoughMs(dateProfile.maxTime) - core.asRoughMs(dateProfile.minTime);
// TODO: why not use normalizeRange!?
var normalizedStart = normalizeDate(dateProfile.renderRange.start, tDateProfile, dateEnv);
var normalizedEnd = normalizeDate(dateProfile.renderRange.end, tDateProfile, dateEnv);
// apply minTime/maxTime
// TODO: View should be responsible.
if (tDateProfile.isTimeScale) {
normalizedStart = dateEnv.add(normalizedStart, dateProfile.minTime);
normalizedEnd = dateEnv.add(core.addDays(normalizedEnd, -1), dateProfile.maxTime);
}
tDateProfile.timeWindowMs = timeWindowMs;
tDateProfile.normalizedRange = { start: normalizedStart, end: normalizedEnd };
var slotDates = [];
var date = normalizedStart;
while (date < normalizedEnd) {
if (isValidDate(date, tDateProfile, dateProfile, view)) {
slotDates.push(date);
}
date = dateEnv.add(date, tDateProfile.slotDuration);
}
tDateProfile.slotDates = slotDates;
// more...
var snapIndex = -1;
var snapDiff = 0; // index of the diff :(
var snapDiffToIndex = [];
var snapIndexToDiff = [];
date = normalizedStart;
while (date < normalizedEnd) {
if (isValidDate(date, tDateProfile, dateProfile, view)) {
snapIndex++;
snapDiffToIndex.push(snapIndex);
snapIndexToDiff.push(snapDiff);
}
else {
snapDiffToIndex.push(snapIndex + 0.5);
}
date = dateEnv.add(date, tDateProfile.snapDuration);
snapDiff++;
}
tDateProfile.snapDiffToIndex = snapDiffToIndex;
tDateProfile.snapIndexToDiff = snapIndexToDiff;
tDateProfile.snapCnt = snapIndex + 1; // is always one behind
tDateProfile.slotCnt = tDateProfile.snapCnt / tDateProfile.snapsPerSlot;
// more...
tDateProfile.isWeekStarts = buildIsWeekStarts(tDateProfile, dateEnv);
tDateProfile.cellRows = buildCellRows(tDateProfile, dateEnv, view);
return tDateProfile;
}
/*
snaps to appropriate unit
*/
function normalizeDate(date, tDateProfile, dateEnv) {
var normalDate = date;
if (!tDateProfile.isTimeScale) {
normalDate = core.startOfDay(normalDate);
if (tDateProfile.largeUnit) {
normalDate = dateEnv.startOf(normalDate, tDateProfile.largeUnit);
}
}
return normalDate;
}
/*
snaps to appropriate unit
*/
function normalizeRange(range, tDateProfile, dateEnv) {
if (!tDateProfile.isTimeScale) {
range = core.computeVisibleDayRange(range);
if (tDateProfile.largeUnit) {
var dayRange = range; // preserve original result
range = {
start: dateEnv.startOf(range.start, tDateProfile.largeUnit),
end: dateEnv.startOf(range.end, tDateProfile.largeUnit)
};
// if date is partially through the interval, or is in the same interval as the start,
// make the exclusive end be the *next* interval
if (range.end.valueOf() !== dayRange.end.valueOf() || range.end <= range.start) {
range = {
start: range.start,
end: dateEnv.add(range.end, tDateProfile.slotDuration)
};
}
}
}
return range;
}
function isValidDate(date, tDateProfile, dateProfile, view) {
if (view.dateProfileGenerator.isHiddenDay(date)) {
return false;
}
else if (tDateProfile.isTimeScale) {
// determine if the time is within minTime/maxTime, which may have wacky values
var day = core.startOfDay(date);
var timeMs = date.valueOf() - day.valueOf();
var ms = timeMs - core.asRoughMs(dateProfile.minTime); // milliseconds since minTime
ms = ((ms % 86400000) + 86400000) % 86400000; // make negative values wrap to 24hr clock
return ms < tDateProfile.timeWindowMs; // before the maxTime?
}
else {
return true;
}
}
function queryDurationOption(view, name) {
var input = view.opt(name);
if (input != null) {
return core.createDuration(input);
}
}
function validateLabelAndSlot(tDateProfile, dateProfile, dateEnv) {
var currentRange = dateProfile.currentRange;
// make sure labelInterval doesn't exceed the max number of cells
if (tDateProfile.labelInterval) {
var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.labelInterval);
if (labelCnt > core.config.MAX_TIMELINE_SLOTS) {
console.warn('slotLabelInterval results in too many cells');
tDateProfile.labelInterval = null;
}
}
// make sure slotDuration doesn't exceed the maximum number of cells
if (tDateProfile.slotDuration) {
var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, tDateProfile.slotDuration);
if (slotCnt > core.config.MAX_TIMELINE_SLOTS) {
console.warn('slotDuration results in too many cells');
tDateProfile.slotDuration = null;
}
}
// make sure labelInterval is a multiple of slotDuration
if (tDateProfile.labelInterval && tDateProfile.slotDuration) {
var slotsPerLabel = core.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
if (slotsPerLabel === null || slotsPerLabel < 1) {
console.warn('slotLabelInterval must be a multiple of slotDuration');
tDateProfile.slotDuration = null;
}
}
}
function ensureLabelInterval(tDateProfile, dateProfile, dateEnv) {
var currentRange = dateProfile.currentRange;
var labelInterval = tDateProfile.labelInterval;
if (!labelInterval) {
// compute based off the slot duration
// find the largest label interval with an acceptable slots-per-label
var input = void 0;
if (tDateProfile.slotDuration) {
for (var _i = 0, STOCK_SUB_DURATIONS_1 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_1.length; _i++) {
input = STOCK_SUB_DURATIONS_1[_i];
var tryLabelInterval = core.createDuration(input);
var slotsPerLabel = core.wholeDivideDurations(tryLabelInterval, tDateProfile.slotDuration);
if (slotsPerLabel !== null && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
labelInterval = tryLabelInterval;
break;
}
}
// use the slot duration as a last resort
if (!labelInterval) {
labelInterval = tDateProfile.slotDuration;
}
// compute based off the view's duration
// find the largest label interval that yields the minimum number of labels
}
else {
for (var _a = 0, STOCK_SUB_DURATIONS_2 = STOCK_SUB_DURATIONS; _a < STOCK_SUB_DURATIONS_2.length; _a++) {
input = STOCK_SUB_DURATIONS_2[_a];
labelInterval = core.createDuration(input);
var labelCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, labelInterval);
if (labelCnt >= MIN_AUTO_LABELS) {
break;
}
}
}
tDateProfile.labelInterval = labelInterval;
}
return labelInterval;
}
function ensureSlotDuration(tDateProfile, dateProfile, dateEnv) {
var currentRange = dateProfile.currentRange;
var slotDuration = tDateProfile.slotDuration;
if (!slotDuration) {
var labelInterval = ensureLabelInterval(tDateProfile, dateProfile, dateEnv); // will compute if necessary
// compute based off the label interval
// find the largest slot duration that is different from labelInterval, but still acceptable
for (var _i = 0, STOCK_SUB_DURATIONS_3 = STOCK_SUB_DURATIONS; _i < STOCK_SUB_DURATIONS_3.length; _i++) {
var input = STOCK_SUB_DURATIONS_3[_i];
var trySlotDuration = core.createDuration(input);
var slotsPerLabel = core.wholeDivideDurations(labelInterval, trySlotDuration);
if (slotsPerLabel !== null && slotsPerLabel > 1 && slotsPerLabel <= MAX_AUTO_SLOTS_PER_LABEL) {
slotDuration = trySlotDuration;
break;
}
}
// only allow the value if it won't exceed the view's # of slots limit
if (slotDuration) {
var slotCnt = dateEnv.countDurationsBetween(currentRange.start, currentRange.end, slotDuration);
if (slotCnt > MAX_AUTO_CELLS) {
slotDuration = null;
}
}
// use the label interval as a last resort
if (!slotDuration) {
slotDuration = labelInterval;
}
tDateProfile.slotDuration = slotDuration;
}
return slotDuration;
}
function computeHeaderFormats(tDateProfile, dateProfile, dateEnv, view) {
var format1;
var format2;
var labelInterval = tDateProfile.labelInterval;
var unit = core.greatestDurationDenominator(labelInterval).unit;
var weekNumbersVisible = view.opt('weekNumbers');
var format0 = (format1 = (format2 = null));
// NOTE: weekNumber computation function wont work
if ((unit === 'week') && !weekNumbersVisible) {
unit = 'day';
}
switch (unit) {
case 'year':
format0 = { year: 'numeric' }; // '2015'
break;
case 'month':
if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
format0 = { year: 'numeric' }; // '2015'
}
format1 = { month: 'short' }; // 'Jan'
break;
case 'week':
if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
format0 = { year: 'numeric' }; // '2015'
}
format1 = { week: 'narrow' }; // 'Wk4'
break;
case 'day':
if (currentRangeAs('years', dateProfile, dateEnv) > 1) {
format0 = { year: 'numeric', month: 'long' }; // 'January 2014'
}
else if (currentRangeAs('months', dateProfile, dateEnv) > 1) {
format0 = { month: 'long' }; // 'January'
}
if (weekNumbersVisible) {
format1 = { week: 'short' }; // 'Wk 4'
}
format2 = { weekday: 'narrow', day: 'numeric' }; // 'Su 9'
break;
case 'hour':
if (weekNumbersVisible) {
format0 = { week: 'short' }; // 'Wk 4'
}
if (currentRangeAs('days', dateProfile, dateEnv) > 1) {
format1 = { weekday: 'short', day: 'numeric', month: 'numeric', omitCommas: true }; // Sat 4/7
}
format2 = {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'short'
};
break;
case 'minute':
// sufficiently large number of different minute cells?
if ((core.asRoughMinutes(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
format0 = {
hour: 'numeric',
meridiem: 'short'
};
format1 = function (params) {
return ':' + core.padStart(params.date.minute, 2); // ':30'
};
}
else {
format0 = {
hour: 'numeric',
minute: 'numeric',
meridiem: 'short'
};
}
break;
case 'second':
// sufficiently large number of different second cells?
if ((core.asRoughSeconds(labelInterval) / 60) >= MAX_AUTO_SLOTS_PER_LABEL) {
format0 = { hour: 'numeric', minute: '2-digit', meridiem: 'lowercase' }; // '8:30 PM'
format1 = function (params) {
return ':' + core.padStart(params.date.second, 2); // ':30'
};
}
else {
format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
}
break;
case 'millisecond':
format0 = { hour: 'numeric', minute: '2-digit', second: '2-digit', meridiem: 'lowercase' }; // '8:30:45 PM'
format1 = function (params) {
return '.' + core.padStart(params.millisecond, 3);
};
break;
}
return [].concat(format0 || [], format1 || [], format2 || []);
}
// Compute the number of the give units in the "current" range.
// Won't go more precise than days.
// Will return `0` if there's not a clean whole interval.
function currentRangeAs(unit, dateProfile, dateEnv) {
var range = dateProfile.currentRange;
var res = null;
if (unit === 'years') {
res = dateEnv.diffWholeYears(range.start, range.end);
}
else if (unit === 'months') {
res = dateEnv.diffWholeMonths(range.start, range.end);
}
else if (unit === 'weeks') {
res = dateEnv.diffWholeMonths(range.start, range.end);
}
else if (unit === 'days') {
res = core.diffWholeDays(range.start, range.end);
}
return res || 0;
}
function buildIsWeekStarts(tDateProfile, dateEnv) {
var slotDates = tDateProfile.slotDates, emphasizeWeeks = tDateProfile.emphasizeWeeks;
var prevWeekNumber = null;
var isWeekStarts = [];
for (var _i = 0, slotDates_1 = slotDates; _i < slotDates_1.length; _i++) {
var slotDate = slotDates_1[_i];
var weekNumber = dateEnv.computeWeekNumber(slotDate);
var isWeekStart = emphasizeWeeks && (prevWeekNumber !== null) && (prevWeekNumber !== weekNumber);
prevWeekNumber = weekNumber;
isWeekStarts.push(isWeekStart);
}
return isWeekStarts;
}
function buildCellRows(tDateProfile, dateEnv, view) {
var slotDates = tDateProfile.slotDates;
var formats = tDateProfile.headerFormats;
var cellRows = formats.map(function (format) { return []; }); // indexed by row,col
// specifically for navclicks
var rowUnits = formats.map(function (format) {
return format.getLargestUnit ? format.getLargestUnit() : null;
});
// builds cellRows and slotCells
for (var i = 0; i < slotDates.length; i++) {
var date = slotDates[i];
var isWeekStart = tDateProfile.isWeekStarts[i];
for (var row = 0; row < formats.length; row++) {
var format = formats[row];
var rowCells = cellRows[row];
var leadingCell = rowCells[rowCells.length - 1];
var isSuperRow = (formats.length > 1) && (row < (formats.length - 1)); // more than one row and not the last
var newCell = null;
if (isSuperRow) {
var text = dateEnv.format(date, format);
if (!leadingCell || (leadingCell.text !== text)) {
newCell = buildCellObject(date, text, rowUnits[row], view);
}
else {
leadingCell.colspan += 1;
}
}
else {
if (!leadingCell ||
core.isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.labelInterval))) {
var text = dateEnv.format(date, format);
newCell = buildCellObject(date, text, rowUnits[row], view);
}
else {
leadingCell.colspan += 1;
}
}
if (newCell) {
newCell.weekStart = isWeekStart;
rowCells.push(newCell);
}
}
}
return cellRows;
}
function buildCellObject(date, text, rowUnit, view) {
var spanHtml = core.buildGotoAnchorHtml(view, {
date: date,
type: rowUnit,
forceOff: !rowUnit
}, {
'class': 'fc-cell-text'
}, core.htmlEscape(text));
return { text: text, spanHtml: spanHtml, date: date, colspan: 1, isWeekStart: false };
}
var TimelineNowIndicator = /** @class */ (function () {
function TimelineNowIndicator(headParent, bodyParent) {
this.headParent = headParent;
this.bodyParent = bodyParent;
}
TimelineNowIndicator.prototype.render = function (coord, isRtl) {
var styleProps = isRtl ? { right: -coord } : { left: coord };
this.headParent.appendChild(this.arrowEl = core.createElement('div', {
className: 'fc-now-indicator fc-now-indicator-arrow',
style: styleProps
}));
this.bodyParent.appendChild(this.lineEl = core.createElement('div', {
className: 'fc-now-indicator fc-now-indicator-line',
style: styleProps
}));
};
TimelineNowIndicator.prototype.unrender = function () {
if (this.arrowEl) {
core.removeElement(this.arrowEl);
}
if (this.lineEl) {
core.removeElement(this.lineEl);
}
};
return TimelineNowIndicator;
}());
var STICKY_PROP_VAL = computeStickyPropVal(); // if null, means not supported at all
var IS_MS_EDGE = /Edge/.test(navigator.userAgent);
var IS_SAFARI = STICKY_PROP_VAL === '-webkit-sticky'; // good b/c doesn't confuse chrome
var STICKY_CLASSNAME = 'fc-sticky';
/*
useful beyond the native position:sticky for these reasons:
- support in IE11
- nice centering support
*/
var StickyScroller = /** @class */ (function () {
function StickyScroller(scroller, isRtl, isVertical) {
var _this = this;
this.usingRelative = null;
/*
known bug: called twice on init. problem when mixing with ScrollJoiner
*/
this.updateSize = function () {
var els = Array.prototype.slice.call(_this.scroller.canvas.el.querySelectorAll('.' + STICKY_CLASSNAME));
var elGeoms = _this.queryElGeoms(els);
var viewportWidth = _this.scroller.el.clientWidth;
if (_this.usingRelative) {
var elDestinations = _this.computeElDestinations(elGeoms, viewportWidth); // read before prepPositioning
assignRelativePositions(els, elGeoms, elDestinations);
}
else {
assignStickyPositions(els, elGeoms, viewportWidth);
}
};
this.scroller = scroller;
this.usingRelative =
!STICKY_PROP_VAL || // IE11
(IS_MS_EDGE && isRtl) || // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/18883305/
((IS_MS_EDGE || IS_SAFARI) && isVertical); // because doesn't work with rowspan in tables, our only vertial use
if (this.usingRelative) {
scroller.on('scrollEnd', this.updateSize);
}
}
StickyScroller.prototype.destroy = function () {
this.scroller.off('scrollEnd', this.updateSize);
};
StickyScroller.prototype.queryElGeoms = function (els) {
var canvasOrigin = this.scroller.canvas.el.getBoundingClientRect();
var elGeoms = [];
for (var _i = 0, els_1 = els; _i < els_1.length; _i++) {
var el = els_1[_i];
var parentBound = core.translateRect(el.parentNode.getBoundingClientRect(), -canvasOrigin.left, -canvasOrigin.top);
var elRect = el.getBoundingClientRect();
var computedStyles = window.getComputedStyle(el);
var computedTextAlign = window.getComputedStyle(el.parentNode).textAlign; // ask the parent
var intendedTextAlign = computedTextAlign;
var naturalBound = null;
if (computedStyles.position !== 'sticky') {
naturalBound = core.translateRect(elRect, -canvasOrigin.left - (parseFloat(computedStyles.left) || 0), // could be 'auto'
-canvasOrigin.top - (parseFloat(computedStyles.top) || 0));
}
if (el.hasAttribute('data-sticky-center')) {
intendedTextAlign = 'center';
}
elGeoms.push({
parentBound: parentBound,
naturalBound: naturalBound,
elWidth: elRect.width,
elHeight: elRect.height,
computedTextAlign: computedTextAlign,
intendedTextAlign: intendedTextAlign
});
}
return elGeoms;
};
StickyScroller.prototype.computeElDestinations = function (elGeoms, viewportWidth) {
var viewportLeft = this.scroller.getScrollFromLeft();
var viewportTop = this.scroller.getScrollTop();
var viewportRight = viewportLeft + viewportWidth;
return elGeoms.map(function (elGeom) {
var elWidth = elGeom.elWidth, elHeight = elGeom.elHeight, parentBound = elGeom.parentBound, naturalBound = elGeom.naturalBound;
var destLeft; // relative to canvas topleft
var destTop; // "
switch (elGeom.intendedTextAlign) {
case 'left':
destLeft = viewportLeft;
break;
case 'right':
destLeft = viewportRight - elWidth;
break;
case 'center':
destLeft = (viewportLeft + viewportRight) / 2 - elWidth / 2;
break;
}
destLeft = Math.min(destLeft, parentBound.right - elWidth);
destLeft = Math.max(destLeft, parentBound.left);
destTop = viewportTop;
destTop = Math.min(destTop, parentBound.bottom - elHeight);
destTop = Math.max(destTop, naturalBound.top); // better to use natural top for upper bound
return { left: destLeft, top: destTop };
});
};
return StickyScroller;
}());
function assignRelativePositions(els, elGeoms, elDestinations) {
els.forEach(function (el, i) {
var naturalBound = elGeoms[i].naturalBound;
core.applyStyle(el, {
position: 'relative',
left: elDestinations[i].left - naturalBound.left,
top: elDestinations[i].top - naturalBound.top
});
});
}
function assignStickyPositions(els, elGeoms, viewportWidth) {
els.forEach(function (el, i) {
var stickyLeft = 0;
if (elGeoms[i].intendedTextAlign === 'center') {
stickyLeft = (viewportWidth - elGeoms[i].elWidth) / 2;
// needs to be forced to left?
if (elGeoms[i].computedTextAlign === 'center') {
el.setAttribute('data-sticky-center', '') // remember for next queryElGeoms
;
el.parentNode.style.textAlign = 'left';
}
}
core.applyStyle(el, {
position: STICKY_PROP_VAL,
left: stickyLeft,
right: 0,
top: 0
});
});
}
function computeStickyPropVal() {
var el = core.htmlToElement('<div style="position:-webkit-sticky;position:sticky"></div>');
var val = el.style.position;
if (val.indexOf('sticky') !== -1) {
return val;
}
else {
return null;
}
}
var TimeAxis = /** @class */ (function (_super) {
__extends(TimeAxis, _super);
function TimeAxis(context, headerContainerEl, bodyContainerEl) {
var _this = _super.call(this, context) || this;
var layout = _this.layout = new HeaderBodyLayout(headerContainerEl, bodyContainerEl, 'auto');
var headerEnhancedScroller = layout.headerScroller.enhancedScroll;
var bodyEnhancedScroller = layout.bodyScroller.enhancedScroll;
// needs to go after layout, which has ScrollJoiner
_this.headStickyScroller = new StickyScroller(headerEnhancedScroller, _this.isRtl, false); // isVertical=false
_this.bodyStickyScroller = new StickyScroller(bodyEnhancedScroller, _this.isRtl, false); // isVertical=false
_this.header = new TimelineHeader(context, headerEnhancedScroller.canvas.contentEl);
_this.slats = new TimelineSlats(context, bodyEnhancedScroller.canvas.bgEl);
_this.nowIndicator = new TimelineNowIndicator(headerEnhancedScroller.canvas.el, bodyEnhancedScroller.canvas.el);
return _this;
}
TimeAxis.prototype.destroy = function () {
this.layout.destroy();
this.header.destroy();
this.slats.destroy();
this.nowIndicator.unrender();
this.headStickyScroller.destroy();
this.bodyStickyScroller.destroy();
_super.prototype.destroy.call(this);
};
TimeAxis.prototype.render = function (props) {
var tDateProfile = this.tDateProfile =
buildTimelineDateProfile(props.dateProfile, this.view); // TODO: cache
this.header.receiveProps({
dateProfile: props.dateProfile,
tDateProfile: tDateProfile
});
this.slats.receiveProps({
dateProfile: props.dateProfile,
tDateProfile: tDateProfile
});
};
// Now Indicator
// ------------------------------------------------------------------------------------------
TimeAxis.prototype.getNowIndicatorUnit = function (dateProfile) {
// yuck
var tDateProfile = this.tDateProfile =
buildTimelineDateProfile(dateProfile, this.view); // TODO: cache
if (tDateProfile.isTimeScale) {
return core.greatestDurationDenominator(tDateProfile.slotDuration).unit;
}
};
// will only execute if isTimeScale
TimeAxis.prototype.renderNowIndicator = function (date) {
if (core.rangeContainsMarker(this.tDateProfile.normalizedRange, date)) {
this.nowIndicator.render(this.dateToCoord(date), this.isRtl);
}
};
// will only execute if isTimeScale
TimeAxis.prototype.unrenderNowIndicator = function () {
this.nowIndicator.unrender();
};
// Sizing
// ------------------------------------------------------------------------------------------
TimeAxis.prototype.updateSize = function (isResize, totalHeight, isAuto) {
this.applySlotWidth(this.computeSlotWidth());
// adjusts gutters. do after slot widths set
this.layout.setHeight(totalHeight, isAuto);
// pretty much just queries coords. do last
this.slats.updateSize();
};
TimeAxis.prototype.updateStickyScrollers = function () {
this.headStickyScroller.updateSize();
this.bodyStickyScroller.updateSize();
};
TimeAxis.prototype.computeSlotWidth = function () {
var slotWidth = this.opt('slotWidth') || '';
if (slotWidth === '') {
slotWidth = this.computeDefaultSlotWidth(this.tDateProfile);
}
return slotWidth;
};
TimeAxis.prototype.computeDefaultSlotWidth = function (tDateProfile) {
var maxInnerWidth = 0; // TODO: harness core's `matchCellWidths` for this
this.header.innerEls.forEach(function (innerEl, i) {
maxInnerWidth = Math.max(maxInnerWidth, innerEl.getBoundingClientRect().width);
});
var headingCellWidth = Math.ceil(maxInnerWidth) + 1; // assume no padding, and one pixel border
// in TimelineView.defaults we ensured that labelInterval is an interval of slotDuration
// TODO: rename labelDuration?
var slotsPerLabel = core.wholeDivideDurations(tDateProfile.labelInterval, tDateProfile.slotDuration);
var slotWidth = Math.ceil(headingCellWidth / slotsPerLabel);
var minWidth = window.getComputedStyle(this.header.slatColEls[0]).minWidth;
if (minWidth) {
minWidth = parseInt(minWidth, 10);
if (minWidth) {
slotWidth = Math.max(slotWidth, minWidth);
}
}
return slotWidth;
};
TimeAxis.prototype.applySlotWidth = function (slotWidth) {
var _a = this, layout = _a.layout, tDateProfile = _a.tDateProfile;
var containerWidth = '';
var containerMinWidth = '';
var nonLastSlotWidth = '';
if (slotWidth !== '') {
slotWidth = Math.round(slotWidth);
containerWidth = slotWidth * tDateProfile.slotDates.length;
containerMinWidth = '';
nonLastSlotWidth = slotWidth;
var availableWidth = layout.bodyScroller.enhancedScroll.getClientWidth();
if (availableWidth > containerWidth) {
containerMinWidth = availableWidth;
containerWidth = '';
nonLastSlotWidth = Math.floor(availableWidth / tDateProfile.slotDates.length);
}
}
layout.headerScroller.enhancedScroll.canvas.setWidth(containerWidth);
layout.headerScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth);
layout.bodyScroller.enhancedScroll.canvas.setWidth(containerWidth);
layout.bodyScroller.enhancedScroll.canvas.setMinWidth(containerMinWidth);
if (nonLastSlotWidth !== '') {
this.header.slatColEls.slice(0, -1).concat(this.slats.slatColEls.slice(0, -1)).forEach(function (el) {
el.style.width = nonLastSlotWidth + 'px';
});
}
};
// returned value is between 0 and the number of snaps
TimeAxis.prototype.computeDateSnapCoverage = function (date) {
var _a = this, dateEnv = _a.dateEnv, tDateProfile = _a.tDateProfile;
var snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration);
if (snapDiff < 0) {
return 0;
}
else if (snapDiff >= tDateProfile.snapDiffToIndex.length) {
return tDateProfile.snapCnt;
}
else {
var snapDiffInt = Math.floor(snapDiff);
var snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt];
if (core.isInt(snapCoverage)) { // not an in-between value
snapCoverage += snapDiff - snapDiffInt; // add the remainder
}
else {
// a fractional value, meaning the date is not visible
// always round up in this case. works for start AND end dates in a range.
snapCoverage = Math.ceil(snapCoverage);
}
return snapCoverage;
}
};
// for LTR, results range from 0 to width of area
// for RTL, results range from negative width of area to 0
TimeAxis.prototype.dateToCoord = function (date) {
var tDateProfile = this.tDateProfile;
var snapCoverage = this.computeDateSnapCoverage(date);
var slotCoverage = snapCoverage / tDateProfile.snapsPerSlot;
var slotIndex = Math.floor(slotCoverage);
slotIndex = Math.min(slotIndex, tDateProfile.slotCnt - 1);
var partial = slotCoverage - slotIndex;
var _a = this.slats, innerCoordCache = _a.innerCoordCache, outerCoordCache = _a.outerCoordCache;
if (this.isRtl) {
return (outerCoordCache.rights[slotIndex] -
(innerCoordCache.getWidth(slotIndex) * partial)) - outerCoordCache.originClientRect.width;
}
else {
return (outerCoordCache.lefts[slotIndex] +
(innerCoordCache.getWidth(slotIndex) * partial));
}
};
TimeAxis.prototype.rangeToCoords = function (range) {
if (this.isRtl) {
return { right: this.dateToCoord(range.start), left: this.dateToCoord(range.end) };
}
else {
return { left: this.dateToCoord(range.start), right: this.dateToCoord(range.end) };
}
};
// Scrolling
// ------------------------------------------------------------------------------------------
TimeAxis.prototype.computeDateScroll = function (duration) {
var dateEnv = this.dateEnv;
var dateProfile = this.props.dateProfile;
var left = 0;
if (dateProfile) {
left = this.dateToCoord(dateEnv.add(core.startOfDay(dateProfile.activeRange.start), // startOfDay needed?
duration));
// hack to overcome the left borders of non-first slat
if (!this.isRtl && left) {
left += 1;
}
}
return { left: left };
};
TimeAxis.prototype.queryDateScroll = function () {
var enhancedScroll = this.layout.bodyScroller.enhancedScroll;
return {
left: enhancedScroll.getScrollLeft()
};
};
TimeAxis.prototype.applyDateScroll = function (scroll) {
// TODO: lame we have to update both. use the scrolljoiner instead maybe
this.layout.bodyScroller.enhancedScroll.setScrollLeft(scroll.left || 0);
this.layout.headerScroller.enhancedScroll.setScrollLeft(scroll.left || 0);
};
return TimeAxis;
}(core.Component));
var TimelineLaneEventRenderer = /** @class */ (function (_super) {
__extends(TimelineLaneEventRenderer, _super);
function TimelineLaneEventRenderer(context, masterContainerEl, timeAxis) {
var _this = _super.call(this, context) || this;
_this.masterContainerEl = masterContainerEl;
_this.timeAxis = timeAxis;
return _this;
}
TimelineLaneEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
var view = this.context.view;
var eventRange = seg.eventRange;
var eventDef = eventRange.def;
var eventUi = eventRange.ui;
var isDraggable = view.computeEventDraggable(eventDef, eventUi);
var isResizableFromStart = seg.isStart && view.computeEventStartResizable(eventDef, eventUi);
var isResizableFromEnd = seg.isEnd && view.computeEventEndResizable(eventDef, eventUi);
var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd, mirrorInfo);
classes.unshift('fc-timeline-event', 'fc-h-event');
var timeText = this.getTimeText(eventRange);
return '<a class="' + classes.join(' ') + '" style="' + core.cssToStr(this.getSkinCss(eventUi)) + '"' +
(eventDef.url ?
' href="' + core.htmlEscape(eventDef.url) + '"' :
'') +
'>' +
(timeText ?
'<span class="fc-time-wrap">' +
'<span class="fc-time">' +
core.htmlEscape(timeText) +
'</span>' +
'</span>'
:
'') +
'<span class="fc-title-wrap">' +
'<span class="fc-title fc-sticky">' +
(eventDef.title ? core.htmlEscape(eventDef.title) : '&nbsp;') +
'</span>' +
'</span>' +
(isResizableFromStart ?
'<div class="fc-resizer fc-start-resizer"></div>' :
'') +
(isResizableFromEnd ?
'<div class="fc-resizer fc-end-resizer"></div>' :
'') +
'</a>';
};
TimelineLaneEventRenderer.prototype.computeDisplayEventTime = function () {
return !this.timeAxis.tDateProfile.isTimeScale; // because times should be obvious via axis
};
TimelineLaneEventRenderer.prototype.computeDisplayEventEnd = function () {
return false;
};
// Computes a default event time formatting string if `timeFormat` is not explicitly defined
TimelineLaneEventRenderer.prototype.computeEventTimeFormat = function () {
return {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'narrow'
};
};
TimelineLaneEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
if (!this.el && this.masterContainerEl) {
this.el = core.createElement('div', { className: 'fc-event-container' });
if (mirrorInfo) {
this.el.classList.add('fc-mirror-container');
}
this.masterContainerEl.appendChild(this.el);
}
if (this.el) {
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
this.el.appendChild(seg.el);
}
}
};
TimelineLaneEventRenderer.prototype.detachSegs = function (segs) {
for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
var seg = segs_2[_i];
core.removeElement(seg.el);
}
};
// computes AND assigns (assigns the left/right at least). bad
TimelineLaneEventRenderer.prototype.computeSegSizes = function (segs) {
var timeAxis = this.timeAxis;
for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
var seg = segs_3[_i];
var coords = timeAxis.rangeToCoords(seg); // works because Seg has start/end
core.applyStyle(seg.el, {
left: (seg.left = coords.left),
right: -(seg.right = coords.right)
});
}
};
TimelineLaneEventRenderer.prototype.assignSegSizes = function (segs) {
if (!this.el) {
return;
}
// compute seg verticals
for (var _i = 0, segs_4 = segs; _i < segs_4.length; _i++) {
var seg = segs_4[_i];
seg.height = core.computeHeightAndMargins(seg.el);
}
this.buildSegLevels(segs); // populates above/below props for computeOffsetForSegs
var totalHeight = computeOffsetForSegs(segs); // also assigns seg.top
core.applyStyleProp(this.el, 'height', totalHeight);
// assign seg verticals
for (var _a = 0, segs_5 = segs; _a < segs_5.length; _a++) {
var seg = segs_5[_a];
core.applyStyleProp(seg.el, 'top', seg.top);
}
};
TimelineLaneEventRenderer.prototype.buildSegLevels = function (segs) {
var segLevels = [];
segs = this.sortEventSegs(segs);
for (var _i = 0, segs_6 = segs; _i < segs_6.length; _i++) {
var unplacedSeg = segs_6[_i];
unplacedSeg.above = [];
// determine the first level with no collisions
var level = 0; // level index
while (level < segLevels.length) {
var isLevelCollision = false;
// determine collisions
for (var _a = 0, _b = segLevels[level]; _a < _b.length; _a++) {
var placedSeg = _b[_a];
if (timeRowSegsCollide(unplacedSeg, placedSeg)) {
unplacedSeg.above.push(placedSeg);
isLevelCollision = true;
}
}
if (isLevelCollision) {
level += 1;
}
else {
break;
}
}
// insert into the first non-colliding level. create if necessary
(segLevels[level] || (segLevels[level] = []))
.push(unplacedSeg);
// record possible colliding segments below (TODO: automated test for this)
level += 1;
while (level < segLevels.length) {
for (var _c = 0, _d = segLevels[level]; _c < _d.length; _c++) {
var belowSeg = _d[_c];
if (timeRowSegsCollide(unplacedSeg, belowSeg)) {
belowSeg.above.push(unplacedSeg);
}
}
level += 1;
}
}
return segLevels;
};
return TimelineLaneEventRenderer;
}(core.FgEventRenderer));
function computeOffsetForSegs(segs) {
var max = 0;
for (var _i = 0, segs_7 = segs; _i < segs_7.length; _i++) {
var seg = segs_7[_i];
max = Math.max(max, computeOffsetForSeg(seg));
}
return max;
}
function computeOffsetForSeg(seg) {
if ((seg.top == null)) {
seg.top = computeOffsetForSegs(seg.above);
}
return seg.top + seg.height;
}
function timeRowSegsCollide(seg0, seg1) {
return (seg0.left < seg1.right) && (seg0.right > seg1.left);
}
var TimelineLaneFillRenderer = /** @class */ (function (_super) {
__extends(TimelineLaneFillRenderer, _super);
function TimelineLaneFillRenderer(context, masterContainerEl, timeAxis) {
var _this = _super.call(this, context) || this;
_this.masterContainerEl = masterContainerEl;
_this.timeAxis = timeAxis;
return _this;
}
TimelineLaneFillRenderer.prototype.attachSegs = function (type, segs) {
if (segs.length) {
var className = void 0;
if (type === 'businessHours') {
className = 'bgevent';
}
else {
className = type.toLowerCase();
}
// making a new container each time is OKAY
// all types of segs (background or business hours or whatever) are rendered in one pass
var containerEl = core.createElement('div', { className: 'fc-' + className + '-container' });
this.masterContainerEl.appendChild(containerEl);
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
containerEl.appendChild(seg.el);
}
return [containerEl]; // return value
}
};
TimelineLaneFillRenderer.prototype.computeSegSizes = function (segs) {
var timeAxis = this.timeAxis;
for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
var seg = segs_2[_i];
var coords = timeAxis.rangeToCoords(seg);
seg.left = coords.left;
seg.right = coords.right;
}
};
TimelineLaneFillRenderer.prototype.assignSegSizes = function (segs) {
for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
var seg = segs_3[_i];
core.applyStyle(seg.el, {
left: seg.left,
right: -seg.right
});
}
};
return TimelineLaneFillRenderer;
}(core.FillRenderer));
var TimelineLane = /** @class */ (function (_super) {
__extends(TimelineLane, _super);
function TimelineLane(context, fgContainerEl, bgContainerEl, timeAxis) {
var _this = _super.call(this, context, bgContainerEl) // should el be bgContainerEl???
|| this;
_this.slicer = new TimelineLaneSlicer();
_this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag);
_this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize);
var fillRenderer = _this.fillRenderer = new TimelineLaneFillRenderer(context, bgContainerEl, timeAxis);
var eventRenderer = _this.eventRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis);
_this.mirrorRenderer = new TimelineLaneEventRenderer(context, fgContainerEl, timeAxis);
_this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'));
_this.renderDateSelection = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'highlight'), fillRenderer.unrender.bind(fillRenderer, 'highlight'));
_this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'));
_this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer));
_this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
_this.timeAxis = timeAxis;
return _this;
}
TimelineLane.prototype.render = function (props) {
var slicedProps = this.slicer.sliceProps(props, props.dateProfile, this.timeAxis.tDateProfile.isTimeScale ? null : props.nextDayThreshold, this, this.timeAxis);
this.renderBusinessHours(slicedProps.businessHourSegs);
this.renderDateSelection(slicedProps.dateSelectionSegs);
this.renderBgEvents(slicedProps.bgEventSegs);
this.renderFgEvents(slicedProps.fgEventSegs);
this.renderEventSelection(slicedProps.eventSelection);
this.renderEventDrag(slicedProps.eventDrag);
this.renderEventResize(slicedProps.eventResize);
};
TimelineLane.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.renderBusinessHours.unrender();
this.renderDateSelection.unrender();
this.renderBgEvents.unrender();
this.renderFgEvents.unrender();
this.renderEventSelection.unrender();
this.renderEventDrag.unrender();
this.renderEventResize.unrender();
};
TimelineLane.prototype._renderEventDrag = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype._unrenderEventDrag = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype._renderEventResize = function (state) {
if (state) {
// HACK. eventRenderer and fillRenderer both use these segs. would compete over seg.el
var segsForHighlight = state.segs.map(function (seg) {
return __assign({}, seg);
});
this.eventRenderer.hideByHash(state.affectedInstances);
this.fillRenderer.renderSegs('highlight', segsForHighlight);
this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype._unrenderEventResize = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.fillRenderer.unrender('highlight');
this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
};
TimelineLane.prototype.updateSize = function (isResize) {
var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
fillRenderer.computeSizes(isResize);
eventRenderer.computeSizes(isResize);
mirrorRenderer.computeSizes(isResize);
fillRenderer.assignSizes(isResize);
eventRenderer.assignSizes(isResize);
mirrorRenderer.assignSizes(isResize);
};
return TimelineLane;
}(core.DateComponent));
var TimelineLaneSlicer = /** @class */ (function (_super) {
__extends(TimelineLaneSlicer, _super);
function TimelineLaneSlicer() {
return _super !== null && _super.apply(this, arguments) || this;
}
TimelineLaneSlicer.prototype.sliceRange = function (origRange, timeAxis) {
var tDateProfile = timeAxis.tDateProfile;
var dateProfile = timeAxis.props.dateProfile;
var normalRange = normalizeRange(origRange, tDateProfile, timeAxis.dateEnv);
var segs = [];
// protect against when the span is entirely in an invalid date region
if (timeAxis.computeDateSnapCoverage(normalRange.start) < timeAxis.computeDateSnapCoverage(normalRange.end)) {
// intersect the footprint's range with the grid's range
var slicedRange = core.intersectRanges(normalRange, tDateProfile.normalizedRange);
if (slicedRange) {
segs.push({
start: slicedRange.start,
end: slicedRange.end,
isStart: slicedRange.start.valueOf() === normalRange.start.valueOf() && isValidDate(slicedRange.start, tDateProfile, dateProfile, timeAxis.view),
isEnd: slicedRange.end.valueOf() === normalRange.end.valueOf() && isValidDate(core.addMs(slicedRange.end, -1), tDateProfile, dateProfile, timeAxis.view)
});
}
}
return segs;
};
return TimelineLaneSlicer;
}(core.Slicer));
var TimelineView = /** @class */ (function (_super) {
__extends(TimelineView, _super);
function TimelineView(context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.el.classList.add('fc-timeline');
if (_this.opt('eventOverlap') === false) {
_this.el.classList.add('fc-no-overlap');
}
_this.el.innerHTML = _this.renderSkeletonHtml();
_this.timeAxis = new TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area'));
_this.lane = new TimelineLane(_this.context, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis);
context.calendar.registerInteractiveComponent(_this, {
el: _this.timeAxis.slats.el
});
return _this;
}
TimelineView.prototype.destroy = function () {
this.timeAxis.destroy();
this.lane.destroy();
_super.prototype.destroy.call(this);
this.calendar.unregisterInteractiveComponent(this);
};
TimelineView.prototype.renderSkeletonHtml = function () {
var theme = this.theme;
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>";
};
TimelineView.prototype.render = function (props) {
_super.prototype.render.call(this, props); // flags for updateSize, addScroll
this.timeAxis.receiveProps({
dateProfile: props.dateProfile
});
this.lane.receiveProps(__assign({}, props, { nextDayThreshold: this.nextDayThreshold }));
};
TimelineView.prototype.updateSize = function (isResize, totalHeight, isAuto) {
this.timeAxis.updateSize(isResize, totalHeight, isAuto);
this.lane.updateSize(isResize);
};
// Now Indicator
// ------------------------------------------------------------------------------------------
TimelineView.prototype.getNowIndicatorUnit = function (dateProfile) {
return this.timeAxis.getNowIndicatorUnit(dateProfile);
};
TimelineView.prototype.renderNowIndicator = function (date) {
this.timeAxis.renderNowIndicator(date);
};
TimelineView.prototype.unrenderNowIndicator = function () {
this.timeAxis.unrenderNowIndicator();
};
// Scroll System
// ------------------------------------------------------------------------------------------
TimelineView.prototype.computeDateScroll = function (duration) {
return this.timeAxis.computeDateScroll(duration);
};
TimelineView.prototype.applyScroll = function (scroll, isResize) {
_super.prototype.applyScroll.call(this, scroll, isResize); // will call applyDateScroll
// avoid updating stickyscroll too often
// TODO: repeat code as ResourceTimelineView::updateSize
var calendar = this.calendar;
if (isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated) {
this.timeAxis.updateStickyScrollers();
}
};
TimelineView.prototype.applyDateScroll = function (scroll) {
this.timeAxis.applyDateScroll(scroll);
};
TimelineView.prototype.queryScroll = function () {
var enhancedScroll = this.timeAxis.layout.bodyScroller.enhancedScroll;
return {
top: enhancedScroll.getScrollTop(),
left: enhancedScroll.getScrollLeft()
};
};
// Hit System
// ------------------------------------------------------------------------------------------
TimelineView.prototype.buildPositionCaches = function () {
this.timeAxis.slats.updateSize();
};
TimelineView.prototype.queryHit = function (positionLeft, positionTop, elWidth, elHeight) {
var slatHit = this.timeAxis.slats.positionToHit(positionLeft);
if (slatHit) {
return {
component: this,
dateSpan: slatHit.dateSpan,
rect: {
left: slatHit.left,
right: slatHit.right,
top: 0,
bottom: elHeight
},
dayEl: slatHit.dayEl,
layer: 0
};
}
};
return TimelineView;
}(core.View));
var main = core.createPlugin({
defaultView: 'timelineDay',
views: {
timeline: {
class: TimelineView,
eventResizableFromStart: true // how is this consumed for TimelineView tho?
},
timelineDay: {
type: 'timeline',
duration: { days: 1 }
},
timelineWeek: {
type: 'timeline',
duration: { weeks: 1 }
},
timelineMonth: {
type: 'timeline',
duration: { months: 1 }
},
timelineYear: {
type: 'timeline',
duration: { years: 1 }
}
}
});
exports.HeaderBodyLayout = HeaderBodyLayout;
exports.ScrollJoiner = ScrollJoiner;
exports.StickyScroller = StickyScroller;
exports.TimeAxis = TimeAxis;
exports.TimelineLane = TimelineLane;
exports.TimelineView = TimelineView;
exports.default = main;
Object.defineProperty(exports, '__esModule', { value: true });
}));
.fc-scroller-clip{overflow:hidden;position:relative}.fc-no-scrollbars{background:rgba(255,255,255,0)}.fc-no-scrollbars::-webkit-scrollbar{width:0;height:0}.fc-scroller-canvas{position:relative;box-sizing:border-box;min-height:100%}.fc-scroller-canvas>.fc-bg{z-index:1}.fc-scroller-canvas>.fc-content{z-index:2;position:relative;border-style:solid;border-width:0}.fc-scroller-canvas.fc-gutter-left>.fc-content{border-left-width:1px;margin-left:-1px}.fc-scroller-canvas.fc-gutter-right>.fc-content{border-right-width:1px;margin-right:-1px}.fc-scroller-canvas.fc-gutter-top>.fc-content{border-top-width:1px;margin-top:-1px}.fc-rtl .fc-timeline{direction:rtl}.fc-scrolled .fc-head .fc-scroller{z-index:2}.fc-timeline.fc-scrolled .fc-head .fc-scroller{box-shadow:0 3px 4px rgba(0,0,0,.075)}.fc-timeline .fc-body .fc-scroller{z-index:1}.fc-timeline .fc-scroller-canvas>div>div>table,.fc-timeline .fc-scroller-canvas>div>table{border-style:hidden}.fc-timeline .fc-scroller-canvas>.fc-content>.fc-rows>table{border-bottom-style:none}.fc-timeline td,.fc-timeline th{white-space:nowrap}.fc-timeline .fc-cell-content{overflow:hidden}.fc-timeline .fc-cell-text{display:inline-block;padding-left:4px;padding-right:4px}.fc-timeline th{vertical-align:middle}.fc-timeline .fc-head .fc-cell-content{padding-top:3px;padding-bottom:3px}.fc-timeline .fc-head .fc-time-area .fc-cell-content{overflow:visible}.fc-time-area col{min-width:2.2em}.fc-ltr .fc-time-area .fc-chrono th{text-align:left}.fc-rtl .fc-time-area .fc-chrono th{text-align:right}.fc-time-area .fc-slats{position:absolute;z-index:1;top:0;left:0;right:0;bottom:0}.fc-time-area .fc-slats table{height:100%}.fc-time-area .fc-slats .fc-minor{border-style:dotted}.fc-time-area .fc-slats td{border-width:0 1px}.fc-ltr .fc-time-area .fc-slats td{border-right-width:0}.fc-rtl .fc-time-area .fc-slats td{border-left-width:0}.fc-time-area .fc-bgevent-container,.fc-time-area .fc-highlight-container{position:absolute;z-index:2;top:0;bottom:0;width:0}.fc-ltr .fc-time-area .fc-bgevent-container,.fc-ltr .fc-time-area .fc-highlight-container,.fc-ltr .fc-time-area .fc-mirror-container{left:0}.fc-rtl .fc-time-area .fc-bgevent-container,.fc-rtl .fc-time-area .fc-highlight-container,.fc-rtl .fc-time-area .fc-mirror-container{right:0}.fc-time-area .fc-bgevent,.fc-time-area .fc-highlight{position:absolute;top:0;bottom:0}.fc-timeline .fc-now-indicator{z-index:3;top:0}.fc-time-area .fc-now-indicator-arrow{margin:0 -6px;border-width:6px 5px 0;border-left-color:transparent;border-right-color:transparent}.fc-time-area .fc-now-indicator-line{margin:0 -1px;bottom:0;border-left-width:1px}.fc-time-area .fc-event-container{position:relative;z-index:2;width:0}.fc-time-area .fc-mirror-container{position:absolute;z-index:3;top:0}.fc-time-area .fc-event-container{padding-bottom:8px;top:-1px}.fc-time-area tr:first-child .fc-event-container{top:0}.fc-no-overlap .fc-time-area .fc-event-container{padding-bottom:0;top:0}.fc-timeline-event{position:absolute;display:flex;border-radius:0;padding:2px 1px;margin-bottom:1px}.fc-no-overlap .fc-timeline-event{padding-top:5px;padding-bottom:5px;margin-bottom:0}.fc-ltr .fc-timeline-event{flex-direction:row;margin-right:1px}.fc-rtl .fc-timeline-event{margin-left:1px}.fc-timeline-event .fc-time-wrap{flex-shrink:0;min-width:0}.fc-timeline-event .fc-title-wrap{flex-grow:1;min-width:0}.fc-timeline-event .fc-time,.fc-timeline-event .fc-title{display:inline-block;vertical-align:top;max-width:100%;padding:0 2px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;white-space:nowrap;overflow:hidden}.fc-timeline-event .fc-time{font-weight:700}.fc-timeline-event.fc-not-end:after,.fc-timeline-event.fc-not-start:before{content:"";align-self:center;width:0;height:0;margin:0 1px;border:5px solid #000;border-top-color:transparent;border-bottom-color:transparent;opacity:.5}.fc-ltr .fc-timeline-event.fc-not-start:before,.fc-rtl .fc-timeline-event.fc-not-end:after{border-left:0}.fc-ltr .fc-timeline-event.fc-not-end:after,.fc-rtl .fc-timeline-event.fc-not-start:before{border-right:0}
\ No newline at end of file
/*!
FullCalendar Timeline Plugin v4.3.0
Docs & License: https://fullcalendar.io/scheduler
(c) 2019 Adam Shaw
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):t((e=e||self).FullCalendarTimeline={},e.FullCalendar)}(this,function(e,t){"use strict";var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function n(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var i,o=function(){return(o=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},l=function(){function e(){this.gutters={},this.el=t.htmlToElement('<div class="fc-scroller-canvas"> <div class="fc-content"></div> <div class="fc-bg"></div> </div>'),this.contentEl=this.el.querySelector(".fc-content"),this.bgEl=this.el.querySelector(".fc-bg")}return e.prototype.setGutters=function(e){e?o(this.gutters,e):this.gutters={},this.updateSize()},e.prototype.setWidth=function(e){this.width=e,this.updateSize()},e.prototype.setMinWidth=function(e){this.minWidth=e,this.updateSize()},e.prototype.clearWidth=function(){this.width=null,this.minWidth=null,this.updateSize()},e.prototype.updateSize=function(){var e=this.gutters,r=this.el;t.forceClassName(r,"fc-gutter-left",e.left),t.forceClassName(r,"fc-gutter-right",e.right),t.forceClassName(r,"fc-gutter-top",e.top),t.forceClassName(r,"fc-gutter-bottom",e.bottom),t.applyStyle(r,{paddingLeft:e.left||"",paddingRight:e.right||"",paddingTop:e.top||"",paddingBottom:e.bottom||"",width:null!=this.width?this.width+(e.left||0)+(e.right||0):"",minWidth:null!=this.minWidth?this.minWidth+(e.left||0)+(e.right||0):""}),t.applyStyle(this.bgEl,{left:e.left||"",right:e.right||"",top:e.top||"",bottom:e.bottom||""})},e}(),s=function(e){function r(r,n){var i=e.call(this,r,n)||this;return i.reportScroll=function(){i.isScrolling||i.reportScrollStart(),i.trigger("scroll"),i.isMoving=!0,i.requestMovingEnd()},i.reportScrollStart=function(){i.isScrolling||(i.isScrolling=!0,i.trigger("scrollStart",i.isTouching))},i.reportTouchStart=function(){i.isTouching=!0},i.reportTouchEnd=function(){i.isTouching&&(i.isTouching=!1,i.isTouchScrollEnabled&&i.unbindPreventTouchScroll(),i.isMoving||i.reportScrollEnd())},i.isScrolling=!1,i.isTouching=!1,i.isMoving=!1,i.isTouchScrollEnabled=!0,i.requestMovingEnd=t.debounce(i.reportMovingEnd,500),i.canvas=new l,i.el.appendChild(i.canvas.el),i.applyOverflow(),i.bindHandlers(),i}return n(r,e),r.prototype.destroy=function(){e.prototype.destroy.call(this),this.unbindHandlers()},r.prototype.disableTouchScroll=function(){this.isTouchScrollEnabled=!1,this.bindPreventTouchScroll()},r.prototype.enableTouchScroll=function(){this.isTouchScrollEnabled=!0,this.isTouching||this.unbindPreventTouchScroll()},r.prototype.bindPreventTouchScroll=function(){this.preventTouchScrollHandler||this.el.addEventListener("touchmove",this.preventTouchScrollHandler=t.preventDefault)},r.prototype.unbindPreventTouchScroll=function(){this.preventTouchScrollHandler&&(this.el.removeEventListener("touchmove",this.preventTouchScrollHandler),this.preventTouchScrollHandler=null)},r.prototype.bindHandlers=function(){this.el.addEventListener("scroll",this.reportScroll),this.el.addEventListener("touchstart",this.reportTouchStart,{passive:!0}),this.el.addEventListener("touchend",this.reportTouchEnd)},r.prototype.unbindHandlers=function(){this.el.removeEventListener("scroll",this.reportScroll),this.el.removeEventListener("touchstart",this.reportTouchStart,{passive:!0}),this.el.removeEventListener("touchend",this.reportTouchEnd)},r.prototype.reportMovingEnd=function(){this.isMoving=!1,this.isTouching||this.reportScrollEnd()},r.prototype.reportScrollEnd=function(){this.isScrolling&&(this.trigger("scrollEnd"),this.isScrolling=!1)},r.prototype.getScrollLeft=function(){var e=this.el,t=window.getComputedStyle(e).direction,r=e.scrollLeft;if("rtl"===t)switch(a()){case"positive":r=r+e.clientWidth-e.scrollWidth;break;case"reverse":r=-r}return r},r.prototype.setScrollLeft=function(e){var t=this.el;if("rtl"===window.getComputedStyle(t).direction)switch(a()){case"positive":e=e-t.clientWidth+t.scrollWidth;break;case"reverse":e=-e}t.scrollLeft=e},r.prototype.getScrollFromLeft=function(){var e=this.el,t=window.getComputedStyle(e).direction,r=e.scrollLeft;if("rtl"===t)switch(a()){case"negative":r=r-e.clientWidth+e.scrollWidth;break;case"reverse":r=-r-e.clientWidth+e.scrollWidth}return r},r}(t.ScrollComponent);function a(){return i||(i=function(){var e,r=t.htmlToElement('<div style=" position: absolute; top: -1000px; width: 1px; height: 1px; overflow: scroll; direction: rtl; font-size: 100px; ">A</div>');document.body.appendChild(r),r.scrollLeft>0?e="positive":(r.scrollLeft=1,e=r.scrollLeft>0?"reverse":"negative");return t.removeElement(r),e}())}t.EmitterMixin.mixInto(s);var c=function(){function e(e,r,n){this.isHScrollbarsClipped=!1,this.isVScrollbarsClipped=!1,"clipped-scroll"===e&&(e="scroll",this.isHScrollbarsClipped=!0),"clipped-scroll"===r&&(r="scroll",this.isVScrollbarsClipped=!0),this.enhancedScroll=new s(e,r),n.appendChild(this.el=t.createElement("div",{className:"fc-scroller-clip"})),this.el.appendChild(this.enhancedScroll.el)}return e.prototype.destroy=function(){t.removeElement(this.el)},e.prototype.updateSize=function(){var e=this.enhancedScroll,r=e.el,n=t.computeEdges(r),i={marginLeft:0,marginRight:0,marginTop:0,marginBottom:0};this.isVScrollbarsClipped&&(i.marginLeft=-n.scrollbarLeft,i.marginRight=-n.scrollbarRight),this.isHScrollbarsClipped&&(i.marginBottom=-n.scrollbarBottom),t.applyStyle(r,i),!this.isHScrollbarsClipped&&"hidden"!==e.overflowX||!this.isVScrollbarsClipped&&"hidden"!==e.overflowY||n.scrollbarLeft||n.scrollbarRight||n.scrollbarBottom?r.classList.remove("fc-no-scrollbars"):r.classList.add("fc-no-scrollbars")},e.prototype.setHeight=function(e){this.enhancedScroll.setHeight(e)},e.prototype.getScrollbarWidths=function(){var e=this.enhancedScroll.getScrollbarWidths();return this.isVScrollbarsClipped&&(e.left=0,e.right=0),this.isHScrollbarsClipped&&(e.bottom=0),e},e}(),d=function(){function e(e,t){this.axis=e,this.scrollers=t;for(var r=0,n=this.scrollers;r<n.length;r++){var i=n[r];this.initScroller(i)}}return e.prototype.initScroller=function(e){var t=this,r=e.enhancedScroll,n=function(){t.assignMasterScroller(e)};"wheel mousewheel DomMouseScroll MozMousePixelScroll".split(" ").forEach(function(e){r.el.addEventListener(e,n)}),r.on("scrollStart",function(){t.masterScroller||t.assignMasterScroller(e)}).on("scroll",function(){if(e===t.masterScroller)for(var n=0,i=t.scrollers;n<i.length;n++){var o=i[n];if(o!==e)switch(t.axis){case"horizontal":o.enhancedScroll.el.scrollLeft=r.el.scrollLeft;break;case"vertical":o.enhancedScroll.setScrollTop(r.getScrollTop())}}}).on("scrollEnd",function(){e===t.masterScroller&&t.unassignMasterScroller()})},e.prototype.assignMasterScroller=function(e){this.unassignMasterScroller(),this.masterScroller=e;for(var t=0,r=this.scrollers;t<r.length;t++){var n=r[t];n!==e&&n.enhancedScroll.disableTouchScroll()}},e.prototype.unassignMasterScroller=function(){if(this.masterScroller){for(var e=0,t=this.scrollers;e<t.length;e++){t[e].enhancedScroll.enableTouchScroll()}this.masterScroller=null}},e.prototype.update=function(){for(var e,t,r=this.scrollers.map(function(e){return e.getScrollbarWidths()}),n=0,i=0,o=0,l=0,s=0,a=r;s<a.length;s++)e=a[s],n=Math.max(n,e.left),i=Math.max(i,e.right),o=Math.max(o,e.top),l=Math.max(l,e.bottom);for(t=0;t<this.scrollers.length;t++){var c=this.scrollers[t];e=r[t],c.enhancedScroll.canvas.setGutters("horizontal"===this.axis?{left:n-e.left,right:i-e.right}:{top:o-e.top,bottom:l-e.bottom})}},e}(),h=function(){function e(e,t,r){this.headerScroller=new c("clipped-scroll","hidden",e),this.bodyScroller=new c("auto",r,t),this.scrollJoiner=new d("horizontal",[this.headerScroller,this.bodyScroller])}return e.prototype.destroy=function(){this.headerScroller.destroy(),this.bodyScroller.destroy()},e.prototype.setHeight=function(e,t){var r;r=t?"auto":e-this.queryHeadHeight(),this.bodyScroller.setHeight(r),this.headerScroller.updateSize(),this.bodyScroller.updateSize(),this.scrollJoiner.update()},e.prototype.queryHeadHeight=function(){return this.headerScroller.enhancedScroll.canvas.contentEl.getBoundingClientRect().height},e}(),u=function(e){function r(r,n){var i=e.call(this,r)||this;return n.appendChild(i.tableEl=t.createElement("table",{className:i.theme.getClass("tableGrid")})),i}return n(r,e),r.prototype.destroy=function(){t.removeElement(this.tableEl),e.prototype.destroy.call(this)},r.prototype.render=function(e){this.renderDates(e.tDateProfile)},r.prototype.renderDates=function(e){for(var r=this.dateEnv,n=this.theme,i=e.cellRows,o=i[i.length-1],l=t.asRoughMs(e.labelInterval)>t.asRoughMs(e.slotDuration),s=t.isSingleDay(e.slotDuration),a="<colgroup>",c=e.slotCnt-1;c>=0;c--)a+="<col/>";a+="</colgroup>",a+="<tbody>";for(var d=0,h=i;d<h.length;d++){var u=h[d];a+="<tr"+(l&&u===o?' class="fc-chrono"':"")+">";for(var p=0,f=u;p<f.length;p++){var g=f[p],m=[n.getClass("widgetHeader")];g.isWeekStart&&m.push("fc-em-cell"),s&&(m=m.concat(t.getDayClasses(g.date,this.props.dateProfile,this.context,!0))),a+='<th class="'+m.join(" ")+'" data-date="'+r.formatIso(g.date,{omitTime:!e.isTimeScale,omitTimeZoneOffset:!0})+'"'+(g.colspan>1?' colspan="'+g.colspan+'"':"")+'><div class="fc-cell-content">'+g.spanHtml+"</div></th>"}a+="</tr>"}a+="</tbody>",this.tableEl.innerHTML=a,this.slatColEls=t.findElements(this.tableEl,"col"),this.innerEls=t.findElements(this.tableEl.querySelector("tr:last-child"),"th .fc-cell-text"),t.findElements(this.tableEl.querySelectorAll("tr:not(:last-child)"),"th .fc-cell-text").forEach(function(e){e.classList.add("fc-sticky")})},r}(t.Component),p=function(e){function r(r,n){var i=e.call(this,r)||this;return n.appendChild(i.el=t.createElement("div",{className:"fc-slats"})),i}return n(r,e),r.prototype.destroy=function(){t.removeElement(this.el),e.prototype.destroy.call(this)},r.prototype.render=function(e){this.renderDates(e.tDateProfile)},r.prototype.renderDates=function(e){for(var r=this.theme,n=this.view,i=this.dateEnv,o=e.slotDates,l=e.isWeekStarts,s='<table class="'+r.getClass("tableGrid")+'"><colgroup>',a=0;a<o.length;a++)s+="<col/>";s+="</colgroup>",s+="<tbody><tr>";for(a=0;a<o.length;a++)s+=this.slatCellHtml(o[a],l[a],e);s+="</tr></tbody></table>",this.el.innerHTML=s,this.slatColEls=t.findElements(this.el,"col"),this.slatEls=t.findElements(this.el,"td");for(a=0;a<o.length;a++)n.publiclyTrigger("dayRender",[{date:i.toDate(o[a]),el:this.slatEls[a],view:n}]);this.outerCoordCache=new t.PositionCache(this.el,this.slatEls,!0,!1),this.innerCoordCache=new t.PositionCache(this.el,t.findChildren(this.slatEls,"div"),!0,!1)},r.prototype.slatCellHtml=function(e,r,n){var i,o=this.theme,l=this.dateEnv;return n.isTimeScale?(i=[]).push(t.isInt(l.countDurationsBetween(n.normalizedRange.start,e,n.labelInterval))?"fc-major":"fc-minor"):(i=t.getDayClasses(e,this.props.dateProfile,this.context)).push("fc-day"),i.unshift(o.getClass("widgetContent")),r&&i.push("fc-em-cell"),'<td class="'+i.join(" ")+'" data-date="'+l.formatIso(e,{omitTime:!n.isTimeScale,omitTimeZoneOffset:!0})+'"><div></div></td>'},r.prototype.updateSize=function(){this.outerCoordCache.build(),this.innerCoordCache.build()},r.prototype.positionToHit=function(e){var r=this.outerCoordCache,n=this.props.tDateProfile,i=r.leftToIndex(e);if(null!=i){var o=r.getWidth(i),l=this.isRtl?(r.rights[i]-e)/o:(e-r.lefts[i])/o,s=Math.floor(l*n.snapsPerSlot),a=this.dateEnv.add(n.slotDates[i],t.multiplyDuration(n.snapDuration,s));return{dateSpan:{range:{start:a,end:this.dateEnv.add(a,n.snapDuration)},allDay:!this.props.tDateProfile.isTimeScale},dayEl:this.slatColEls[i],left:r.lefts[i],right:r.rights[i]}}return null},r}(t.Component),f=18,g=6,m=200;t.config.MAX_TIMELINE_SLOTS=1e3;var v=[{years:1},{months:1},{days:1},{hours:1},{minutes:30},{minutes:15},{minutes:10},{minutes:5},{minutes:1},{seconds:30},{seconds:15},{seconds:10},{seconds:5},{seconds:1},{milliseconds:500},{milliseconds:100},{milliseconds:10},{milliseconds:1}];function y(e,r){var n=r.dateEnv,i={labelInterval:E(r,"slotLabelInterval"),slotDuration:E(r,"slotDuration")};!function(e,r,n){var i=r.currentRange;if(e.labelInterval){var o=n.countDurationsBetween(i.start,i.end,e.labelInterval);o>t.config.MAX_TIMELINE_SLOTS&&(console.warn("slotLabelInterval results in too many cells"),e.labelInterval=null)}if(e.slotDuration){var l=n.countDurationsBetween(i.start,i.end,e.slotDuration);l>t.config.MAX_TIMELINE_SLOTS&&(console.warn("slotDuration results in too many cells"),e.slotDuration=null)}if(e.labelInterval&&e.slotDuration){var s=t.wholeDivideDurations(e.labelInterval,e.slotDuration);(null===s||s<1)&&(console.warn("slotLabelInterval must be a multiple of slotDuration"),e.slotDuration=null)}}(i,e,n),D(i,e,n),function(e,r,n){var i=r.currentRange,o=e.slotDuration;if(!o){for(var l=D(e,r,n),s=0,a=v;s<a.length;s++){var c=a[s],d=t.createDuration(c),h=t.wholeDivideDurations(l,d);if(null!==h&&h>1&&h<=g){o=d;break}}if(o){var u=n.countDurationsBetween(i.start,i.end,o);u>m&&(o=null)}o||(o=l),e.slotDuration=o}}(i,e,n);var o=r.opt("slotLabelFormat"),l=Array.isArray(o)?o:null!=o?[o]:function(e,r,n,i){var o,l,s=e.labelInterval,a=t.greatestDurationDenominator(s).unit,c=i.opt("weekNumbers"),d=o=l=null;"week"!==a||c||(a="day");switch(a){case"year":d={year:"numeric"};break;case"month":w("years",r,n)>1&&(d={year:"numeric"}),o={month:"short"};break;case"week":w("years",r,n)>1&&(d={year:"numeric"}),o={week:"narrow"};break;case"day":w("years",r,n)>1?d={year:"numeric",month:"long"}:w("months",r,n)>1&&(d={month:"long"}),c&&(o={week:"short"}),l={weekday:"narrow",day:"numeric"};break;case"hour":c&&(d={week:"short"}),w("days",r,n)>1&&(o={weekday:"short",day:"numeric",month:"numeric",omitCommas:!0}),l={hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"};break;case"minute":t.asRoughMinutes(s)/60>=g?(d={hour:"numeric",meridiem:"short"},o=function(e){return":"+t.padStart(e.date.minute,2)}):d={hour:"numeric",minute:"numeric",meridiem:"short"};break;case"second":t.asRoughSeconds(s)/60>=g?(d={hour:"numeric",minute:"2-digit",meridiem:"lowercase"},o=function(e){return":"+t.padStart(e.date.second,2)}):d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"};break;case"millisecond":d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"},o=function(e){return"."+t.padStart(e.millisecond,3)}}return[].concat(d||[],o||[],l||[])}(i,e,n,r);i.headerFormats=l.map(function(e){return t.createFormatter(e)}),i.isTimeScale=Boolean(i.slotDuration.milliseconds);var s=null;if(!i.isTimeScale){var a=t.greatestDurationDenominator(i.slotDuration).unit;/year|month|week/.test(a)&&(s=a)}i.largeUnit=s,i.emphasizeWeeks=t.isSingleDay(i.slotDuration)&&w("weeks",e,n)>=2&&!r.opt("businessHours");var c,d,h=r.opt("snapDuration");h&&(c=t.createDuration(h),d=t.wholeDivideDurations(i.slotDuration,c)),null==d&&(c=i.slotDuration,d=1),i.snapDuration=c,i.snapsPerSlot=d;var u=t.asRoughMs(e.maxTime)-t.asRoughMs(e.minTime),p=S(e.renderRange.start,i,n),f=S(e.renderRange.end,i,n);i.isTimeScale&&(p=n.add(p,e.minTime),f=n.add(t.addDays(f,-1),e.maxTime)),i.timeWindowMs=u,i.normalizedRange={start:p,end:f};for(var y=[],T=p;T<f;)b(T,i,e,r)&&y.push(T),T=n.add(T,i.slotDuration);i.slotDates=y;var R=-1,x=0,M=[],z=[];for(T=p;T<f;)b(T,i,e,r)?(R++,M.push(R),z.push(x)):M.push(R+.5),T=n.add(T,i.snapDuration),x++;return i.snapDiffToIndex=M,i.snapIndexToDiff=z,i.snapCnt=R+1,i.slotCnt=i.snapCnt/i.snapsPerSlot,i.isWeekStarts=function(e,t){for(var r=e.slotDates,n=e.emphasizeWeeks,i=null,o=[],l=0,s=r;l<s.length;l++){var a=s[l],c=t.computeWeekNumber(a),d=n&&null!==i&&i!==c;i=c,o.push(d)}return o}(i,n),i.cellRows=function(e,r,n){for(var i=e.slotDates,o=e.headerFormats,l=o.map(function(e){return[]}),s=o.map(function(e){return e.getLargestUnit?e.getLargestUnit():null}),a=0;a<i.length;a++)for(var c=i[a],d=e.isWeekStarts[a],h=0;h<o.length;h++){var u=o[h],p=l[h],f=p[p.length-1],g=o.length>1&&h<o.length-1,m=null;if(g){var v=r.format(c,u);f&&f.text===v?f.colspan+=1:m=C(c,v,s[h],n)}else if(!f||t.isInt(r.countDurationsBetween(e.normalizedRange.start,c,e.labelInterval))){var v=r.format(c,u);m=C(c,v,s[h],n)}else f.colspan+=1;m&&(m.weekStart=d,p.push(m))}return l}(i,n,r),i}function S(e,r,n){var i=e;return r.isTimeScale||(i=t.startOfDay(i),r.largeUnit&&(i=n.startOf(i,r.largeUnit))),i}function b(e,r,n,i){if(i.dateProfileGenerator.isHiddenDay(e))return!1;if(r.isTimeScale){var o=t.startOfDay(e),l=e.valueOf()-o.valueOf()-t.asRoughMs(n.minTime);return(l=(l%864e5+864e5)%864e5)<r.timeWindowMs}return!0}function E(e,r){var n=e.opt(r);if(null!=n)return t.createDuration(n)}function D(e,r,n){var i=r.currentRange,o=e.labelInterval;if(!o){var l=void 0;if(e.slotDuration){for(var s=0,a=v;s<a.length;s++){l=a[s];var c=t.createDuration(l),d=t.wholeDivideDurations(c,e.slotDuration);if(null!==d&&d<=g){o=c;break}}o||(o=e.slotDuration)}else for(var h=0,u=v;h<u.length;h++){if(l=u[h],o=t.createDuration(l),n.countDurationsBetween(i.start,i.end,o)>=f)break}e.labelInterval=o}return o}function w(e,r,n){var i=r.currentRange,o=null;return"years"===e?o=n.diffWholeYears(i.start,i.end):"months"===e?o=n.diffWholeMonths(i.start,i.end):"weeks"===e?o=n.diffWholeMonths(i.start,i.end):"days"===e&&(o=t.diffWholeDays(i.start,i.end)),o||0}function C(e,r,n,i){return{text:r,spanHtml:t.buildGotoAnchorHtml(i,{date:e,type:n,forceOff:!n},{class:"fc-cell-text"},t.htmlEscape(r)),date:e,colspan:1,isWeekStart:!1}}var T,R=function(){function e(e,t){this.headParent=e,this.bodyParent=t}return e.prototype.render=function(e,r){var n=r?{right:-e}:{left:e};this.headParent.appendChild(this.arrowEl=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-arrow",style:n})),this.bodyParent.appendChild(this.lineEl=t.createElement("div",{className:"fc-now-indicator fc-now-indicator-line",style:n}))},e.prototype.unrender=function(){this.arrowEl&&t.removeElement(this.arrowEl),this.lineEl&&t.removeElement(this.lineEl)},e}(),x=-1!==(T=t.htmlToElement('<div style="position:-webkit-sticky;position:sticky"></div>').style.position).indexOf("sticky")?T:null,M=/Edge/.test(navigator.userAgent),z="-webkit-sticky"===x,k="fc-sticky",P=function(){function e(e,r,n){var i=this;this.usingRelative=null,this.updateSize=function(){var e=Array.prototype.slice.call(i.scroller.canvas.el.querySelectorAll("."+k)),r=i.queryElGeoms(e),n=i.scroller.el.clientWidth;i.usingRelative?function(e,r,n){e.forEach(function(e,i){var o=r[i].naturalBound;t.applyStyle(e,{position:"relative",left:n[i].left-o.left,top:n[i].top-o.top})})}(e,r,i.computeElDestinations(r,n)):function(e,r,n){e.forEach(function(e,i){var o=0;"center"===r[i].intendedTextAlign&&(o=(n-r[i].elWidth)/2,"center"===r[i].computedTextAlign&&(e.setAttribute("data-sticky-center",""),e.parentNode.style.textAlign="left")),t.applyStyle(e,{position:x,left:o,right:0,top:0})})}(e,r,n)},this.scroller=e,this.usingRelative=!x||M&&r||(M||z)&&n,this.usingRelative&&e.on("scrollEnd",this.updateSize)}return e.prototype.destroy=function(){this.scroller.off("scrollEnd",this.updateSize)},e.prototype.queryElGeoms=function(e){for(var r=this.scroller.canvas.el.getBoundingClientRect(),n=[],i=0,o=e;i<o.length;i++){var l=o[i],s=t.translateRect(l.parentNode.getBoundingClientRect(),-r.left,-r.top),a=l.getBoundingClientRect(),c=window.getComputedStyle(l),d=window.getComputedStyle(l.parentNode).textAlign,h=d,u=null;"sticky"!==c.position&&(u=t.translateRect(a,-r.left-(parseFloat(c.left)||0),-r.top-(parseFloat(c.top)||0))),l.hasAttribute("data-sticky-center")&&(h="center"),n.push({parentBound:s,naturalBound:u,elWidth:a.width,elHeight:a.height,computedTextAlign:d,intendedTextAlign:h})}return n},e.prototype.computeElDestinations=function(e,t){var r=this.scroller.getScrollFromLeft(),n=this.scroller.getScrollTop(),i=r+t;return e.map(function(e){var t,o,l=e.elWidth,s=e.elHeight,a=e.parentBound,c=e.naturalBound;switch(e.intendedTextAlign){case"left":t=r;break;case"right":t=i-l;break;case"center":t=(r+i)/2-l/2}return t=Math.min(t,a.right-l),t=Math.max(t,a.left),o=n,o=Math.min(o,a.bottom-s),{left:t,top:o=Math.max(o,c.top)}})},e}();var I=function(e){function r(t,r,n){var i=e.call(this,t)||this,o=i.layout=new h(r,n,"auto"),l=o.headerScroller.enhancedScroll,s=o.bodyScroller.enhancedScroll;return i.headStickyScroller=new P(l,i.isRtl,!1),i.bodyStickyScroller=new P(s,i.isRtl,!1),i.header=new u(t,l.canvas.contentEl),i.slats=new p(t,s.canvas.bgEl),i.nowIndicator=new R(l.canvas.el,s.canvas.el),i}return n(r,e),r.prototype.destroy=function(){this.layout.destroy(),this.header.destroy(),this.slats.destroy(),this.nowIndicator.unrender(),this.headStickyScroller.destroy(),this.bodyStickyScroller.destroy(),e.prototype.destroy.call(this)},r.prototype.render=function(e){var t=this.tDateProfile=y(e.dateProfile,this.view);this.header.receiveProps({dateProfile:e.dateProfile,tDateProfile:t}),this.slats.receiveProps({dateProfile:e.dateProfile,tDateProfile:t})},r.prototype.getNowIndicatorUnit=function(e){var r=this.tDateProfile=y(e,this.view);if(r.isTimeScale)return t.greatestDurationDenominator(r.slotDuration).unit},r.prototype.renderNowIndicator=function(e){t.rangeContainsMarker(this.tDateProfile.normalizedRange,e)&&this.nowIndicator.render(this.dateToCoord(e),this.isRtl)},r.prototype.unrenderNowIndicator=function(){this.nowIndicator.unrender()},r.prototype.updateSize=function(e,t,r){this.applySlotWidth(this.computeSlotWidth()),this.layout.setHeight(t,r),this.slats.updateSize()},r.prototype.updateStickyScrollers=function(){this.headStickyScroller.updateSize(),this.bodyStickyScroller.updateSize()},r.prototype.computeSlotWidth=function(){var e=this.opt("slotWidth")||"";return""===e&&(e=this.computeDefaultSlotWidth(this.tDateProfile)),e},r.prototype.computeDefaultSlotWidth=function(e){var r=0;this.header.innerEls.forEach(function(e,t){r=Math.max(r,e.getBoundingClientRect().width)});var n=Math.ceil(r)+1,i=t.wholeDivideDurations(e.labelInterval,e.slotDuration),o=Math.ceil(n/i),l=window.getComputedStyle(this.header.slatColEls[0]).minWidth;return l&&(l=parseInt(l,10))&&(o=Math.max(o,l)),o},r.prototype.applySlotWidth=function(e){var t=this.layout,r=this.tDateProfile,n="",i="",o="";if(""!==e){n=(e=Math.round(e))*r.slotDates.length,i="",o=e;var l=t.bodyScroller.enhancedScroll.getClientWidth();l>n&&(i=l,n="",o=Math.floor(l/r.slotDates.length))}t.headerScroller.enhancedScroll.canvas.setWidth(n),t.headerScroller.enhancedScroll.canvas.setMinWidth(i),t.bodyScroller.enhancedScroll.canvas.setWidth(n),t.bodyScroller.enhancedScroll.canvas.setMinWidth(i),""!==o&&this.header.slatColEls.slice(0,-1).concat(this.slats.slatColEls.slice(0,-1)).forEach(function(e){e.style.width=o+"px"})},r.prototype.computeDateSnapCoverage=function(e){var r=this.dateEnv,n=this.tDateProfile,i=r.countDurationsBetween(n.normalizedRange.start,e,n.snapDuration);if(i<0)return 0;if(i>=n.snapDiffToIndex.length)return n.snapCnt;var o=Math.floor(i),l=n.snapDiffToIndex[o];return t.isInt(l)?l+=i-o:l=Math.ceil(l),l},r.prototype.dateToCoord=function(e){var t=this.tDateProfile,r=this.computeDateSnapCoverage(e)/t.snapsPerSlot,n=Math.floor(r),i=r-(n=Math.min(n,t.slotCnt-1)),o=this.slats,l=o.innerCoordCache,s=o.outerCoordCache;return this.isRtl?s.rights[n]-l.getWidth(n)*i-s.originClientRect.width:s.lefts[n]+l.getWidth(n)*i},r.prototype.rangeToCoords=function(e){return this.isRtl?{right:this.dateToCoord(e.start),left:this.dateToCoord(e.end)}:{left:this.dateToCoord(e.start),right:this.dateToCoord(e.end)}},r.prototype.computeDateScroll=function(e){var r=this.dateEnv,n=this.props.dateProfile,i=0;return n&&(i=this.dateToCoord(r.add(t.startOfDay(n.activeRange.start),e)),!this.isRtl&&i&&(i+=1)),{left:i}},r.prototype.queryDateScroll=function(){return{left:this.layout.bodyScroller.enhancedScroll.getScrollLeft()}},r.prototype.applyDateScroll=function(e){this.layout.bodyScroller.enhancedScroll.setScrollLeft(e.left||0),this.layout.headerScroller.enhancedScroll.setScrollLeft(e.left||0)},r}(t.Component),H=function(e){function r(t,r,n){var i=e.call(this,t)||this;return i.masterContainerEl=r,i.timeAxis=n,i}return n(r,e),r.prototype.renderSegHtml=function(e,r){var n=this.context.view,i=e.eventRange,o=i.def,l=i.ui,s=n.computeEventDraggable(o,l),a=e.isStart&&n.computeEventStartResizable(o,l),c=e.isEnd&&n.computeEventEndResizable(o,l),d=this.getSegClasses(e,s,a||c,r);d.unshift("fc-timeline-event","fc-h-event");var h=this.getTimeText(i);return'<a class="'+d.join(" ")+'" style="'+t.cssToStr(this.getSkinCss(l))+'"'+(o.url?' href="'+t.htmlEscape(o.url)+'"':"")+">"+(h?'<span class="fc-time-wrap"><span class="fc-time">'+t.htmlEscape(h)+"</span></span>":"")+'<span class="fc-title-wrap"><span class="fc-title fc-sticky">'+(o.title?t.htmlEscape(o.title):"&nbsp;")+"</span></span>"+(a?'<div class="fc-resizer fc-start-resizer"></div>':"")+(c?'<div class="fc-resizer fc-end-resizer"></div>':"")+"</a>"},r.prototype.computeDisplayEventTime=function(){return!this.timeAxis.tDateProfile.isTimeScale},r.prototype.computeDisplayEventEnd=function(){return!1},r.prototype.computeEventTimeFormat=function(){return{hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"}},r.prototype.attachSegs=function(e,r){if(!this.el&&this.masterContainerEl&&(this.el=t.createElement("div",{className:"fc-event-container"}),r&&this.el.classList.add("fc-mirror-container"),this.masterContainerEl.appendChild(this.el)),this.el)for(var n=0,i=e;n<i.length;n++){var o=i[n];this.el.appendChild(o.el)}},r.prototype.detachSegs=function(e){for(var r=0,n=e;r<n.length;r++){var i=n[r];t.removeElement(i.el)}},r.prototype.computeSegSizes=function(e){for(var r=this.timeAxis,n=0,i=e;n<i.length;n++){var o=i[n],l=r.rangeToCoords(o);t.applyStyle(o.el,{left:o.left=l.left,right:-(o.right=l.right)})}},r.prototype.assignSegSizes=function(e){if(this.el){for(var r=0,n=e;r<n.length;r++){(s=n[r]).height=t.computeHeightAndMargins(s.el)}this.buildSegLevels(e);var i=L(e);t.applyStyleProp(this.el,"height",i);for(var o=0,l=e;o<l.length;o++){var s=l[o];t.applyStyleProp(s.el,"top",s.top)}}},r.prototype.buildSegLevels=function(e){for(var t=[],r=0,n=e=this.sortEventSegs(e);r<n.length;r++){var i=n[r];i.above=[];for(var o=0;o<t.length;){for(var l=!1,s=0,a=t[o];s<a.length;s++){var c=a[s];A(i,c)&&(i.above.push(c),l=!0)}if(!l)break;o+=1}for((t[o]||(t[o]=[])).push(i),o+=1;o<t.length;){for(var d=0,h=t[o];d<h.length;d++){var u=h[d];A(i,u)&&u.above.push(i)}o+=1}}return t},r}(t.FgEventRenderer);function L(e){for(var t=0,r=0,n=e;r<n.length;r++){var i=n[r];t=Math.max(t,W(i))}return t}function W(e){return null==e.top&&(e.top=L(e.above)),e.top+e.height}function A(e,t){return e.left<t.right&&e.right>t.left}var B=function(e){function r(t,r,n){var i=e.call(this,t)||this;return i.masterContainerEl=r,i.timeAxis=n,i}return n(r,e),r.prototype.attachSegs=function(e,r){if(r.length){var n=void 0;n="businessHours"===e?"bgevent":e.toLowerCase();var i=t.createElement("div",{className:"fc-"+n+"-container"});this.masterContainerEl.appendChild(i);for(var o=0,l=r;o<l.length;o++){var s=l[o];i.appendChild(s.el)}return[i]}},r.prototype.computeSegSizes=function(e){for(var t=this.timeAxis,r=0,n=e;r<n.length;r++){var i=n[r],o=t.rangeToCoords(i);i.left=o.left,i.right=o.right}},r.prototype.assignSegSizes=function(e){for(var r=0,n=e;r<n.length;r++){var i=n[r];t.applyStyle(i.el,{left:i.left,right:-i.right})}},r}(t.FillRenderer),O=function(e){function r(r,n,i,o){var l=e.call(this,r,i)||this;l.slicer=new N,l.renderEventDrag=t.memoizeRendering(l._renderEventDrag,l._unrenderEventDrag),l.renderEventResize=t.memoizeRendering(l._renderEventResize,l._unrenderEventResize);var s=l.fillRenderer=new B(r,i,o),a=l.eventRenderer=new H(r,n,o);return l.mirrorRenderer=new H(r,n,o),l.renderBusinessHours=t.memoizeRendering(s.renderSegs.bind(s,"businessHours"),s.unrender.bind(s,"businessHours")),l.renderDateSelection=t.memoizeRendering(s.renderSegs.bind(s,"highlight"),s.unrender.bind(s,"highlight")),l.renderBgEvents=t.memoizeRendering(s.renderSegs.bind(s,"bgEvent"),s.unrender.bind(s,"bgEvent")),l.renderFgEvents=t.memoizeRendering(a.renderSegs.bind(a),a.unrender.bind(a)),l.renderEventSelection=t.memoizeRendering(a.selectByInstanceId.bind(a),a.unselectByInstanceId.bind(a),[l.renderFgEvents]),l.timeAxis=o,l}return n(r,e),r.prototype.render=function(e){var t=this.slicer.sliceProps(e,e.dateProfile,this.timeAxis.tDateProfile.isTimeScale?null:e.nextDayThreshold,this,this.timeAxis);this.renderBusinessHours(t.businessHourSegs),this.renderDateSelection(t.dateSelectionSegs),this.renderBgEvents(t.bgEventSegs),this.renderFgEvents(t.fgEventSegs),this.renderEventSelection(t.eventSelection),this.renderEventDrag(t.eventDrag),this.renderEventResize(t.eventResize)},r.prototype.destroy=function(){e.prototype.destroy.call(this),this.renderBusinessHours.unrender(),this.renderDateSelection.unrender(),this.renderBgEvents.unrender(),this.renderFgEvents.unrender(),this.renderEventSelection.unrender(),this.renderEventDrag.unrender(),this.renderEventResize.unrender()},r.prototype._renderEventDrag=function(e){e&&(this.eventRenderer.hideByHash(e.affectedInstances),this.mirrorRenderer.renderSegs(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}))},r.prototype._unrenderEventDrag=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.mirrorRenderer.unrender(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}))},r.prototype._renderEventResize=function(e){if(e){var t=e.segs.map(function(e){return o({},e)});this.eventRenderer.hideByHash(e.affectedInstances),this.fillRenderer.renderSegs("highlight",t),this.mirrorRenderer.renderSegs(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg})}},r.prototype._unrenderEventResize=function(e){e&&(this.eventRenderer.showByHash(e.affectedInstances),this.fillRenderer.unrender("highlight"),this.mirrorRenderer.unrender(e.segs,{isDragging:!0,sourceSeg:e.sourceSeg}))},r.prototype.updateSize=function(e){var t=this.fillRenderer,r=this.eventRenderer,n=this.mirrorRenderer;t.computeSizes(e),r.computeSizes(e),n.computeSizes(e),t.assignSizes(e),r.assignSizes(e),n.assignSizes(e)},r}(t.DateComponent),N=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return n(r,e),r.prototype.sliceRange=function(e,r){var n=r.tDateProfile,i=r.props.dateProfile,o=function(e,r,n){if(!r.isTimeScale&&(e=t.computeVisibleDayRange(e),r.largeUnit)){var i=e;((e={start:n.startOf(e.start,r.largeUnit),end:n.startOf(e.end,r.largeUnit)}).end.valueOf()!==i.end.valueOf()||e.end<=e.start)&&(e={start:e.start,end:n.add(e.end,r.slotDuration)})}return e}(e,n,r.dateEnv),l=[];if(r.computeDateSnapCoverage(o.start)<r.computeDateSnapCoverage(o.end)){var s=t.intersectRanges(o,n.normalizedRange);s&&l.push({start:s.start,end:s.end,isStart:s.start.valueOf()===o.start.valueOf()&&b(s.start,n,i,r.view),isEnd:s.end.valueOf()===o.end.valueOf()&&b(t.addMs(s.end,-1),n,i,r.view)})}return l},r}(t.Slicer),_=function(e){function t(t,r,n,i){var o=e.call(this,t,r,n,i)||this;return o.el.classList.add("fc-timeline"),!1===o.opt("eventOverlap")&&o.el.classList.add("fc-no-overlap"),o.el.innerHTML=o.renderSkeletonHtml(),o.timeAxis=new I(o.context,o.el.querySelector("thead .fc-time-area"),o.el.querySelector("tbody .fc-time-area")),o.lane=new O(o.context,o.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl,o.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl,o.timeAxis),t.calendar.registerInteractiveComponent(o,{el:o.timeAxis.slats.el}),o}return n(t,e),t.prototype.destroy=function(){this.timeAxis.destroy(),this.lane.destroy(),e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},t.prototype.renderSkeletonHtml=function(){var e=this.theme;return'<table class="'+e.getClass("tableGrid")+'"> <thead class="fc-head"> <tr> <td class="fc-time-area '+e.getClass("widgetHeader")+'"></td> </tr> </thead> <tbody class="fc-body"> <tr> <td class="fc-time-area '+e.getClass("widgetContent")+'"></td> </tr> </tbody> </table>'},t.prototype.render=function(t){e.prototype.render.call(this,t),this.timeAxis.receiveProps({dateProfile:t.dateProfile}),this.lane.receiveProps(o({},t,{nextDayThreshold:this.nextDayThreshold}))},t.prototype.updateSize=function(e,t,r){this.timeAxis.updateSize(e,t,r),this.lane.updateSize(e)},t.prototype.getNowIndicatorUnit=function(e){return this.timeAxis.getNowIndicatorUnit(e)},t.prototype.renderNowIndicator=function(e){this.timeAxis.renderNowIndicator(e)},t.prototype.unrenderNowIndicator=function(){this.timeAxis.unrenderNowIndicator()},t.prototype.computeDateScroll=function(e){return this.timeAxis.computeDateScroll(e)},t.prototype.applyScroll=function(t,r){e.prototype.applyScroll.call(this,t,r);var n=this.calendar;(r||n.isViewUpdated||n.isDatesUpdated||n.isEventsUpdated)&&this.timeAxis.updateStickyScrollers()},t.prototype.applyDateScroll=function(e){this.timeAxis.applyDateScroll(e)},t.prototype.queryScroll=function(){var e=this.timeAxis.layout.bodyScroller.enhancedScroll;return{top:e.getScrollTop(),left:e.getScrollLeft()}},t.prototype.buildPositionCaches=function(){this.timeAxis.slats.updateSize()},t.prototype.queryHit=function(e,t,r,n){var i=this.timeAxis.slats.positionToHit(e);if(i)return{component:this,dateSpan:i.dateSpan,rect:{left:i.left,right:i.right,top:0,bottom:n},dayEl:i.dayEl,layer:0}},t}(t.View),F=t.createPlugin({defaultView:"timelineDay",views:{timeline:{class:_,eventResizableFromStart:!0},timelineDay:{type:"timeline",duration:{days:1}},timelineWeek:{type:"timeline",duration:{weeks:1}},timelineMonth:{type:"timeline",duration:{months:1}},timelineYear:{type:"timeline",duration:{years:1}}}});e.HeaderBodyLayout=h,e.ScrollJoiner=d,e.StickyScroller=P,e.TimeAxis=I,e.TimelineLane=O,e.TimelineView=_,e.default=F,Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
{
"name": "@fullcalendar/timeline",
"version": "4.3.0",
"title": "FullCalendar Timeline Plugin",
"description": "Display events on a horizontal time axis (without resources)",
"keywords": [
"calendar",
"event",
"full-sized"
],
"homepage": "https://fullcalendar.io/scheduler",
"docs": "https://fullcalendar.io/docs/timeline-view-no-resources",
"bugs": "https://fullcalendar.io/reporting-bugs",
"repository": {
"type": "git",
"url": "https://github.com/fullcalendar/fullcalendar-scheduler.git",
"homepage": "https://github.com/fullcalendar/fullcalendar-scheduler"
},
"license": "SEE LICENSE IN LICENSE.md",
"author": {
"name": "Adam Shaw",
"email": "arshaw@arshaw.com",
"url": "http://arshaw.com/"
},
"copyright": "2019 Adam Shaw",
"peerDependencies": {
"@fullcalendar/core": "~4.3.0"
},
"main": "main.js",
"module": "main.esm.js",
"unpkg": "main.min.js",
"types": "main.d.ts"
}
......@@ -12,7 +12,7 @@
'resourceId': '{{ slot.room.title }}',
'backgroundColor': '{{ slot|highlight_change_colors }}',
'borderColor': '{{ slot.ak.category.color }}',
'url': '{% url 'submit:ak_detail' event_slug=event.slug pk=slot.ak.pk %}'
'url': '{{ slot.ak.detail_url }}'
},
{% endif %}
{% endfor %}
......
{% load static %}
{% load tz %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% load tags_AKPlan %}
<link href='{% static 'AKPlan/vendor/fullcalendar/core/main.min.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/daygrid/main.min.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/timegrid/main.min.css' %}' rel='stylesheet'/>
<script src='{% static 'AKPlan/vendor/fullcalendar/core/main.min.js' %}'></script>
{% with 'AKPlan/vendor/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %}
<script src="{% static locale_file %}"></script>
{% endwith %}
<script src='{% static 'AKPlan/vendor/fullcalendar/daygrid/main.min.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/timegrid/main.min.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/bootstrap/main.min.js' %}'></script>
{% include "AKModel/load_fullcalendar.html" %}
<script>
{% get_current_language as LANGUAGE_CODE %}
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('akSlotCalendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: ['timeGrid', 'bootstrap'],
// Adapt to timezone of the connected event
timeZone: '{{ ak.event.timezone }}',
defaultView: 'timeGrid',
initialView: 'timeGrid',
// Adapt to user selected locale
locale: '{{ LANGUAGE_CODE }}',
// No header, not buttons
header: {
left: '',
center: '',
right: ''
},
headerToolbar: false,
aspectRatio: 2.5,
themeSystem: 'bootstrap',
themeSystem: 'bootstrap5',
buttonIcons: {
prev: 'ignore fa-solid fa-angle-left',
next: 'ignore fa-solid fa-angle-right',
},
// Only show calendar view for the dates of the connected event
visibleRange: {
start: '{{ ak.event.start | timezone:ak.event.timezone | date:"Y-m-d H:i:s" }}',
end: '{{ ak.event.end | timezone:ak.event.timezone | date:"Y-m-d H:i:s"}}',
},
scrollTime: '08:00:00',
allDaySlot: false,
nowIndicator: true,
now: "{% timestamp_now event.timezone %}",
eventTextColor: '#fff',
eventColor: '#127ba3',
// Create entries for all scheduled slots
......@@ -64,10 +56,11 @@
start: '{{ a.start | timezone:ak.event.timezone | date:"Y-m-d H:i:s" }}',
end: '{{ a.end | timezone:ak.event.timezone | date:"Y-m-d H:i:s" }}',
backgroundColor: '#28B62C',
rendering: 'background'
display: 'background'
},
{% endfor %}
]
],
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
});
calendar.render();
......
{% extends "base.html" %}
{% load fontawesome_5 %}
{% load fontawesome_6 %}
{% load i18n %}
{% load static %}
......@@ -10,15 +10,7 @@
{% endblock %}
{% block imports %}
{% get_current_language as LANGUAGE_CODE %}
<link href='{% static 'AKPlan/vendor/fullcalendar/core/main.css' %}' rel='stylesheet'/>
<script src='{% static 'AKPlan/vendor/fullcalendar/core/main.js' %}'></script>
{% with 'AKPlan/vendor/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %}
<script src="{% static locale_file %}"></script>
{% endwith %}
<script src='{% static 'AKPlan/vendor/fullcalendar/bootstrap/main.js' %}'></script>
{% include "AKModel/load_fullcalendar.html" %}
{% block fullcalendar %}{% endblock %}
{% endblock imports %}
......@@ -26,7 +18,7 @@
{% block footer_custom %}
{% if event.contact_email %}
<h4>
<a href="mailto:{{ event.contact_email }}">{% fa5_icon "envelope" "far" %} {% trans "Write to organizers of this event for questions and comments" %}</a>
<a href="mailto:{{ event.contact_email }}">{% fa6_icon "envelope" "far" %} {% trans "Write to organizers of this event for questions and comments" %}</a>
</h4>
{% endif %}
{% endblock %}
{% extends "AKPlan/plan_base.html" %}
{% load fontawesome_5 %}
{% load fontawesome_6 %}
{% load i18n %}
{% load static %}
{% load tz %}
{% load tags_AKPlan %}
{% block fullcalendar %}
{% if not event.plan_hidden or user.is_staff %}
{% get_current_language as LANGUAGE_CODE %}
<link href='{% static 'AKPlan/vendor/fullcalendar/daygrid/main.min.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/timegrid/main.min.css' %}' rel='stylesheet'/>
<script src='{% static 'AKPlan/vendor/fullcalendar/daygrid/main.min.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/timegrid/main.min.js' %}'></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('planCalendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: ['timeGrid', 'bootstrap'],
// Adapt to timezone of the connected event
timeZone: '{{ event.timezone }}',
defaultView: 'timeGrid',
initialView: 'timeGrid',
// Adapt to user selected locale
locale: '{{ LANGUAGE_CODE }}',
// No header, not buttons
header: {
headerToolbar: {
left: '',
center: '',
right: ''
},
aspectRatio: 2,
themeSystem: 'bootstrap',
themeSystem: 'bootstrap5',
buttonIcons: {
prev: 'ignore fa-solid fa-angle-left',
next: 'ignore fa-solid fa-angle-right',
},
// Only show calendar view for the dates of the connected event
visibleRange: {
start: '{{ event.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
end: '{{ event.end | timezone:event.timezone | date:"Y-m-d H:i:s"}}',
},
scrollTime: '08:00:00',
allDaySlot: false,
nowIndicator: true,
now: "{% timestamp_now event.timezone %}",
eventTextColor: '#fff',
eventColor: '#127ba3',
// Create entries for all scheduled slots
events: {% block encode %}{% endblock %}
events: {% block encode %}{% endblock %},
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
});
calendar.render();
......
{% extends "AKPlan/plan_base.html" %}
{% load fontawesome_5 %}
{% load fontawesome_6 %}
{% load i18n %}
{% load static %}
{% load tz %}
{% load tags_AKPlan %}
{% block fullcalendar %}
{% if not event.plan_hidden or user.is_staff %}
{% get_current_language as LANGUAGE_CODE %}
<link href='{% static 'AKPlan/vendor/fullcalendar/timeline/main.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/resource-timeline/main.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/resource-timeline/main.min.css' %}' rel='stylesheet'/>
<script src='{% static 'AKPlan/vendor/fullcalendar/timeline/main.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/resource-common/main.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/resource-timeline/main.js' %}'></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var planEl = document.getElementById('planCalendar');
var plan = new FullCalendar.Calendar(planEl, {
plugins: ['resourceTimeline', 'bootstrap'],
timeZone: '{{ event.timezone }}',
header: {
headerToolbar: {
left: 'today prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineEvent'
},
aspectRatio: 2,
themeSystem: 'bootstrap',
themeSystem: 'bootstrap5',
buttonIcons: {
prev: 'ignore fa-solid fa-angle-left',
next: 'ignore fa-solid fa-angle-right',
},
// Adapt to user selected locale
locale: '{{ LANGUAGE_CODE }}',
defaultView: 'resourceTimelineEvent',
locale: '{{ LANGUAGE_CODE }}',
initialView: 'resourceTimelineEvent',
views: {
resourceTimelineDay: {
type: 'resourceTimeline',
......@@ -50,16 +46,17 @@
buttonText: '{% trans "Event" %}',
}
},
eventRender: function(info) {
eventDidMount: function(info) {
$(info.el).tooltip({title: info.event.extendedProps.description});
},
editable: false,
allDaySlot: false,
nowIndicator: true,
now: "{% timestamp_now event.timezone %}",
eventTextColor: '#fff',
eventColor: '#127ba3',
resourceAreaWidth: '15%',
resourceLabelText: '{% trans "Room" %}',
resourceAreaHeaderContent: '{% trans "Room" %}',
resources: {% include "AKPlan/encode_rooms.html" %},
events: {% with akslots as slots %}{% include "AKPlan/encode_events.html" %}{% endwith %},
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
......@@ -68,7 +65,9 @@
plan.render();
// Scroll to current time
$('.fc-scroller').scrollLeft($('.fc-now-indicator').position().left);
if($(".fc-timeline-now-indicator-line").length) {
$('.fc-scroller').scrollLeft($('.fc-timeline-now-indicator-line').position().left);
}
});
</script>
{% endif %}
......@@ -84,11 +83,11 @@
{% block content %}
<div class="float-right">
<div class="float-end">
<ul class="nav nav-pills">
{% if event.room_set.count > 0 %}
{% if rooms|length > 0 %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button"
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button"
aria-haspopup="true"
aria-expanded="false">{% trans "Rooms" %}</a>
<div class="dropdown-menu" style="">
......@@ -99,13 +98,13 @@
</div>
</li>
{% endif %}
{% if event.aktrack_set.count > 0 %}
{% if tracks|length > 0 %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button"
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button"
aria-haspopup="true"
aria-expanded="false">{% trans "Tracks" %}</a>
<div class="dropdown-menu">
{% for t in event.aktrack_set.all %}
{% for t in tracks %}
<a class="dropdown-item"
href="{% url "plan:plan_track" event_slug=event.slug pk=t.pk %}">{{ t }}</a>
{% endfor %}
......@@ -115,7 +114,7 @@
{% if event.active %}
<li class="nav-item">
<a class="nav-link active"
href="{% url 'plan:plan_wall' event_slug=event.slug %}">{% fa5_icon 'desktop' 'fas' %}&nbsp;&nbsp;{% trans "AK Wall" %}</a>
href="{% url 'plan:plan_wall' event_slug=event.slug %}">{% fa6_icon 'desktop' 'fas' %}&nbsp;&nbsp;{% trans "AK Wall" %}</a>
</li>
{% endif %}
</ul>
......@@ -149,7 +148,9 @@
{% endif %}
<div class="col-md-12">
<div id="planCalendar" style="margin-top:30px;"></div>
<div style="margin-top:30px;margin-bottom: 70px;">
<div id="planCalendar"></div>
</div>
</div>
{% else %}
<div class="col-md-12">
......
{% extends "AKPlan/plan_detail.html" %}
{% load fontawesome_5 %}
{% load fontawesome_6 %}
{% load tags_AKModel %}
{% load tz %}
......@@ -16,26 +16,37 @@
{% block encode %}
[
{% for slot in room.akslot_set.all %}
{% for slot in slots %}
{% if slot.start %}
{'title': '{{ slot.ak }}',
'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
'url': '{% url 'submit:ak_detail' event_slug=event.slug pk=slot.ak.pk %}',
'url': '{{ slot.ak.detail_url }}',
'borderColor': '{{ slot.ak.track.color }}',
'color': '{{ slot.ak.category.color }}',
},
{% endif %}
{% endfor %}
{% for a in room.availabilities.all %}
{
title: '',
start: '{{ a.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
end: '{{ a.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
'resourceId': '{{ a.room.title }}',
backgroundColor: '#28B62C',
display: 'background',
groupId: 'roomAvailable',
},
{% endfor %}
]
{% endblock %}
{% block content %}
<div class="float-right">
<div class="float-end">
<ul class="nav nav-pills">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Rooms" %}</a>
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Rooms" %}</a>
<div class="dropdown-menu" style="">
{% for r in event.room_set.all %}
<a class="dropdown-item" href="{% url "plan:plan_room" event_slug=event.slug pk=r.pk %}">{{ r }}</a>
......@@ -47,9 +58,9 @@
<h1>{% trans "Room" %}: {{ room.name }} {% if room.location != '' %}({{ room.location }}){% endif %}</h1>
{% if "AKOnline"|check_app_installed and room.virtualroom and room.virtualroom.url != '' %}
<a class="btn btn-success" href="{{ room.virtualroom.url }}">
{% fa5_icon 'external-link-alt' 'fas' %} {% trans "Go to virtual room" %}
{% if "AKOnline"|check_app_installed and room.virtual and room.virtual.url != '' %}
<a class="btn btn-success" target="_parent" href="{{ room.virtual.url }}">
{% fa6_icon 'external-link-alt' 'fas' %} {% trans "Go to virtual room" %}
</a>
{% endif %}
......
......@@ -19,7 +19,7 @@
{'title': '{{ slot.ak }} @ {{ slot.room }}',
'start': '{{ slot.start | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
'end': '{{ slot.end | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
'url': '{% url 'submit:ak_detail' event_slug=event.slug pk=slot.ak.pk %}',
'url': '{{ slot.ak.detail_url }}',
'color': '{{ track.color }}',
'borderColor': '{{ slot.ak.category.color }}',
},
......@@ -30,10 +30,10 @@
{% block content %}
<div class="float-right">
<div class="float-end">
<ul class="nav nav-pills">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Tracks" %}</a>
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Tracks" %}</a>
<div class="dropdown-menu">
{% for t in event.aktrack_set.all %}
<a class="dropdown-item" href="{% url "plan:plan_track" event_slug=event.slug pk=t.pk %}">{{ t }}</a>
......
{% load compress %}
{% load static %}
{% load i18n %}
{% load bootstrap4 %}
{% load fontawesome_5 %}
{% load django_bootstrap5 %}
{% load fontawesome_6 %}
{% load tags_AKModel %}
{% load tags_AKPlan %}
{% load tz %}
......@@ -13,57 +15,56 @@
<title>{% block title %}AK Planning{% endblock %}</title>
{# Load Bootstrap CSS and JavaScript as well as font awesome #}
{% bootstrap_css %}
{% bootstrap_javascript jquery='slim' %}
{% fontawesome_5_static %}
{% compress css %}
<link rel="stylesheet" type="text/x-scss" href="{% static 'common/vendor/bootswatch-lumen/theme.scss' %}">
{% fontawesome_6_css %}
<link rel="stylesheet" href="{% static 'common/css/custom.css' %}">
{% endcompress %}
<link rel="stylesheet" href="{% static 'common/css/custom.css' %}">
{% compress js %}
{% bootstrap_javascript %}
<script src="{% static 'common/vendor/jquery/jquery-3.6.3.min.js' %}"></script>
{% fontawesome_6_js %}
{% endcompress %}
{% get_current_language as LANGUAGE_CODE %}
<link href='{% static 'AKPlan/vendor/fullcalendar/core/main.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/timeline/main.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/resource-timeline/main.css' %}' rel='stylesheet'/>
<link href='{% static 'AKPlan/vendor/fullcalendar/resource-timeline/main.min.css' %}' rel='stylesheet'/>
{% include "AKModel/load_fullcalendar.html" %}
<script src='{% static 'AKPlan/vendor/fullcalendar/core/main.js' %}'></script>
{% with 'AKPlan/vendor/fullcalendar/core/locales/'|add:LANGUAGE_CODE|add:'.js' as locale_file %}
<script src="{% static locale_file %}"></script>
{% endwith %}
<script src='{% static 'AKPlan/vendor/fullcalendar/timeline/main.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/resource-common/main.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/resource-timeline/main.js' %}'></script>
<script src='{% static 'AKPlan/vendor/fullcalendar/bootstrap/main.js' %}'></script>
{% get_current_language as LANGUAGE_CODE %}
<script>
document.addEventListener('DOMContentLoaded', function () {
var planEl = document.getElementById('planCalendar');
var plan = new FullCalendar.Calendar(planEl, {
plugins: ['resourceTimeline', 'bootstrap'],
timeZone: '{{ event.timezone }}',
header: false,
themeSystem: 'bootstrap',
headerToolbar: false,
themeSystem: 'bootstrap5',
buttonIcons: {
prev: 'ignore fa-solid fa-angle-left',
next: 'ignore fa-solid fa-angle-right',
},
// Adapt to user selected locale
locale: '{{ LANGUAGE_CODE }}',
type: 'resourceTimeline',
slotDuration: '01:00',
defaultView: 'resourceTimeline',
initialView: 'resourceTimeline',
visibleRange: {
start: '{{ start | timezone:event.timezone | date:"Y-m-d H:i:s" }}',
end: '{{ end | timezone:event.timezone | date:"Y-m-d H:i:s"}}',
},
eventRender: function(info) {
slotMinTime: '{{ earliest_start_hour }}:00:00',
slotMaxTime: '{{ latest_end_hour }}:00:00',
eventDidMount: function(info) {
$(info.el).tooltip({title: info.event.extendedProps.description});
},
editable: false,
allDaySlot: false,
nowIndicator: true,
now: "{% timestamp_now event.timezone %}",
eventTextColor: '#fff',
eventColor: '#127ba3',
height: 'parent',
height: '90%',
resourceAreaWidth: '15%',
resourceLabelText: '{% trans "Room" %}',
resourceAreaHeaderContent: '{% trans "Room" %}',
resources: [
{% for room in rooms %}
{
......@@ -79,10 +80,48 @@
plan.render();
// Scroll to current time
$('.fc-scroller').scrollLeft($('.fc-now-indicator').position().left);
if($(".fc-timeline-now-indicator-line").length) {
$('.fc-scroller').scrollLeft($('.fc-timeline-now-indicator-line').position().left);
}
// == Auto Reload ==
// function from: https://stackoverflow.com/questions/5448545/how-to-retrieve-get-parameters-from-javascript/
function findGetParameter(parameterName) {
var result = null,
tmp = [];
location.search
.substr(1)
.split("&")
.forEach(function (item) {
tmp = item.split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
});
return result;
}
// Check whether an autoreload frequency was specified and treat it as full minutes
const autoreload_frequency = Math.ceil(findGetParameter("autoreload"));
const cbxAutoReload = $('#cbxAutoReload');
if(autoreload_frequency>0) {
window.setTimeout ( function() { window.location.reload(); }, autoreload_frequency * 60 * 1000);
console.log("Autoreload active");
cbxAutoReload.prop('checked', true);
}
else {
cbxAutoReload.prop('checked', false);
}
cbxAutoReload.change(function () {
let url = window.location.href.split('?')[0];
if(cbxAutoReload.prop('checked')) {
url = url + "?autoreload=5";
}
window.location.replace(url);
});
});
</script>
</head>
<body>
{% timezone event.timezone %}
......@@ -104,6 +143,9 @@
<div id="planCalendar"></div>
</div>
</div>
<div style="position: absolute;bottom: 1vh;left:1vw;background-color: #FFFFFF;padding: 1vh;">
<input type="checkbox" name="autoreload" id="cbxAutoReload"> <label for="cbxAutoReload">{% trans "Reload page automatically?" %}</label>
</div>
{% endtimezone %}
</body>
......