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 0 additions and 6199 deletions
/* Divider between resources and time area
--------------------------------------------------------------------------------------------------*/
.fc-timeline .fc-divider {
width: 3px;
border-style: double;
/* overcome neighboring borders */
}
.fc-timeline .fc-head > tr > .fc-divider {
border-bottom: 0;
}
.fc-timeline .fc-body > tr > .fc-divider {
border-top: 0;
}
/* Resource Area
--------------------------------------------------------------------------------------------------*/
.fc-resource-area {
width: 30%;
}
.fc-resource-area col {
width: 40%;
min-width: 70px;
/* will be read by JS */
}
.fc-resource-area col.fc-main-col {
width: 60%;
/* make the first column in a nested setup bigger */
}
.fc-flat .fc-expander-space {
/* fc-flat is opposite of fc-nested */
display: none;
}
.fc-ltr .fc-resource-area tr > * {
text-align: left;
}
.fc-rtl .fc-resource-area tr > * {
text-align: right;
}
.fc-resource-area .fc-cell-content {
padding-left: 4px;
padding-right: 4px;
}
/* head */
.fc-resource-area .fc-super th {
text-align: center;
}
.fc-resource-area th > div {
position: relative;
}
.fc-resource-area th .fc-cell-content {
position: relative;
z-index: 1;
}
.fc-resource-area th .fc-col-resizer {
position: absolute;
z-index: 2;
top: 0;
bottom: 0;
width: 5px;
}
.fc-timeline .fc-col-resizer {
cursor: col-resize;
}
.fc-ltr .fc-resource-area th .fc-col-resizer {
right: -3px;
}
.fc-rtl .fc-resource-area th .fc-col-resizer {
left: -3px;
}
/* body */
.fc-body .fc-resource-area .fc-cell-content {
/* might BE the cell */
padding-top: 8px;
padding-bottom: 8px;
}
.fc-no-overlap .fc-body .fc-resource-area .fc-cell-content {
/* might BE the cell */
padding-top: 6px;
padding-bottom: 6px;
}
.fc-resource-area .fc-icon {
/* the expander and spacers before the expander */
display: inline-block;
width: 1em;
/* ensure constant width, esp for empty icons */
text-align: center;
}
.fc-resource-area .fc-expander {
cursor: pointer;
opacity: 0.65;
}
/* body resource rows */
.fc-time-area .fc-rows {
position: relative;
z-index: 3;
}
.fc-time-area .fc-rows td > div {
position: relative;
}
.fc-time-area .fc-rows .fc-bgevent-container,
.fc-time-area .fc-rows .fc-highlight-container {
z-index: 1;
}
// Generated by dts-bundle v0.7.3-fork.1
// Dependencies for this module:
// ../../../../../@fullcalendar/core
// ../../../../../@fullcalendar/timeline
// ../../../../../@fullcalendar/resource-common
declare module '@fullcalendar/resource-timeline' {
import ResourceTimelineView from '@fullcalendar/resource-timeline/ResourceTimelineView';
export { ResourceTimelineView };
const _default: import("@fullcalendar/core").PluginDef;
export default _default;
}
declare module '@fullcalendar/resource-timeline/ResourceTimelineView' {
import {
ComponentContext,
DateProfile,
DateProfileGenerator,
Duration,
ElementDragging,
Hit,
PositionCache,
SplittableProps,
View,
ViewSpec
} from '@fullcalendar/core';
import {ScrollJoiner, StickyScroller, TimeAxis, TimelineLane} from '@fullcalendar/timeline';
import {GroupNode, ResourceNode, ResourceViewProps} from '@fullcalendar/resource-common';
import GroupRow from '@fullcalendar/resource-timeline/GroupRow';
import ResourceRow from '@fullcalendar/resource-timeline/ResourceRow';
import Spreadsheet from '@fullcalendar/resource-timeline/Spreadsheet';
export {ResourceTimelineView as default, ResourceTimelineView};
class ResourceTimelineView extends View {
static needsResourceData: boolean;
props: ResourceViewProps;
spreadsheet: Spreadsheet;
timeAxis: TimeAxis;
lane: TimelineLane;
bodyScrollJoiner: ScrollJoiner;
spreadsheetBodyStickyScroller: StickyScroller;
isStickyScrollDirty: boolean;
timeAxisTbody: HTMLElement;
miscHeight: number;
rowNodes: (GroupNode | ResourceNode)[];
rowComponents: (GroupRow | ResourceRow)[];
rowComponentsById: {
[id: string]: (GroupRow | ResourceRow);
};
resourceAreaHeadEl: HTMLElement;
resourceAreaWidth?: number;
resourceAreaWidthDraggings: ElementDragging[];
superHeaderText: any;
isVGrouping: any;
isHGrouping: any;
groupSpecs: any;
colSpecs: any;
orderSpecs: any;
rowPositions: PositionCache;
constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement);
renderSkeletonHtml(): string;
render(props: ResourceViewProps): void;
updateHasNesting(isNesting: boolean): void;
diffRows(newNodes: any): void;
addRow(index: any, rowNode: any): void;
removeRows(startIndex: any, len: any, oldRowNodes: any): void;
buildChildComponent(node: (GroupNode | ResourceNode), spreadsheetTbody: HTMLElement, spreadsheetNext: HTMLElement, timeAxisTbody: HTMLElement, timeAxisNext: HTMLElement): GroupRow | ResourceRow;
renderRows(dateProfile: DateProfile, fallbackBusinessHours: any, splitProps: {
[resourceId: string]: SplittableProps;
}): void;
updateSize(isResize: any, viewHeight: any, isAuto: any): void;
syncHeadHeights(): void;
updateRowSizes(isResize: boolean): number;
destroy(): void;
getNowIndicatorUnit(dateProfile: DateProfile): string;
renderNowIndicator(date: any): void;
unrenderNowIndicator(): void;
queryScroll(): any;
applyScroll(scroll: any, isResize: any): void;
computeDateScroll(duration: Duration): {
left: number;
};
queryDateScroll(): {
left: number;
};
applyDateScroll(scroll: any): void;
queryResourceScroll(): any;
applyResourceScroll(scroll: any): void;
buildPositionCaches(): void;
queryHit(positionLeft: number, positionTop: number): Hit;
setResourceAreaWidth(widthVal: any): void;
initResourceAreaWidthDragging(): void;
}
}
declare module '@fullcalendar/resource-timeline/GroupRow' {
import {Group} from '@fullcalendar/resource-common';
import Row from '@fullcalendar/resource-timeline/Row';
export interface GroupRowProps {
spreadsheetColCnt: number;
id: string;
isExpanded: boolean;
group: Group;
}
export { GroupRow as default, GroupRow };
class GroupRow extends Row<GroupRowProps> {
spreadsheetHeightEl: HTMLElement;
timeAxisHeightEl: HTMLElement;
expanderIconEl: HTMLElement;
render(props: GroupRowProps): void;
destroy(): void;
renderCells(group: Group, spreadsheetColCnt: number): void;
unrenderCells(): void;
renderSpreadsheetContent(group: Group): HTMLElement;
renderCellText(group: Group): any;
getHeightEls(): HTMLElement[];
updateExpanderIcon(isExpanded: boolean): void;
onExpanderClick: (ev: UIEvent) => void;
}
}
declare module '@fullcalendar/resource-timeline/ResourceRow' {
import {
ComponentContext,
DateProfile,
DateSpan,
Duration,
EventInteractionState,
EventStore,
EventUiHash
} from '@fullcalendar/core';
import {TimeAxis, TimelineLane} from '@fullcalendar/timeline';
import Row from '@fullcalendar/resource-timeline/Row';
import SpreadsheetRow from '@fullcalendar/resource-timeline/SpreadsheetRow';
import {Resource} from '@fullcalendar/resource-common';
export interface ResourceRowProps {
dateProfile: DateProfile;
nextDayThreshold: Duration;
businessHours: EventStore | null;
eventStore: EventStore | null;
eventUiBases: EventUiHash;
dateSelection: DateSpan | null;
eventSelection: string;
eventDrag: EventInteractionState | null;
eventResize: EventInteractionState | null;
colSpecs: any;
id: string;
rowSpans: number[];
depth: number;
isExpanded: boolean;
hasChildren: boolean;
resource: Resource;
}
export { ResourceRow as default, ResourceRow };
class ResourceRow extends Row<ResourceRowProps> {
innerContainerEl: HTMLElement;
spreadsheetRow: SpreadsheetRow;
lane: TimelineLane;
constructor(context: ComponentContext, a: any, b: any, c: any, d: any, timeAxis: TimeAxis);
destroy(): void;
render(props: ResourceRowProps): void;
updateSize(isResize: boolean): void;
getHeightEls(): HTMLElement[];
}
}
declare module '@fullcalendar/resource-timeline/Spreadsheet' {
import {Component, ComponentContext} from '@fullcalendar/core';
import {HeaderBodyLayout} from '@fullcalendar/timeline';
import SpreadsheetHeader from '@fullcalendar/resource-timeline/SpreadsheetHeader';
export interface SpreadsheetProps {
superHeaderText: string;
colSpecs: any;
}
export {Spreadsheet as default, Spreadsheet};
class Spreadsheet extends Component<SpreadsheetProps> {
header: SpreadsheetHeader;
layout: HeaderBodyLayout;
bodyContainerEl: HTMLElement;
bodyColGroup: HTMLElement;
bodyTbody: HTMLElement;
bodyColEls: HTMLElement[];
constructor(context: ComponentContext, headParentEl: HTMLElement, bodyParentEl: HTMLElement);
destroy(): void;
render(props: SpreadsheetProps): void;
renderCells(superHeaderText: any, colSpecs: any): void;
unrenderCells(): void;
renderColTags(colSpecs: any): string;
updateSize(isResize: any, totalHeight: any, isAuto: any): void;
applyColWidths(colWidths: (number | string)[]): void;
}
}
declare module '@fullcalendar/resource-timeline/Row' {
import {Component, ComponentContext} from '@fullcalendar/core';
export { Row as default, Row };
abstract class Row<PropsType> extends Component<PropsType> {
spreadsheetTr: HTMLElement;
timeAxisTr: HTMLElement;
isSizeDirty: boolean;
constructor(context: ComponentContext, spreadsheetParent: HTMLElement, spreadsheetNextSibling: HTMLElement, timeAxisParent: HTMLElement, timeAxisNextSibling: HTMLElement);
destroy(): void;
abstract getHeightEls(): HTMLElement[];
updateSize(isResize: boolean): void;
}
}
declare module '@fullcalendar/resource-timeline/SpreadsheetRow' {
import {Component, ComponentContext} from '@fullcalendar/core';
import {Resource} from '@fullcalendar/resource-common';
export interface SpreadsheetRowProps {
colSpecs: any;
id: string;
rowSpans: number[];
depth: number;
isExpanded: boolean;
hasChildren: boolean;
resource: Resource;
}
export { SpreadsheetRow as default, SpreadsheetRow };
class SpreadsheetRow extends Component<SpreadsheetRowProps> {
tr: HTMLElement;
heightEl: HTMLElement;
expanderIconEl: HTMLElement;
constructor(context: ComponentContext, tr: HTMLElement);
render(props: SpreadsheetRowProps): void;
destroy(): void;
renderRow(resource: Resource, rowSpans: number[], depth: number, colSpecs: any): void;
unrenderRow(): void;
updateExpanderIcon(hasChildren: boolean, isExpanded: boolean): void;
onExpanderClick: (ev: UIEvent) => void;
}
}
declare module '@fullcalendar/resource-timeline/SpreadsheetHeader' {
import {Component, ComponentContext, ElementDragging, EmitterMixin} from '@fullcalendar/core';
export interface SpreadsheetHeaderProps {
superHeaderText: string;
colSpecs: any;
colTags: string;
}
export {SpreadsheetHeader as default, SpreadsheetHeader};
class SpreadsheetHeader extends Component<SpreadsheetHeaderProps> {
tableEl: HTMLElement;
resizerEls: HTMLElement[];
resizables: ElementDragging[];
thEls: HTMLElement[];
colEls: HTMLElement[];
colWidths: number[];
emitter: EmitterMixin;
constructor(context: ComponentContext, parentEl: HTMLElement);
destroy(): void;
render(props: SpreadsheetHeaderProps): void;
initColResizing(): void;
}
}
/*!
FullCalendar Resource Timeline Plugin v4.3.0
Docs & License: https://fullcalendar.io/scheduler
(c) 2019 Adam Shaw
*/
import {
applyStyleProp,
Component,
createElement,
createPlugin,
EmitterMixin,
htmlEscape,
htmlToElement,
isArraysEqual,
memoize,
memoizeRendering,
parseFieldSpecs,
PositionCache,
removeElement,
View
} from '@fullcalendar/core';
import TimelinePlugin, {
HeaderBodyLayout,
ScrollJoiner,
StickyScroller,
TimeAxis,
TimelineLane
} from '@fullcalendar/timeline';
import ResourceCommonPlugin, {
buildResourceFields,
buildResourceTextFunc,
buildRowNodes,
isGroupsEqual,
ResourceApi,
ResourceSplitter
} from '@fullcalendar/resource-common';
/*! *****************************************************************************
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);
};
var Row = /** @class */ (function (_super) {
__extends(Row, _super);
function Row(context, spreadsheetParent, spreadsheetNextSibling, timeAxisParent, timeAxisNextSibling) {
var _this = _super.call(this, context) || this;
_this.isSizeDirty = false;
spreadsheetParent.insertBefore(_this.spreadsheetTr = document.createElement('tr'), spreadsheetNextSibling);
timeAxisParent.insertBefore(_this.timeAxisTr = document.createElement('tr'), timeAxisNextSibling);
return _this;
}
Row.prototype.destroy = function () {
removeElement(this.spreadsheetTr);
removeElement(this.timeAxisTr);
_super.prototype.destroy.call(this);
};
Row.prototype.updateSize = function (isResize) {
this.isSizeDirty = false;
};
return Row;
}(Component));
function updateExpanderIcon(el, isExpanded) {
var classList = el.classList;
if (isExpanded) {
classList.remove('fc-icon-plus-square');
classList.add('fc-icon-minus-square');
}
else {
classList.remove('fc-icon-minus-square');
classList.add('fc-icon-plus-square');
}
}
function clearExpanderIcon(el) {
var classList = el.classList;
classList.remove('fc-icon-minus-square');
classList.remove('fc-icon-plus-square');
}
function updateTrResourceId(tr, resourceId) {
tr.setAttribute('data-resource-id', resourceId);
}
var GroupRow = /** @class */ (function (_super) {
__extends(GroupRow, _super);
function GroupRow() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._renderCells = memoizeRendering(_this.renderCells, _this.unrenderCells);
_this._updateExpanderIcon = memoizeRendering(_this.updateExpanderIcon, null, [_this._renderCells]);
_this.onExpanderClick = function (ev) {
var props = _this.props;
_this.calendar.dispatch({
type: 'SET_RESOURCE_ENTITY_EXPANDED',
id: props.id,
isExpanded: !props.isExpanded
});
};
return _this;
}
GroupRow.prototype.render = function (props) {
this._renderCells(props.group, props.spreadsheetColCnt);
this._updateExpanderIcon(props.isExpanded);
this.isSizeDirty = true;
};
GroupRow.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this._renderCells.unrender(); // should unrender everything else
};
GroupRow.prototype.renderCells = function (group, spreadsheetColCnt) {
var spreadsheetContentEl = this.renderSpreadsheetContent(group);
this.spreadsheetTr.appendChild(createElement('td', {
className: 'fc-divider',
colSpan: spreadsheetColCnt // span across all columns
}, this.spreadsheetHeightEl = createElement('div', null, spreadsheetContentEl)) // needed by setTrInnerHeight
);
this.expanderIconEl = spreadsheetContentEl.querySelector('.fc-icon');
this.expanderIconEl.parentElement.addEventListener('click', this.onExpanderClick);
// insert a single cell, with a single empty <div>.
// there will be no content
this.timeAxisTr.appendChild(createElement('td', { className: 'fc-divider' }, this.timeAxisHeightEl = document.createElement('div')));
};
GroupRow.prototype.unrenderCells = function () {
this.spreadsheetTr.innerHTML = '';
this.timeAxisTr.innerHTML = '';
};
/*
Renders the content wrapper element that will be inserted into this row's TD cell.
*/
GroupRow.prototype.renderSpreadsheetContent = function (group) {
var text = this.renderCellText(group);
var contentEl = htmlToElement('<div class="fc-cell-content">' +
'<span class="fc-expander">' +
'<span class="fc-icon"></span>' +
'</span>' +
'<span class="fc-cell-text">' +
(text ? htmlEscape(text) : '&nbsp;') +
'</span>' +
'</div>');
var filter = group.spec.render;
if (typeof filter === 'function') {
contentEl = filter(contentEl, group.value) || contentEl;
}
return contentEl;
};
GroupRow.prototype.renderCellText = function (group) {
var text = group.value || ''; // might be null/undefined if an ad-hoc grouping
var filter = group.spec.text;
if (typeof filter === 'function') {
text = filter(text) || text;
}
return text;
};
GroupRow.prototype.getHeightEls = function () {
return [this.spreadsheetHeightEl, this.timeAxisHeightEl];
};
GroupRow.prototype.updateExpanderIcon = function (isExpanded) {
updateExpanderIcon(this.expanderIconEl, isExpanded);
};
return GroupRow;
}(Row));
GroupRow.addEqualityFuncs({
group: isGroupsEqual // HACK for ResourceTimelineView::renderRows
});
var SpreadsheetRow = /** @class */ (function (_super) {
__extends(SpreadsheetRow, _super);
function SpreadsheetRow(context, tr) {
var _this = _super.call(this, context) || this;
_this._renderRow = memoizeRendering(_this.renderRow, _this.unrenderRow);
_this._updateTrResourceId = memoizeRendering(updateTrResourceId, null, [_this._renderRow]);
_this._updateExpanderIcon = memoizeRendering(_this.updateExpanderIcon, null, [_this._renderRow]);
_this.onExpanderClick = function (ev) {
var props = _this.props;
_this.calendar.dispatch({
type: 'SET_RESOURCE_ENTITY_EXPANDED',
id: props.id,
isExpanded: !props.isExpanded
});
};
_this.tr = tr;
return _this;
}
SpreadsheetRow.prototype.render = function (props) {
this._renderRow(props.resource, props.rowSpans, props.depth, props.colSpecs);
this._updateTrResourceId(this.tr, props.resource.id); // TODO: only use public ID?
this._updateExpanderIcon(props.hasChildren, props.isExpanded);
};
SpreadsheetRow.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this._renderRow.unrender(); // should unrender everything else
};
SpreadsheetRow.prototype.renderRow = function (resource, rowSpans, depth, colSpecs) {
var _a = this, tr = _a.tr, theme = _a.theme, calendar = _a.calendar, view = _a.view;
var resourceFields = buildResourceFields(resource); // slightly inefficient. already done up the call stack
var mainTd;
for (var i = 0; i < colSpecs.length; i++) {
var colSpec = colSpecs[i];
var rowSpan = rowSpans[i];
if (rowSpan === 0) { // not responsible for group-based rows. VRowGroup is
continue;
}
else if (rowSpan == null) {
rowSpan = 1;
}
var text = void 0;
if (colSpec.field) {
text = resourceFields[colSpec.field];
}
else {
text = buildResourceTextFunc(colSpec.text, calendar)(resource);
}
var contentEl = htmlToElement('<div class="fc-cell-content">' +
(colSpec.isMain ? renderIconHtml(depth) : '') +
'<span class="fc-cell-text">' +
(text ? htmlEscape(text) : '&nbsp;') +
'</span>' +
'</div>');
if (typeof colSpec.render === 'function') { // a filter function for the element
contentEl = colSpec.render(new ResourceApi(calendar, resource), contentEl) || contentEl;
}
if (rowSpan > 1) {
contentEl.classList.add('fc-sticky');
}
var td = createElement('td', {
className: theme.getClass('widgetContent'),
rowspan: rowSpan
}, contentEl);
// the first cell of the row needs to have an inner div for setTrInnerHeight
if (colSpec.isMain) {
td.appendChild(this.heightEl = createElement('div', null, td.childNodes) // inner wrap
);
mainTd = td;
}
tr.appendChild(td);
}
this.expanderIconEl = tr.querySelector('.fc-expander-space .fc-icon');
// wait until very end
view.publiclyTrigger('resourceRender', [
{
resource: new ResourceApi(calendar, resource),
el: mainTd,
view: view
}
]);
};
SpreadsheetRow.prototype.unrenderRow = function () {
this.tr.innerHTML = '';
};
SpreadsheetRow.prototype.updateExpanderIcon = function (hasChildren, isExpanded) {
var expanderIconEl = this.expanderIconEl;
var expanderEl = expanderIconEl.parentElement;
if (expanderIconEl &&
expanderEl // why would this be null?? was the case in IE11
) {
if (hasChildren) {
expanderEl.addEventListener('click', this.onExpanderClick);
expanderEl.classList.add('fc-expander');
updateExpanderIcon(expanderIconEl, isExpanded);
}
else {
expanderEl.removeEventListener('click', this.onExpanderClick);
expanderEl.classList.remove('fc-expander');
clearExpanderIcon(expanderIconEl);
}
}
};
return SpreadsheetRow;
}(Component));
/*
Renders the HTML responsible for the subrow expander area,
as well as the space before it (used to align expanders of similar depths)
*/
function renderIconHtml(depth) {
var html = '';
for (var i = 0; i < depth; i++) {
html += '<span class="fc-icon"></span>';
}
html +=
'<span class="fc-expander-space">' +
'<span class="fc-icon"></span>' +
'</span>';
return html;
}
var ResourceRow = /** @class */ (function (_super) {
__extends(ResourceRow, _super);
function ResourceRow(context, a, b, c, d, timeAxis) {
var _this = _super.call(this, context, a, b, c, d) || this;
_this._updateTrResourceId = memoizeRendering(updateTrResourceId);
_this.spreadsheetRow = new SpreadsheetRow(context, _this.spreadsheetTr);
_this.timeAxisTr.appendChild(createElement('td', { className: _this.theme.getClass('widgetContent') }, _this.innerContainerEl = document.createElement('div')));
_this.lane = new TimelineLane(context, _this.innerContainerEl, _this.innerContainerEl, timeAxis);
return _this;
}
ResourceRow.prototype.destroy = function () {
this.spreadsheetRow.destroy();
this.lane.destroy();
_super.prototype.destroy.call(this);
};
ResourceRow.prototype.render = function (props) {
// spreadsheetRow handles calling updateTrResourceId for spreadsheetTr
this.spreadsheetRow.receiveProps({
colSpecs: props.colSpecs,
id: props.id,
rowSpans: props.rowSpans,
depth: props.depth,
isExpanded: props.isExpanded,
hasChildren: props.hasChildren,
resource: props.resource
});
this._updateTrResourceId(this.timeAxisTr, props.resource.id);
this.lane.receiveProps({
dateProfile: props.dateProfile,
nextDayThreshold: props.nextDayThreshold,
businessHours: props.businessHours,
eventStore: props.eventStore,
eventUiBases: props.eventUiBases,
dateSelection: props.dateSelection,
eventSelection: props.eventSelection,
eventDrag: props.eventDrag,
eventResize: props.eventResize
});
this.isSizeDirty = true;
};
ResourceRow.prototype.updateSize = function (isResize) {
_super.prototype.updateSize.call(this, isResize);
this.lane.updateSize(isResize);
};
ResourceRow.prototype.getHeightEls = function () {
return [this.spreadsheetRow.heightEl, this.innerContainerEl];
};
return ResourceRow;
}(Row));
ResourceRow.addEqualityFuncs({
rowSpans: isArraysEqual // HACK for isSizeDirty, ResourceTimelineView::renderRows
});
var COL_MIN_WIDTH = 30;
var SpreadsheetHeader = /** @class */ (function (_super) {
__extends(SpreadsheetHeader, _super);
function SpreadsheetHeader(context, parentEl) {
var _this = _super.call(this, context) || this;
_this.resizables = [];
_this.colWidths = [];
_this.emitter = new EmitterMixin();
parentEl.appendChild(_this.tableEl = createElement('table', {
className: _this.theme.getClass('tableGrid')
}));
return _this;
}
SpreadsheetHeader.prototype.destroy = function () {
for (var _i = 0, _a = this.resizables; _i < _a.length; _i++) {
var resizable = _a[_i];
resizable.destroy();
}
removeElement(this.tableEl);
_super.prototype.destroy.call(this);
};
SpreadsheetHeader.prototype.render = function (props) {
var theme = this.theme;
var colSpecs = props.colSpecs;
var html = '<colgroup>' + props.colTags + '</colgroup>' +
'<tbody>';
if (props.superHeaderText) {
html +=
'<tr class="fc-super">' +
'<th class="' + theme.getClass('widgetHeader') + '" colspan="' + colSpecs.length + '">' +
'<div class="fc-cell-content">' +
'<span class="fc-cell-text">' +
htmlEscape(props.superHeaderText) +
'</span>' +
'</div>' +
'</th>' +
'</tr>';
}
html += '<tr>';
for (var i = 0; i < colSpecs.length; i++) {
var o = colSpecs[i];
var isLast = i === (colSpecs.length - 1);
html +=
"<th class=\"" + theme.getClass('widgetHeader') + "\">" +
'<div>' +
'<div class="fc-cell-content">' +
(o.isMain ?
'<span class="fc-expander-space">' +
'<span class="fc-icon"></span>' +
'</span>' :
'') +
'<span class="fc-cell-text">' +
htmlEscape(o.labelText || '') + // what about normalizing this value ahead of time?
'</span>' +
'</div>' +
(!isLast ? '<div class="fc-col-resizer"></div>' : '') +
'</div>' +
'</th>';
}
html += '</tr>';
html += '</tbody>';
this.tableEl.innerHTML = html;
this.thEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('th'));
this.colEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('col'));
this.resizerEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('.fc-col-resizer'));
this.initColResizing();
};
SpreadsheetHeader.prototype.initColResizing = function () {
var _this = this;
var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl;
if (ElementDraggingImpl) {
this.resizables = this.resizerEls.map(function (handleEl, colIndex) {
var dragging = new ElementDraggingImpl(handleEl);
var startWidth;
dragging.emitter.on('dragstart', function () {
startWidth = _this.colWidths[colIndex];
if (typeof startWidth !== 'number') {
startWidth = _this.thEls[colIndex].getBoundingClientRect().width;
}
});
dragging.emitter.on('dragmove', function (pev) {
_this.colWidths[colIndex] = Math.max(startWidth + pev.deltaX * (_this.isRtl ? -1 : 1), COL_MIN_WIDTH);
_this.emitter.trigger('colwidthchange', _this.colWidths);
});
dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area
return dragging;
});
}
};
return SpreadsheetHeader;
}(Component));
var Spreadsheet = /** @class */ (function (_super) {
__extends(Spreadsheet, _super);
function Spreadsheet(context, headParentEl, bodyParentEl) {
var _this = _super.call(this, context) || this;
_this._renderCells = memoizeRendering(_this.renderCells, _this.unrenderCells);
_this.layout = new HeaderBodyLayout(headParentEl, bodyParentEl, 'clipped-scroll');
var headerEnhancedScroller = _this.layout.headerScroller.enhancedScroll;
var bodyEnhancedScroller = _this.layout.bodyScroller.enhancedScroll;
_this.header = new SpreadsheetHeader(context, headerEnhancedScroller.canvas.contentEl);
_this.header.emitter.on('colwidthchange', function (colWidths) {
_this.applyColWidths(colWidths);
});
bodyEnhancedScroller.canvas.contentEl
.appendChild(_this.bodyContainerEl = createElement('div', { className: 'fc-rows' }, '<table>' +
'<colgroup />' +
'<tbody />' +
'</table>'));
_this.bodyColGroup = _this.bodyContainerEl.querySelector('colgroup');
_this.bodyTbody = _this.bodyContainerEl.querySelector('tbody');
return _this;
}
Spreadsheet.prototype.destroy = function () {
this.header.destroy();
this.layout.destroy();
this._renderCells.unrender();
_super.prototype.destroy.call(this);
};
Spreadsheet.prototype.render = function (props) {
this._renderCells(props.superHeaderText, props.colSpecs);
};
Spreadsheet.prototype.renderCells = function (superHeaderText, colSpecs) {
var colTags = this.renderColTags(colSpecs);
this.header.receiveProps({
superHeaderText: superHeaderText,
colSpecs: colSpecs,
colTags: colTags
});
this.bodyColGroup.innerHTML = colTags;
this.bodyColEls = Array.prototype.slice.call(this.bodyColGroup.querySelectorAll('col'));
this.applyColWidths(colSpecs.map(function (colSpec) { return colSpec.width; }));
};
Spreadsheet.prototype.unrenderCells = function () {
this.bodyColGroup.innerHTML = '';
};
Spreadsheet.prototype.renderColTags = function (colSpecs) {
var html = '';
for (var _i = 0, colSpecs_1 = colSpecs; _i < colSpecs_1.length; _i++) {
var o = colSpecs_1[_i];
if (o.isMain) {
html += '<col class="fc-main-col"/>';
}
else {
html += '<col/>';
}
}
return html;
};
Spreadsheet.prototype.updateSize = function (isResize, totalHeight, isAuto) {
this.layout.setHeight(totalHeight, isAuto);
};
Spreadsheet.prototype.applyColWidths = function (colWidths) {
var _this = this;
colWidths.forEach(function (colWidth, colIndex) {
var headEl = _this.header.colEls[colIndex]; // bad to access child
var bodyEl = _this.bodyColEls[colIndex];
var styleVal;
if (typeof colWidth === 'number') {
styleVal = colWidth + 'px';
}
else if (typeof colWidth == null) {
styleVal = '';
}
headEl.style.width = bodyEl.style.width = styleVal;
});
};
return Spreadsheet;
}(Component));
var MIN_RESOURCE_AREA_WIDTH = 30; // definitely bigger than scrollbars
var ResourceTimelineView = /** @class */ (function (_super) {
__extends(ResourceTimelineView, _super);
function ResourceTimelineView(context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.isStickyScrollDirty = false;
_this.rowNodes = [];
_this.rowComponents = [];
_this.rowComponentsById = {};
_this.resourceAreaWidthDraggings = [];
_this.splitter = new ResourceSplitter(); // doesn't let it do businessHours tho
_this.hasResourceBusinessHours = memoize(hasResourceBusinessHours);
_this.buildRowNodes = memoize(buildRowNodes);
_this.hasNesting = memoize(hasNesting);
_this._updateHasNesting = memoizeRendering(_this.updateHasNesting);
var allColSpecs = _this.opt('resourceColumns') || [];
var labelText = _this.opt('resourceLabelText'); // TODO: view.override
var defaultLabelText = 'Resources'; // TODO: view.defaults
var superHeaderText = null;
if (!allColSpecs.length) {
allColSpecs.push({
labelText: labelText || defaultLabelText,
text: buildResourceTextFunc(_this.opt('resourceText'), _this.calendar)
});
}
else {
superHeaderText = labelText;
}
var plainColSpecs = [];
var groupColSpecs = [];
var groupSpecs = [];
var isVGrouping = false;
var isHGrouping = false;
for (var _i = 0, allColSpecs_1 = allColSpecs; _i < allColSpecs_1.length; _i++) {
var colSpec = allColSpecs_1[_i];
if (colSpec.group) {
groupColSpecs.push(colSpec);
}
else {
plainColSpecs.push(colSpec);
}
}
plainColSpecs[0].isMain = true;
if (groupColSpecs.length) {
groupSpecs = groupColSpecs;
isVGrouping = true;
}
else {
var hGroupField = _this.opt('resourceGroupField');
if (hGroupField) {
isHGrouping = true;
groupSpecs.push({
field: hGroupField,
text: _this.opt('resourceGroupText'),
render: _this.opt('resourceGroupRender')
});
}
}
var allOrderSpecs = parseFieldSpecs(_this.opt('resourceOrder'));
var plainOrderSpecs = [];
for (var _a = 0, allOrderSpecs_1 = allOrderSpecs; _a < allOrderSpecs_1.length; _a++) {
var orderSpec = allOrderSpecs_1[_a];
var isGroup = false;
for (var _b = 0, groupSpecs_1 = groupSpecs; _b < groupSpecs_1.length; _b++) {
var groupSpec = groupSpecs_1[_b];
if (groupSpec.field === orderSpec.field) {
groupSpec.order = orderSpec.order; // -1, 0, 1
isGroup = true;
break;
}
}
if (!isGroup) {
plainOrderSpecs.push(orderSpec);
}
}
_this.superHeaderText = superHeaderText;
_this.isVGrouping = isVGrouping;
_this.isHGrouping = isHGrouping;
_this.groupSpecs = groupSpecs;
_this.colSpecs = groupColSpecs.concat(plainColSpecs);
_this.orderSpecs = plainOrderSpecs;
// START RENDERING...
_this.el.classList.add('fc-timeline');
if (_this.opt('eventOverlap') === false) {
_this.el.classList.add('fc-no-overlap');
}
_this.el.innerHTML = _this.renderSkeletonHtml();
_this.resourceAreaHeadEl = _this.el.querySelector('thead .fc-resource-area');
_this.setResourceAreaWidth(_this.opt('resourceAreaWidth'));
_this.initResourceAreaWidthDragging();
_this.miscHeight = _this.el.getBoundingClientRect().height;
_this.spreadsheet = new Spreadsheet(_this.context, _this.resourceAreaHeadEl, _this.el.querySelector('tbody .fc-resource-area'));
_this.timeAxis = new TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area'));
var timeAxisRowContainer = createElement('div', { className: 'fc-rows' }, '<table><tbody /></table>');
_this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl.appendChild(timeAxisRowContainer);
_this.timeAxisTbody = timeAxisRowContainer.querySelector('tbody');
_this.lane = new TimelineLane(_this.context, null, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis);
_this.bodyScrollJoiner = new ScrollJoiner('vertical', [
_this.spreadsheet.layout.bodyScroller,
_this.timeAxis.layout.bodyScroller
]);
// after scrolljoiner
_this.spreadsheetBodyStickyScroller = new StickyScroller(_this.spreadsheet.layout.bodyScroller.enhancedScroll, _this.isRtl, true // isVertical
);
_this.spreadsheet.receiveProps({
superHeaderText: _this.superHeaderText,
colSpecs: _this.colSpecs
});
// Component...
context.calendar.registerInteractiveComponent(_this, {
el: _this.timeAxis.slats.el
});
return _this;
}
ResourceTimelineView.prototype.renderSkeletonHtml = function () {
var theme = this.theme;
return "<table class=\"" + theme.getClass('tableGrid') + "\"> <thead class=\"fc-head\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetHeader') + "\"></td> </tr> </thead> <tbody class=\"fc-body\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetContent') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetContent') + "\"></td> </tr> </tbody> </table>";
};
ResourceTimelineView.prototype.render = function (props) {
_super.prototype.render.call(this, props);
var splitProps = this.splitter.splitProps(props);
var hasResourceBusinessHours = this.hasResourceBusinessHours(props.resourceStore);
this.timeAxis.receiveProps({
dateProfile: props.dateProfile
});
// for all-resource bg events / selections / business-hours
this.lane.receiveProps(__assign({}, splitProps[''], { dateProfile: props.dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: hasResourceBusinessHours ? null : props.businessHours }));
var newRowNodes = this.buildRowNodes(props.resourceStore, this.groupSpecs, this.orderSpecs, this.isVGrouping, props.resourceEntityExpansions, this.opt('resourcesInitiallyExpanded'));
this._updateHasNesting(this.hasNesting(newRowNodes));
this.diffRows(newRowNodes);
this.renderRows(props.dateProfile, hasResourceBusinessHours ? props.businessHours : null, // CONFUSING, comment
splitProps);
};
ResourceTimelineView.prototype.updateHasNesting = function (isNesting) {
var classList = this.el.classList;
if (isNesting) {
classList.remove('fc-flat');
}
else {
classList.add('fc-flat');
}
};
ResourceTimelineView.prototype.diffRows = function (newNodes) {
var oldNodes = this.rowNodes;
var oldLen = oldNodes.length;
var oldIndexHash = {}; // id -> index
var oldI = 0;
var newI = 0;
for (oldI = 0; oldI < oldLen; oldI++) {
oldIndexHash[oldNodes[oldI].id] = oldI;
}
// iterate new nodes
for (oldI = 0, newI = 0; newI < newNodes.length; newI++) {
var newNode = newNodes[newI];
var oldIFound = oldIndexHash[newNode.id];
if (oldIFound != null && oldIFound >= oldI) {
this.removeRows(newI, oldIFound - oldI, oldNodes); // won't do anything if same index
oldI = oldIFound + 1;
}
else {
this.addRow(newI, newNode);
}
}
// old rows that weren't found need to be removed
this.removeRows(newI, oldLen - oldI, oldNodes); // won't do anything if same index
this.rowNodes = newNodes;
};
/*
rowComponents is the in-progress result
*/
ResourceTimelineView.prototype.addRow = function (index, rowNode) {
var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById;
var nextComponent = rowComponents[index];
var newComponent = this.buildChildComponent(rowNode, this.spreadsheet.bodyTbody, nextComponent ? nextComponent.spreadsheetTr : null, this.timeAxisTbody, nextComponent ? nextComponent.timeAxisTr : null);
rowComponents.splice(index, 0, newComponent);
rowComponentsById[rowNode.id] = newComponent;
};
ResourceTimelineView.prototype.removeRows = function (startIndex, len, oldRowNodes) {
if (len) {
var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById;
for (var i = 0; i < len; i++) {
var rowComponent = rowComponents[startIndex + i];
rowComponent.destroy();
delete rowComponentsById[oldRowNodes[i].id];
}
rowComponents.splice(startIndex, len);
}
};
ResourceTimelineView.prototype.buildChildComponent = function (node, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext) {
if (node.group) {
return new GroupRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext);
}
else if (node.resource) {
return new ResourceRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext, this.timeAxis);
}
};
ResourceTimelineView.prototype.renderRows = function (dateProfile, fallbackBusinessHours, splitProps) {
var _a = this, rowNodes = _a.rowNodes, rowComponents = _a.rowComponents;
for (var i = 0; i < rowNodes.length; i++) {
var rowNode = rowNodes[i];
var rowComponent = rowComponents[i];
if (rowNode.group) {
rowComponent.receiveProps({
spreadsheetColCnt: this.colSpecs.length,
id: rowNode.id,
isExpanded: rowNode.isExpanded,
group: rowNode.group
});
}
else {
var resource = rowNode.resource;
rowComponent.receiveProps(__assign({}, splitProps[resource.id], { dateProfile: dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: resource.businessHours || fallbackBusinessHours, colSpecs: this.colSpecs, id: rowNode.id, rowSpans: rowNode.rowSpans, depth: rowNode.depth, isExpanded: rowNode.isExpanded, hasChildren: rowNode.hasChildren, resource: rowNode.resource }));
}
}
};
ResourceTimelineView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
// FYI: this ordering is really important
var calendar = this.calendar;
var isBaseSizing = isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated;
if (isBaseSizing) {
this.syncHeadHeights();
this.timeAxis.updateSize(isResize, viewHeight - this.miscHeight, isAuto);
this.spreadsheet.updateSize(isResize, viewHeight - this.miscHeight, isAuto);
}
var rowSizingCnt = this.updateRowSizes(isResize);
this.lane.updateSize(isResize); // is efficient. uses flags
if (isBaseSizing || rowSizingCnt) {
this.bodyScrollJoiner.update();
this.timeAxis.layout.scrollJoiner.update(); // hack
this.rowPositions = new PositionCache(this.timeAxis.slats.el, this.rowComponents.map(function (rowComponent) {
return rowComponent.timeAxisTr;
}), false, // isHorizontal
true // isVertical
);
this.rowPositions.build();
this.isStickyScrollDirty = true;
}
};
ResourceTimelineView.prototype.syncHeadHeights = function () {
var spreadsheetHeadEl = this.spreadsheet.header.tableEl;
var timeAxisHeadEl = this.timeAxis.header.tableEl;
spreadsheetHeadEl.style.height = '';
timeAxisHeadEl.style.height = '';
var max = Math.max(spreadsheetHeadEl.getBoundingClientRect().height, timeAxisHeadEl.getBoundingClientRect().height);
spreadsheetHeadEl.style.height =
timeAxisHeadEl.style.height = max + 'px';
};
ResourceTimelineView.prototype.updateRowSizes = function (isResize) {
var dirtyRowComponents = this.rowComponents;
if (!isResize) {
dirtyRowComponents = dirtyRowComponents.filter(function (rowComponent) {
return rowComponent.isSizeDirty;
});
}
var elArrays = dirtyRowComponents.map(function (rowComponent) {
return rowComponent.getHeightEls();
});
// reset to natural heights
for (var _i = 0, elArrays_1 = elArrays; _i < elArrays_1.length; _i++) {
var elArray = elArrays_1[_i];
for (var _a = 0, elArray_1 = elArray; _a < elArray_1.length; _a++) {
var el = elArray_1[_a];
el.style.height = '';
}
}
// let rows update their contents' heights
for (var _b = 0, dirtyRowComponents_1 = dirtyRowComponents; _b < dirtyRowComponents_1.length; _b++) {
var rowComponent = dirtyRowComponents_1[_b];
rowComponent.updateSize(isResize); // will reset isSizeDirty
}
var maxHeights = elArrays.map(function (elArray) {
var maxHeight = null;
for (var _i = 0, elArray_2 = elArray; _i < elArray_2.length; _i++) {
var el = elArray_2[_i];
var height = el.getBoundingClientRect().height;
if (maxHeight === null || height > maxHeight) {
maxHeight = height;
}
}
return maxHeight;
});
for (var i = 0; i < elArrays.length; i++) {
for (var _c = 0, _d = elArrays[i]; _c < _d.length; _c++) {
var el = _d[_c];
el.style.height = maxHeights[i] + 'px';
}
}
return dirtyRowComponents.length;
};
ResourceTimelineView.prototype.destroy = function () {
for (var _i = 0, _a = this.rowComponents; _i < _a.length; _i++) {
var rowComponent = _a[_i];
rowComponent.destroy();
}
this.rowNodes = [];
this.rowComponents = [];
this.spreadsheet.destroy();
this.timeAxis.destroy();
for (var _b = 0, _c = this.resourceAreaWidthDraggings; _b < _c.length; _b++) {
var resourceAreaWidthDragging = _c[_b];
resourceAreaWidthDragging.destroy();
}
this.spreadsheetBodyStickyScroller.destroy();
_super.prototype.destroy.call(this);
this.calendar.unregisterInteractiveComponent(this);
};
// Now Indicator
// ------------------------------------------------------------------------------------------
ResourceTimelineView.prototype.getNowIndicatorUnit = function (dateProfile) {
return this.timeAxis.getNowIndicatorUnit(dateProfile);
};
ResourceTimelineView.prototype.renderNowIndicator = function (date) {
this.timeAxis.renderNowIndicator(date);
};
ResourceTimelineView.prototype.unrenderNowIndicator = function () {
this.timeAxis.unrenderNowIndicator();
};
// Scrolling
// ------------------------------------------------------------------------------------------------------------------
// this is useful for scrolling prev/next dates while resource is scrolled down
ResourceTimelineView.prototype.queryScroll = function () {
var scroll = _super.prototype.queryScroll.call(this);
if (this.props.resourceStore) {
__assign(scroll, this.queryResourceScroll());
}
return scroll;
};
ResourceTimelineView.prototype.applyScroll = function (scroll, isResize) {
_super.prototype.applyScroll.call(this, scroll, isResize);
if (this.props.resourceStore) {
this.applyResourceScroll(scroll);
}
// avoid updating stickyscroll too often
if (isResize || this.isStickyScrollDirty) {
this.isStickyScrollDirty = false;
this.spreadsheetBodyStickyScroller.updateSize();
this.timeAxis.updateStickyScrollers();
}
};
ResourceTimelineView.prototype.computeDateScroll = function (duration) {
return this.timeAxis.computeDateScroll(duration);
};
ResourceTimelineView.prototype.queryDateScroll = function () {
return this.timeAxis.queryDateScroll();
};
ResourceTimelineView.prototype.applyDateScroll = function (scroll) {
this.timeAxis.applyDateScroll(scroll);
};
ResourceTimelineView.prototype.queryResourceScroll = function () {
var _a = this, rowComponents = _a.rowComponents, rowNodes = _a.rowNodes;
var scroll = {};
var scrollerTop = this.timeAxis.layout.bodyScroller.el.getBoundingClientRect().top; // fixed position
for (var i = 0; i < rowComponents.length; i++) {
var rowComponent = rowComponents[i];
var rowNode = rowNodes[i];
var el = rowComponent.timeAxisTr;
var elBottom = el.getBoundingClientRect().bottom; // fixed position
if (elBottom > scrollerTop) {
scroll.rowId = rowNode.id;
scroll.bottom = elBottom - scrollerTop;
break;
}
}
// TODO: what about left scroll state for spreadsheet area?
return scroll;
};
ResourceTimelineView.prototype.applyResourceScroll = function (scroll) {
var rowId = scroll.forcedRowId || scroll.rowId;
if (rowId) {
var rowComponent = this.rowComponentsById[rowId];
if (rowComponent) {
var el = rowComponent.timeAxisTr;
if (el) {
var innerTop = this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.el.getBoundingClientRect().top;
var rowRect = el.getBoundingClientRect();
var scrollTop = (scroll.forcedRowId ?
rowRect.top : // just use top edge
rowRect.bottom - scroll.bottom) - // pixels from bottom edge
innerTop;
this.timeAxis.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop);
this.spreadsheet.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop);
}
}
}
};
// TODO: scrollToResource
// Hit System
// ------------------------------------------------------------------------------------------
ResourceTimelineView.prototype.buildPositionCaches = function () {
this.timeAxis.slats.updateSize();
this.rowPositions.build();
};
ResourceTimelineView.prototype.queryHit = function (positionLeft, positionTop) {
var rowPositions = this.rowPositions;
var slats = this.timeAxis.slats;
var rowIndex = rowPositions.topToIndex(positionTop);
if (rowIndex != null) {
var resource = this.rowNodes[rowIndex].resource;
if (resource) { // not a group
var slatHit = slats.positionToHit(positionLeft);
if (slatHit) {
return {
component: this,
dateSpan: {
range: slatHit.dateSpan.range,
allDay: slatHit.dateSpan.allDay,
resourceId: resource.id
},
rect: {
left: slatHit.left,
right: slatHit.right,
top: rowPositions.tops[rowIndex],
bottom: rowPositions.bottoms[rowIndex]
},
dayEl: slatHit.dayEl,
layer: 0
};
}
}
}
};
// Resource Area
// ------------------------------------------------------------------------------------------------------------------
ResourceTimelineView.prototype.setResourceAreaWidth = function (widthVal) {
this.resourceAreaWidth = widthVal;
applyStyleProp(this.resourceAreaHeadEl, 'width', widthVal || '');
};
ResourceTimelineView.prototype.initResourceAreaWidthDragging = function () {
var _this = this;
var resourceAreaDividerEls = Array.prototype.slice.call(this.el.querySelectorAll('.fc-col-resizer'));
var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl;
if (ElementDraggingImpl) {
this.resourceAreaWidthDraggings = resourceAreaDividerEls.map(function (el) {
var dragging = new ElementDraggingImpl(el);
var dragStartWidth;
var viewWidth;
dragging.emitter.on('dragstart', function () {
dragStartWidth = _this.resourceAreaWidth;
if (typeof dragStartWidth !== 'number') {
dragStartWidth = _this.resourceAreaHeadEl.getBoundingClientRect().width;
}
viewWidth = _this.el.getBoundingClientRect().width;
});
dragging.emitter.on('dragmove', function (pev) {
var newWidth = dragStartWidth + pev.deltaX * (_this.isRtl ? -1 : 1);
newWidth = Math.max(newWidth, MIN_RESOURCE_AREA_WIDTH);
newWidth = Math.min(newWidth, viewWidth - MIN_RESOURCE_AREA_WIDTH);
_this.setResourceAreaWidth(newWidth);
});
dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area
return dragging;
});
}
};
ResourceTimelineView.needsResourceData = true; // for ResourceViewProps
return ResourceTimelineView;
}(View));
function hasResourceBusinessHours(resourceStore) {
for (var resourceId in resourceStore) {
var resource = resourceStore[resourceId];
if (resource.businessHours) {
return true;
}
}
return false;
}
function hasNesting(nodes) {
for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
var node = nodes_1[_i];
if (node.group) {
return true;
}
else if (node.resource) {
if (node.hasChildren) {
return true;
}
}
}
return false;
}
var main = createPlugin({
deps: [ResourceCommonPlugin, TimelinePlugin],
defaultView: 'resourceTimelineDay',
views: {
resourceTimeline: {
class: ResourceTimelineView,
resourceAreaWidth: '30%',
resourcesInitiallyExpanded: true,
eventResizableFromStart: true // TODO: not DRY with this same setting in the main timeline config
},
resourceTimelineDay: {
type: 'resourceTimeline',
duration: { days: 1 }
},
resourceTimelineWeek: {
type: 'resourceTimeline',
duration: { weeks: 1 }
},
resourceTimelineMonth: {
type: 'resourceTimeline',
duration: { months: 1 }
},
resourceTimelineYear: {
type: 'resourceTimeline',
duration: { years: 1 }
}
}
});
export default main;
export { ResourceTimelineView };
/*!
FullCalendar Resource 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'), require('@fullcalendar/timeline'), require('@fullcalendar/resource-common')) :
typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/timeline', '@fullcalendar/resource-common'], factory) :
(global = global || self, factory(global.FullCalendarResourceTimeline = {}, global.FullCalendar, global.FullCalendarTimeline, global.FullCalendarResourceCommon));
}(this, function (exports, core, TimelinePlugin, ResourceCommonPlugin) { 'use strict';
var TimelinePlugin__default = 'default' in TimelinePlugin ? TimelinePlugin['default'] : TimelinePlugin;
var ResourceCommonPlugin__default = 'default' in ResourceCommonPlugin ? ResourceCommonPlugin['default'] : ResourceCommonPlugin;
/*! *****************************************************************************
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);
};
var Row = /** @class */ (function (_super) {
__extends(Row, _super);
function Row(context, spreadsheetParent, spreadsheetNextSibling, timeAxisParent, timeAxisNextSibling) {
var _this = _super.call(this, context) || this;
_this.isSizeDirty = false;
spreadsheetParent.insertBefore(_this.spreadsheetTr = document.createElement('tr'), spreadsheetNextSibling);
timeAxisParent.insertBefore(_this.timeAxisTr = document.createElement('tr'), timeAxisNextSibling);
return _this;
}
Row.prototype.destroy = function () {
core.removeElement(this.spreadsheetTr);
core.removeElement(this.timeAxisTr);
_super.prototype.destroy.call(this);
};
Row.prototype.updateSize = function (isResize) {
this.isSizeDirty = false;
};
return Row;
}(core.Component));
function updateExpanderIcon(el, isExpanded) {
var classList = el.classList;
if (isExpanded) {
classList.remove('fc-icon-plus-square');
classList.add('fc-icon-minus-square');
}
else {
classList.remove('fc-icon-minus-square');
classList.add('fc-icon-plus-square');
}
}
function clearExpanderIcon(el) {
var classList = el.classList;
classList.remove('fc-icon-minus-square');
classList.remove('fc-icon-plus-square');
}
function updateTrResourceId(tr, resourceId) {
tr.setAttribute('data-resource-id', resourceId);
}
var GroupRow = /** @class */ (function (_super) {
__extends(GroupRow, _super);
function GroupRow() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._renderCells = core.memoizeRendering(_this.renderCells, _this.unrenderCells);
_this._updateExpanderIcon = core.memoizeRendering(_this.updateExpanderIcon, null, [_this._renderCells]);
_this.onExpanderClick = function (ev) {
var props = _this.props;
_this.calendar.dispatch({
type: 'SET_RESOURCE_ENTITY_EXPANDED',
id: props.id,
isExpanded: !props.isExpanded
});
};
return _this;
}
GroupRow.prototype.render = function (props) {
this._renderCells(props.group, props.spreadsheetColCnt);
this._updateExpanderIcon(props.isExpanded);
this.isSizeDirty = true;
};
GroupRow.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this._renderCells.unrender(); // should unrender everything else
};
GroupRow.prototype.renderCells = function (group, spreadsheetColCnt) {
var spreadsheetContentEl = this.renderSpreadsheetContent(group);
this.spreadsheetTr.appendChild(core.createElement('td', {
className: 'fc-divider',
colSpan: spreadsheetColCnt // span across all columns
}, this.spreadsheetHeightEl = core.createElement('div', null, spreadsheetContentEl)) // needed by setTrInnerHeight
);
this.expanderIconEl = spreadsheetContentEl.querySelector('.fc-icon');
this.expanderIconEl.parentElement.addEventListener('click', this.onExpanderClick);
// insert a single cell, with a single empty <div>.
// there will be no content
this.timeAxisTr.appendChild(core.createElement('td', { className: 'fc-divider' }, this.timeAxisHeightEl = document.createElement('div')));
};
GroupRow.prototype.unrenderCells = function () {
this.spreadsheetTr.innerHTML = '';
this.timeAxisTr.innerHTML = '';
};
/*
Renders the content wrapper element that will be inserted into this row's TD cell.
*/
GroupRow.prototype.renderSpreadsheetContent = function (group) {
var text = this.renderCellText(group);
var contentEl = core.htmlToElement('<div class="fc-cell-content">' +
'<span class="fc-expander">' +
'<span class="fc-icon"></span>' +
'</span>' +
'<span class="fc-cell-text">' +
(text ? core.htmlEscape(text) : '&nbsp;') +
'</span>' +
'</div>');
var filter = group.spec.render;
if (typeof filter === 'function') {
contentEl = filter(contentEl, group.value) || contentEl;
}
return contentEl;
};
GroupRow.prototype.renderCellText = function (group) {
var text = group.value || ''; // might be null/undefined if an ad-hoc grouping
var filter = group.spec.text;
if (typeof filter === 'function') {
text = filter(text) || text;
}
return text;
};
GroupRow.prototype.getHeightEls = function () {
return [this.spreadsheetHeightEl, this.timeAxisHeightEl];
};
GroupRow.prototype.updateExpanderIcon = function (isExpanded) {
updateExpanderIcon(this.expanderIconEl, isExpanded);
};
return GroupRow;
}(Row));
GroupRow.addEqualityFuncs({
group: ResourceCommonPlugin.isGroupsEqual // HACK for ResourceTimelineView::renderRows
});
var SpreadsheetRow = /** @class */ (function (_super) {
__extends(SpreadsheetRow, _super);
function SpreadsheetRow(context, tr) {
var _this = _super.call(this, context) || this;
_this._renderRow = core.memoizeRendering(_this.renderRow, _this.unrenderRow);
_this._updateTrResourceId = core.memoizeRendering(updateTrResourceId, null, [_this._renderRow]);
_this._updateExpanderIcon = core.memoizeRendering(_this.updateExpanderIcon, null, [_this._renderRow]);
_this.onExpanderClick = function (ev) {
var props = _this.props;
_this.calendar.dispatch({
type: 'SET_RESOURCE_ENTITY_EXPANDED',
id: props.id,
isExpanded: !props.isExpanded
});
};
_this.tr = tr;
return _this;
}
SpreadsheetRow.prototype.render = function (props) {
this._renderRow(props.resource, props.rowSpans, props.depth, props.colSpecs);
this._updateTrResourceId(this.tr, props.resource.id); // TODO: only use public ID?
this._updateExpanderIcon(props.hasChildren, props.isExpanded);
};
SpreadsheetRow.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this._renderRow.unrender(); // should unrender everything else
};
SpreadsheetRow.prototype.renderRow = function (resource, rowSpans, depth, colSpecs) {
var _a = this, tr = _a.tr, theme = _a.theme, calendar = _a.calendar, view = _a.view;
var resourceFields = ResourceCommonPlugin.buildResourceFields(resource); // slightly inefficient. already done up the call stack
var mainTd;
for (var i = 0; i < colSpecs.length; i++) {
var colSpec = colSpecs[i];
var rowSpan = rowSpans[i];
if (rowSpan === 0) { // not responsible for group-based rows. VRowGroup is
continue;
}
else if (rowSpan == null) {
rowSpan = 1;
}
var text = void 0;
if (colSpec.field) {
text = resourceFields[colSpec.field];
}
else {
text = ResourceCommonPlugin.buildResourceTextFunc(colSpec.text, calendar)(resource);
}
var contentEl = core.htmlToElement('<div class="fc-cell-content">' +
(colSpec.isMain ? renderIconHtml(depth) : '') +
'<span class="fc-cell-text">' +
(text ? core.htmlEscape(text) : '&nbsp;') +
'</span>' +
'</div>');
if (typeof colSpec.render === 'function') { // a filter function for the element
contentEl = colSpec.render(new ResourceCommonPlugin.ResourceApi(calendar, resource), contentEl) || contentEl;
}
if (rowSpan > 1) {
contentEl.classList.add('fc-sticky');
}
var td = core.createElement('td', {
className: theme.getClass('widgetContent'),
rowspan: rowSpan
}, contentEl);
// the first cell of the row needs to have an inner div for setTrInnerHeight
if (colSpec.isMain) {
td.appendChild(this.heightEl = core.createElement('div', null, td.childNodes) // inner wrap
);
mainTd = td;
}
tr.appendChild(td);
}
this.expanderIconEl = tr.querySelector('.fc-expander-space .fc-icon');
// wait until very end
view.publiclyTrigger('resourceRender', [
{
resource: new ResourceCommonPlugin.ResourceApi(calendar, resource),
el: mainTd,
view: view
}
]);
};
SpreadsheetRow.prototype.unrenderRow = function () {
this.tr.innerHTML = '';
};
SpreadsheetRow.prototype.updateExpanderIcon = function (hasChildren, isExpanded) {
var expanderIconEl = this.expanderIconEl;
var expanderEl = expanderIconEl.parentElement;
if (expanderIconEl &&
expanderEl // why would this be null?? was the case in IE11
) {
if (hasChildren) {
expanderEl.addEventListener('click', this.onExpanderClick);
expanderEl.classList.add('fc-expander');
updateExpanderIcon(expanderIconEl, isExpanded);
}
else {
expanderEl.removeEventListener('click', this.onExpanderClick);
expanderEl.classList.remove('fc-expander');
clearExpanderIcon(expanderIconEl);
}
}
};
return SpreadsheetRow;
}(core.Component));
/*
Renders the HTML responsible for the subrow expander area,
as well as the space before it (used to align expanders of similar depths)
*/
function renderIconHtml(depth) {
var html = '';
for (var i = 0; i < depth; i++) {
html += '<span class="fc-icon"></span>';
}
html +=
'<span class="fc-expander-space">' +
'<span class="fc-icon"></span>' +
'</span>';
return html;
}
var ResourceRow = /** @class */ (function (_super) {
__extends(ResourceRow, _super);
function ResourceRow(context, a, b, c, d, timeAxis) {
var _this = _super.call(this, context, a, b, c, d) || this;
_this._updateTrResourceId = core.memoizeRendering(updateTrResourceId);
_this.spreadsheetRow = new SpreadsheetRow(context, _this.spreadsheetTr);
_this.timeAxisTr.appendChild(core.createElement('td', { className: _this.theme.getClass('widgetContent') }, _this.innerContainerEl = document.createElement('div')));
_this.lane = new TimelinePlugin.TimelineLane(context, _this.innerContainerEl, _this.innerContainerEl, timeAxis);
return _this;
}
ResourceRow.prototype.destroy = function () {
this.spreadsheetRow.destroy();
this.lane.destroy();
_super.prototype.destroy.call(this);
};
ResourceRow.prototype.render = function (props) {
// spreadsheetRow handles calling updateTrResourceId for spreadsheetTr
this.spreadsheetRow.receiveProps({
colSpecs: props.colSpecs,
id: props.id,
rowSpans: props.rowSpans,
depth: props.depth,
isExpanded: props.isExpanded,
hasChildren: props.hasChildren,
resource: props.resource
});
this._updateTrResourceId(this.timeAxisTr, props.resource.id);
this.lane.receiveProps({
dateProfile: props.dateProfile,
nextDayThreshold: props.nextDayThreshold,
businessHours: props.businessHours,
eventStore: props.eventStore,
eventUiBases: props.eventUiBases,
dateSelection: props.dateSelection,
eventSelection: props.eventSelection,
eventDrag: props.eventDrag,
eventResize: props.eventResize
});
this.isSizeDirty = true;
};
ResourceRow.prototype.updateSize = function (isResize) {
_super.prototype.updateSize.call(this, isResize);
this.lane.updateSize(isResize);
};
ResourceRow.prototype.getHeightEls = function () {
return [this.spreadsheetRow.heightEl, this.innerContainerEl];
};
return ResourceRow;
}(Row));
ResourceRow.addEqualityFuncs({
rowSpans: core.isArraysEqual // HACK for isSizeDirty, ResourceTimelineView::renderRows
});
var COL_MIN_WIDTH = 30;
var SpreadsheetHeader = /** @class */ (function (_super) {
__extends(SpreadsheetHeader, _super);
function SpreadsheetHeader(context, parentEl) {
var _this = _super.call(this, context) || this;
_this.resizables = [];
_this.colWidths = [];
_this.emitter = new core.EmitterMixin();
parentEl.appendChild(_this.tableEl = core.createElement('table', {
className: _this.theme.getClass('tableGrid')
}));
return _this;
}
SpreadsheetHeader.prototype.destroy = function () {
for (var _i = 0, _a = this.resizables; _i < _a.length; _i++) {
var resizable = _a[_i];
resizable.destroy();
}
core.removeElement(this.tableEl);
_super.prototype.destroy.call(this);
};
SpreadsheetHeader.prototype.render = function (props) {
var theme = this.theme;
var colSpecs = props.colSpecs;
var html = '<colgroup>' + props.colTags + '</colgroup>' +
'<tbody>';
if (props.superHeaderText) {
html +=
'<tr class="fc-super">' +
'<th class="' + theme.getClass('widgetHeader') + '" colspan="' + colSpecs.length + '">' +
'<div class="fc-cell-content">' +
'<span class="fc-cell-text">' +
core.htmlEscape(props.superHeaderText) +
'</span>' +
'</div>' +
'</th>' +
'</tr>';
}
html += '<tr>';
for (var i = 0; i < colSpecs.length; i++) {
var o = colSpecs[i];
var isLast = i === (colSpecs.length - 1);
html +=
"<th class=\"" + theme.getClass('widgetHeader') + "\">" +
'<div>' +
'<div class="fc-cell-content">' +
(o.isMain ?
'<span class="fc-expander-space">' +
'<span class="fc-icon"></span>' +
'</span>' :
'') +
'<span class="fc-cell-text">' +
core.htmlEscape(o.labelText || '') + // what about normalizing this value ahead of time?
'</span>' +
'</div>' +
(!isLast ? '<div class="fc-col-resizer"></div>' : '') +
'</div>' +
'</th>';
}
html += '</tr>';
html += '</tbody>';
this.tableEl.innerHTML = html;
this.thEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('th'));
this.colEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('col'));
this.resizerEls = Array.prototype.slice.call(this.tableEl.querySelectorAll('.fc-col-resizer'));
this.initColResizing();
};
SpreadsheetHeader.prototype.initColResizing = function () {
var _this = this;
var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl;
if (ElementDraggingImpl) {
this.resizables = this.resizerEls.map(function (handleEl, colIndex) {
var dragging = new ElementDraggingImpl(handleEl);
var startWidth;
dragging.emitter.on('dragstart', function () {
startWidth = _this.colWidths[colIndex];
if (typeof startWidth !== 'number') {
startWidth = _this.thEls[colIndex].getBoundingClientRect().width;
}
});
dragging.emitter.on('dragmove', function (pev) {
_this.colWidths[colIndex] = Math.max(startWidth + pev.deltaX * (_this.isRtl ? -1 : 1), COL_MIN_WIDTH);
_this.emitter.trigger('colwidthchange', _this.colWidths);
});
dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area
return dragging;
});
}
};
return SpreadsheetHeader;
}(core.Component));
var Spreadsheet = /** @class */ (function (_super) {
__extends(Spreadsheet, _super);
function Spreadsheet(context, headParentEl, bodyParentEl) {
var _this = _super.call(this, context) || this;
_this._renderCells = core.memoizeRendering(_this.renderCells, _this.unrenderCells);
_this.layout = new TimelinePlugin.HeaderBodyLayout(headParentEl, bodyParentEl, 'clipped-scroll');
var headerEnhancedScroller = _this.layout.headerScroller.enhancedScroll;
var bodyEnhancedScroller = _this.layout.bodyScroller.enhancedScroll;
_this.header = new SpreadsheetHeader(context, headerEnhancedScroller.canvas.contentEl);
_this.header.emitter.on('colwidthchange', function (colWidths) {
_this.applyColWidths(colWidths);
});
bodyEnhancedScroller.canvas.contentEl
.appendChild(_this.bodyContainerEl = core.createElement('div', { className: 'fc-rows' }, '<table>' +
'<colgroup />' +
'<tbody />' +
'</table>'));
_this.bodyColGroup = _this.bodyContainerEl.querySelector('colgroup');
_this.bodyTbody = _this.bodyContainerEl.querySelector('tbody');
return _this;
}
Spreadsheet.prototype.destroy = function () {
this.header.destroy();
this.layout.destroy();
this._renderCells.unrender();
_super.prototype.destroy.call(this);
};
Spreadsheet.prototype.render = function (props) {
this._renderCells(props.superHeaderText, props.colSpecs);
};
Spreadsheet.prototype.renderCells = function (superHeaderText, colSpecs) {
var colTags = this.renderColTags(colSpecs);
this.header.receiveProps({
superHeaderText: superHeaderText,
colSpecs: colSpecs,
colTags: colTags
});
this.bodyColGroup.innerHTML = colTags;
this.bodyColEls = Array.prototype.slice.call(this.bodyColGroup.querySelectorAll('col'));
this.applyColWidths(colSpecs.map(function (colSpec) { return colSpec.width; }));
};
Spreadsheet.prototype.unrenderCells = function () {
this.bodyColGroup.innerHTML = '';
};
Spreadsheet.prototype.renderColTags = function (colSpecs) {
var html = '';
for (var _i = 0, colSpecs_1 = colSpecs; _i < colSpecs_1.length; _i++) {
var o = colSpecs_1[_i];
if (o.isMain) {
html += '<col class="fc-main-col"/>';
}
else {
html += '<col/>';
}
}
return html;
};
Spreadsheet.prototype.updateSize = function (isResize, totalHeight, isAuto) {
this.layout.setHeight(totalHeight, isAuto);
};
Spreadsheet.prototype.applyColWidths = function (colWidths) {
var _this = this;
colWidths.forEach(function (colWidth, colIndex) {
var headEl = _this.header.colEls[colIndex]; // bad to access child
var bodyEl = _this.bodyColEls[colIndex];
var styleVal;
if (typeof colWidth === 'number') {
styleVal = colWidth + 'px';
}
else if (typeof colWidth == null) {
styleVal = '';
}
headEl.style.width = bodyEl.style.width = styleVal;
});
};
return Spreadsheet;
}(core.Component));
var MIN_RESOURCE_AREA_WIDTH = 30; // definitely bigger than scrollbars
var ResourceTimelineView = /** @class */ (function (_super) {
__extends(ResourceTimelineView, _super);
function ResourceTimelineView(context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.isStickyScrollDirty = false;
_this.rowNodes = [];
_this.rowComponents = [];
_this.rowComponentsById = {};
_this.resourceAreaWidthDraggings = [];
_this.splitter = new ResourceCommonPlugin.ResourceSplitter(); // doesn't let it do businessHours tho
_this.hasResourceBusinessHours = core.memoize(hasResourceBusinessHours);
_this.buildRowNodes = core.memoize(ResourceCommonPlugin.buildRowNodes);
_this.hasNesting = core.memoize(hasNesting);
_this._updateHasNesting = core.memoizeRendering(_this.updateHasNesting);
var allColSpecs = _this.opt('resourceColumns') || [];
var labelText = _this.opt('resourceLabelText'); // TODO: view.override
var defaultLabelText = 'Resources'; // TODO: view.defaults
var superHeaderText = null;
if (!allColSpecs.length) {
allColSpecs.push({
labelText: labelText || defaultLabelText,
text: ResourceCommonPlugin.buildResourceTextFunc(_this.opt('resourceText'), _this.calendar)
});
}
else {
superHeaderText = labelText;
}
var plainColSpecs = [];
var groupColSpecs = [];
var groupSpecs = [];
var isVGrouping = false;
var isHGrouping = false;
for (var _i = 0, allColSpecs_1 = allColSpecs; _i < allColSpecs_1.length; _i++) {
var colSpec = allColSpecs_1[_i];
if (colSpec.group) {
groupColSpecs.push(colSpec);
}
else {
plainColSpecs.push(colSpec);
}
}
plainColSpecs[0].isMain = true;
if (groupColSpecs.length) {
groupSpecs = groupColSpecs;
isVGrouping = true;
}
else {
var hGroupField = _this.opt('resourceGroupField');
if (hGroupField) {
isHGrouping = true;
groupSpecs.push({
field: hGroupField,
text: _this.opt('resourceGroupText'),
render: _this.opt('resourceGroupRender')
});
}
}
var allOrderSpecs = core.parseFieldSpecs(_this.opt('resourceOrder'));
var plainOrderSpecs = [];
for (var _a = 0, allOrderSpecs_1 = allOrderSpecs; _a < allOrderSpecs_1.length; _a++) {
var orderSpec = allOrderSpecs_1[_a];
var isGroup = false;
for (var _b = 0, groupSpecs_1 = groupSpecs; _b < groupSpecs_1.length; _b++) {
var groupSpec = groupSpecs_1[_b];
if (groupSpec.field === orderSpec.field) {
groupSpec.order = orderSpec.order; // -1, 0, 1
isGroup = true;
break;
}
}
if (!isGroup) {
plainOrderSpecs.push(orderSpec);
}
}
_this.superHeaderText = superHeaderText;
_this.isVGrouping = isVGrouping;
_this.isHGrouping = isHGrouping;
_this.groupSpecs = groupSpecs;
_this.colSpecs = groupColSpecs.concat(plainColSpecs);
_this.orderSpecs = plainOrderSpecs;
// START RENDERING...
_this.el.classList.add('fc-timeline');
if (_this.opt('eventOverlap') === false) {
_this.el.classList.add('fc-no-overlap');
}
_this.el.innerHTML = _this.renderSkeletonHtml();
_this.resourceAreaHeadEl = _this.el.querySelector('thead .fc-resource-area');
_this.setResourceAreaWidth(_this.opt('resourceAreaWidth'));
_this.initResourceAreaWidthDragging();
_this.miscHeight = _this.el.getBoundingClientRect().height;
_this.spreadsheet = new Spreadsheet(_this.context, _this.resourceAreaHeadEl, _this.el.querySelector('tbody .fc-resource-area'));
_this.timeAxis = new TimelinePlugin.TimeAxis(_this.context, _this.el.querySelector('thead .fc-time-area'), _this.el.querySelector('tbody .fc-time-area'));
var timeAxisRowContainer = core.createElement('div', { className: 'fc-rows' }, '<table><tbody /></table>');
_this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl.appendChild(timeAxisRowContainer);
_this.timeAxisTbody = timeAxisRowContainer.querySelector('tbody');
_this.lane = new TimelinePlugin.TimelineLane(_this.context, null, _this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl, _this.timeAxis);
_this.bodyScrollJoiner = new TimelinePlugin.ScrollJoiner('vertical', [
_this.spreadsheet.layout.bodyScroller,
_this.timeAxis.layout.bodyScroller
]);
// after scrolljoiner
_this.spreadsheetBodyStickyScroller = new TimelinePlugin.StickyScroller(_this.spreadsheet.layout.bodyScroller.enhancedScroll, _this.isRtl, true // isVertical
);
_this.spreadsheet.receiveProps({
superHeaderText: _this.superHeaderText,
colSpecs: _this.colSpecs
});
// Component...
context.calendar.registerInteractiveComponent(_this, {
el: _this.timeAxis.slats.el
});
return _this;
}
ResourceTimelineView.prototype.renderSkeletonHtml = function () {
var theme = this.theme;
return "<table class=\"" + theme.getClass('tableGrid') + "\"> <thead class=\"fc-head\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetHeader') + "\"></td> </tr> </thead> <tbody class=\"fc-body\"> <tr> <td class=\"fc-resource-area " + theme.getClass('widgetContent') + "\"></td> <td class=\"fc-divider fc-col-resizer " + theme.getClass('widgetHeader') + "\"></td> <td class=\"fc-time-area " + theme.getClass('widgetContent') + "\"></td> </tr> </tbody> </table>";
};
ResourceTimelineView.prototype.render = function (props) {
_super.prototype.render.call(this, props);
var splitProps = this.splitter.splitProps(props);
var hasResourceBusinessHours = this.hasResourceBusinessHours(props.resourceStore);
this.timeAxis.receiveProps({
dateProfile: props.dateProfile
});
// for all-resource bg events / selections / business-hours
this.lane.receiveProps(__assign({}, splitProps[''], { dateProfile: props.dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: hasResourceBusinessHours ? null : props.businessHours }));
var newRowNodes = this.buildRowNodes(props.resourceStore, this.groupSpecs, this.orderSpecs, this.isVGrouping, props.resourceEntityExpansions, this.opt('resourcesInitiallyExpanded'));
this._updateHasNesting(this.hasNesting(newRowNodes));
this.diffRows(newRowNodes);
this.renderRows(props.dateProfile, hasResourceBusinessHours ? props.businessHours : null, // CONFUSING, comment
splitProps);
};
ResourceTimelineView.prototype.updateHasNesting = function (isNesting) {
var classList = this.el.classList;
if (isNesting) {
classList.remove('fc-flat');
}
else {
classList.add('fc-flat');
}
};
ResourceTimelineView.prototype.diffRows = function (newNodes) {
var oldNodes = this.rowNodes;
var oldLen = oldNodes.length;
var oldIndexHash = {}; // id -> index
var oldI = 0;
var newI = 0;
for (oldI = 0; oldI < oldLen; oldI++) {
oldIndexHash[oldNodes[oldI].id] = oldI;
}
// iterate new nodes
for (oldI = 0, newI = 0; newI < newNodes.length; newI++) {
var newNode = newNodes[newI];
var oldIFound = oldIndexHash[newNode.id];
if (oldIFound != null && oldIFound >= oldI) {
this.removeRows(newI, oldIFound - oldI, oldNodes); // won't do anything if same index
oldI = oldIFound + 1;
}
else {
this.addRow(newI, newNode);
}
}
// old rows that weren't found need to be removed
this.removeRows(newI, oldLen - oldI, oldNodes); // won't do anything if same index
this.rowNodes = newNodes;
};
/*
rowComponents is the in-progress result
*/
ResourceTimelineView.prototype.addRow = function (index, rowNode) {
var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById;
var nextComponent = rowComponents[index];
var newComponent = this.buildChildComponent(rowNode, this.spreadsheet.bodyTbody, nextComponent ? nextComponent.spreadsheetTr : null, this.timeAxisTbody, nextComponent ? nextComponent.timeAxisTr : null);
rowComponents.splice(index, 0, newComponent);
rowComponentsById[rowNode.id] = newComponent;
};
ResourceTimelineView.prototype.removeRows = function (startIndex, len, oldRowNodes) {
if (len) {
var _a = this, rowComponents = _a.rowComponents, rowComponentsById = _a.rowComponentsById;
for (var i = 0; i < len; i++) {
var rowComponent = rowComponents[startIndex + i];
rowComponent.destroy();
delete rowComponentsById[oldRowNodes[i].id];
}
rowComponents.splice(startIndex, len);
}
};
ResourceTimelineView.prototype.buildChildComponent = function (node, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext) {
if (node.group) {
return new GroupRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext);
}
else if (node.resource) {
return new ResourceRow(this.context, spreadsheetTbody, spreadsheetNext, timeAxisTbody, timeAxisNext, this.timeAxis);
}
};
ResourceTimelineView.prototype.renderRows = function (dateProfile, fallbackBusinessHours, splitProps) {
var _a = this, rowNodes = _a.rowNodes, rowComponents = _a.rowComponents;
for (var i = 0; i < rowNodes.length; i++) {
var rowNode = rowNodes[i];
var rowComponent = rowComponents[i];
if (rowNode.group) {
rowComponent.receiveProps({
spreadsheetColCnt: this.colSpecs.length,
id: rowNode.id,
isExpanded: rowNode.isExpanded,
group: rowNode.group
});
}
else {
var resource = rowNode.resource;
rowComponent.receiveProps(__assign({}, splitProps[resource.id], { dateProfile: dateProfile, nextDayThreshold: this.nextDayThreshold, businessHours: resource.businessHours || fallbackBusinessHours, colSpecs: this.colSpecs, id: rowNode.id, rowSpans: rowNode.rowSpans, depth: rowNode.depth, isExpanded: rowNode.isExpanded, hasChildren: rowNode.hasChildren, resource: rowNode.resource }));
}
}
};
ResourceTimelineView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
// FYI: this ordering is really important
var calendar = this.calendar;
var isBaseSizing = isResize || calendar.isViewUpdated || calendar.isDatesUpdated || calendar.isEventsUpdated;
if (isBaseSizing) {
this.syncHeadHeights();
this.timeAxis.updateSize(isResize, viewHeight - this.miscHeight, isAuto);
this.spreadsheet.updateSize(isResize, viewHeight - this.miscHeight, isAuto);
}
var rowSizingCnt = this.updateRowSizes(isResize);
this.lane.updateSize(isResize); // is efficient. uses flags
if (isBaseSizing || rowSizingCnt) {
this.bodyScrollJoiner.update();
this.timeAxis.layout.scrollJoiner.update(); // hack
this.rowPositions = new core.PositionCache(this.timeAxis.slats.el, this.rowComponents.map(function (rowComponent) {
return rowComponent.timeAxisTr;
}), false, // isHorizontal
true // isVertical
);
this.rowPositions.build();
this.isStickyScrollDirty = true;
}
};
ResourceTimelineView.prototype.syncHeadHeights = function () {
var spreadsheetHeadEl = this.spreadsheet.header.tableEl;
var timeAxisHeadEl = this.timeAxis.header.tableEl;
spreadsheetHeadEl.style.height = '';
timeAxisHeadEl.style.height = '';
var max = Math.max(spreadsheetHeadEl.getBoundingClientRect().height, timeAxisHeadEl.getBoundingClientRect().height);
spreadsheetHeadEl.style.height =
timeAxisHeadEl.style.height = max + 'px';
};
ResourceTimelineView.prototype.updateRowSizes = function (isResize) {
var dirtyRowComponents = this.rowComponents;
if (!isResize) {
dirtyRowComponents = dirtyRowComponents.filter(function (rowComponent) {
return rowComponent.isSizeDirty;
});
}
var elArrays = dirtyRowComponents.map(function (rowComponent) {
return rowComponent.getHeightEls();
});
// reset to natural heights
for (var _i = 0, elArrays_1 = elArrays; _i < elArrays_1.length; _i++) {
var elArray = elArrays_1[_i];
for (var _a = 0, elArray_1 = elArray; _a < elArray_1.length; _a++) {
var el = elArray_1[_a];
el.style.height = '';
}
}
// let rows update their contents' heights
for (var _b = 0, dirtyRowComponents_1 = dirtyRowComponents; _b < dirtyRowComponents_1.length; _b++) {
var rowComponent = dirtyRowComponents_1[_b];
rowComponent.updateSize(isResize); // will reset isSizeDirty
}
var maxHeights = elArrays.map(function (elArray) {
var maxHeight = null;
for (var _i = 0, elArray_2 = elArray; _i < elArray_2.length; _i++) {
var el = elArray_2[_i];
var height = el.getBoundingClientRect().height;
if (maxHeight === null || height > maxHeight) {
maxHeight = height;
}
}
return maxHeight;
});
for (var i = 0; i < elArrays.length; i++) {
for (var _c = 0, _d = elArrays[i]; _c < _d.length; _c++) {
var el = _d[_c];
el.style.height = maxHeights[i] + 'px';
}
}
return dirtyRowComponents.length;
};
ResourceTimelineView.prototype.destroy = function () {
for (var _i = 0, _a = this.rowComponents; _i < _a.length; _i++) {
var rowComponent = _a[_i];
rowComponent.destroy();
}
this.rowNodes = [];
this.rowComponents = [];
this.spreadsheet.destroy();
this.timeAxis.destroy();
for (var _b = 0, _c = this.resourceAreaWidthDraggings; _b < _c.length; _b++) {
var resourceAreaWidthDragging = _c[_b];
resourceAreaWidthDragging.destroy();
}
this.spreadsheetBodyStickyScroller.destroy();
_super.prototype.destroy.call(this);
this.calendar.unregisterInteractiveComponent(this);
};
// Now Indicator
// ------------------------------------------------------------------------------------------
ResourceTimelineView.prototype.getNowIndicatorUnit = function (dateProfile) {
return this.timeAxis.getNowIndicatorUnit(dateProfile);
};
ResourceTimelineView.prototype.renderNowIndicator = function (date) {
this.timeAxis.renderNowIndicator(date);
};
ResourceTimelineView.prototype.unrenderNowIndicator = function () {
this.timeAxis.unrenderNowIndicator();
};
// Scrolling
// ------------------------------------------------------------------------------------------------------------------
// this is useful for scrolling prev/next dates while resource is scrolled down
ResourceTimelineView.prototype.queryScroll = function () {
var scroll = _super.prototype.queryScroll.call(this);
if (this.props.resourceStore) {
__assign(scroll, this.queryResourceScroll());
}
return scroll;
};
ResourceTimelineView.prototype.applyScroll = function (scroll, isResize) {
_super.prototype.applyScroll.call(this, scroll, isResize);
if (this.props.resourceStore) {
this.applyResourceScroll(scroll);
}
// avoid updating stickyscroll too often
if (isResize || this.isStickyScrollDirty) {
this.isStickyScrollDirty = false;
this.spreadsheetBodyStickyScroller.updateSize();
this.timeAxis.updateStickyScrollers();
}
};
ResourceTimelineView.prototype.computeDateScroll = function (duration) {
return this.timeAxis.computeDateScroll(duration);
};
ResourceTimelineView.prototype.queryDateScroll = function () {
return this.timeAxis.queryDateScroll();
};
ResourceTimelineView.prototype.applyDateScroll = function (scroll) {
this.timeAxis.applyDateScroll(scroll);
};
ResourceTimelineView.prototype.queryResourceScroll = function () {
var _a = this, rowComponents = _a.rowComponents, rowNodes = _a.rowNodes;
var scroll = {};
var scrollerTop = this.timeAxis.layout.bodyScroller.el.getBoundingClientRect().top; // fixed position
for (var i = 0; i < rowComponents.length; i++) {
var rowComponent = rowComponents[i];
var rowNode = rowNodes[i];
var el = rowComponent.timeAxisTr;
var elBottom = el.getBoundingClientRect().bottom; // fixed position
if (elBottom > scrollerTop) {
scroll.rowId = rowNode.id;
scroll.bottom = elBottom - scrollerTop;
break;
}
}
// TODO: what about left scroll state for spreadsheet area?
return scroll;
};
ResourceTimelineView.prototype.applyResourceScroll = function (scroll) {
var rowId = scroll.forcedRowId || scroll.rowId;
if (rowId) {
var rowComponent = this.rowComponentsById[rowId];
if (rowComponent) {
var el = rowComponent.timeAxisTr;
if (el) {
var innerTop = this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.el.getBoundingClientRect().top;
var rowRect = el.getBoundingClientRect();
var scrollTop = (scroll.forcedRowId ?
rowRect.top : // just use top edge
rowRect.bottom - scroll.bottom) - // pixels from bottom edge
innerTop;
this.timeAxis.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop);
this.spreadsheet.layout.bodyScroller.enhancedScroll.setScrollTop(scrollTop);
}
}
}
};
// TODO: scrollToResource
// Hit System
// ------------------------------------------------------------------------------------------
ResourceTimelineView.prototype.buildPositionCaches = function () {
this.timeAxis.slats.updateSize();
this.rowPositions.build();
};
ResourceTimelineView.prototype.queryHit = function (positionLeft, positionTop) {
var rowPositions = this.rowPositions;
var slats = this.timeAxis.slats;
var rowIndex = rowPositions.topToIndex(positionTop);
if (rowIndex != null) {
var resource = this.rowNodes[rowIndex].resource;
if (resource) { // not a group
var slatHit = slats.positionToHit(positionLeft);
if (slatHit) {
return {
component: this,
dateSpan: {
range: slatHit.dateSpan.range,
allDay: slatHit.dateSpan.allDay,
resourceId: resource.id
},
rect: {
left: slatHit.left,
right: slatHit.right,
top: rowPositions.tops[rowIndex],
bottom: rowPositions.bottoms[rowIndex]
},
dayEl: slatHit.dayEl,
layer: 0
};
}
}
}
};
// Resource Area
// ------------------------------------------------------------------------------------------------------------------
ResourceTimelineView.prototype.setResourceAreaWidth = function (widthVal) {
this.resourceAreaWidth = widthVal;
core.applyStyleProp(this.resourceAreaHeadEl, 'width', widthVal || '');
};
ResourceTimelineView.prototype.initResourceAreaWidthDragging = function () {
var _this = this;
var resourceAreaDividerEls = Array.prototype.slice.call(this.el.querySelectorAll('.fc-col-resizer'));
var ElementDraggingImpl = this.calendar.pluginSystem.hooks.elementDraggingImpl;
if (ElementDraggingImpl) {
this.resourceAreaWidthDraggings = resourceAreaDividerEls.map(function (el) {
var dragging = new ElementDraggingImpl(el);
var dragStartWidth;
var viewWidth;
dragging.emitter.on('dragstart', function () {
dragStartWidth = _this.resourceAreaWidth;
if (typeof dragStartWidth !== 'number') {
dragStartWidth = _this.resourceAreaHeadEl.getBoundingClientRect().width;
}
viewWidth = _this.el.getBoundingClientRect().width;
});
dragging.emitter.on('dragmove', function (pev) {
var newWidth = dragStartWidth + pev.deltaX * (_this.isRtl ? -1 : 1);
newWidth = Math.max(newWidth, MIN_RESOURCE_AREA_WIDTH);
newWidth = Math.min(newWidth, viewWidth - MIN_RESOURCE_AREA_WIDTH);
_this.setResourceAreaWidth(newWidth);
});
dragging.setAutoScrollEnabled(false); // because gets weird with auto-scrolling time area
return dragging;
});
}
};
ResourceTimelineView.needsResourceData = true; // for ResourceViewProps
return ResourceTimelineView;
}(core.View));
function hasResourceBusinessHours(resourceStore) {
for (var resourceId in resourceStore) {
var resource = resourceStore[resourceId];
if (resource.businessHours) {
return true;
}
}
return false;
}
function hasNesting(nodes) {
for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
var node = nodes_1[_i];
if (node.group) {
return true;
}
else if (node.resource) {
if (node.hasChildren) {
return true;
}
}
}
return false;
}
var main = core.createPlugin({
deps: [ResourceCommonPlugin__default, TimelinePlugin__default],
defaultView: 'resourceTimelineDay',
views: {
resourceTimeline: {
class: ResourceTimelineView,
resourceAreaWidth: '30%',
resourcesInitiallyExpanded: true,
eventResizableFromStart: true // TODO: not DRY with this same setting in the main timeline config
},
resourceTimelineDay: {
type: 'resourceTimeline',
duration: { days: 1 }
},
resourceTimelineWeek: {
type: 'resourceTimeline',
duration: { weeks: 1 }
},
resourceTimelineMonth: {
type: 'resourceTimeline',
duration: { months: 1 }
},
resourceTimelineYear: {
type: 'resourceTimeline',
duration: { years: 1 }
}
}
});
exports.ResourceTimelineView = ResourceTimelineView;
exports.default = main;
Object.defineProperty(exports, '__esModule', { value: true });
}));
.fc-timeline .fc-divider{width:3px;border-style:double}.fc-timeline .fc-head>tr>.fc-divider{border-bottom:0}.fc-timeline .fc-body>tr>.fc-divider{border-top:0}.fc-resource-area{width:30%}.fc-resource-area col{width:40%;min-width:70px}.fc-resource-area col.fc-main-col{width:60%}.fc-flat .fc-expander-space{display:none}.fc-ltr .fc-resource-area tr>*{text-align:left}.fc-rtl .fc-resource-area tr>*{text-align:right}.fc-resource-area .fc-cell-content{padding-left:4px;padding-right:4px}.fc-resource-area .fc-super th{text-align:center}.fc-resource-area th>div{position:relative}.fc-resource-area th .fc-cell-content{position:relative;z-index:1}.fc-resource-area th .fc-col-resizer{position:absolute;z-index:2;top:0;bottom:0;width:5px}.fc-timeline .fc-col-resizer{cursor:col-resize}.fc-ltr .fc-resource-area th .fc-col-resizer{right:-3px}.fc-rtl .fc-resource-area th .fc-col-resizer{left:-3px}.fc-body .fc-resource-area .fc-cell-content{padding-top:8px;padding-bottom:8px}.fc-no-overlap .fc-body .fc-resource-area .fc-cell-content{padding-top:6px;padding-bottom:6px}.fc-resource-area .fc-icon{display:inline-block;width:1em;text-align:center}.fc-resource-area .fc-expander{cursor:pointer;opacity:.65}.fc-time-area .fc-rows{position:relative;z-index:3}.fc-time-area .fc-rows td>div{position:relative}.fc-time-area .fc-rows .fc-bgevent-container,.fc-time-area .fc-rows .fc-highlight-container{z-index:1}
\ No newline at end of file
/*!
FullCalendar Resource 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"),require("@fullcalendar/timeline"),require("@fullcalendar/resource-common")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core","@fullcalendar/timeline","@fullcalendar/resource-common"],t):t((e=e||self).FullCalendarResourceTimeline={},e.FullCalendar,e.FullCalendarTimeline,e.FullCalendarResourceCommon)}(this,function(e,t,r,o){"use strict";var i="default"in r?r.default:r,s="default"in o?o.default:o,n=function(e,t){return(n=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 l(e,t){function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var a=function(){return(a=Object.assign||function(e){for(var t,r=1,o=arguments.length;r<o;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},c=function(e){function r(t,r,o,i,s){var n=e.call(this,t)||this;return n.isSizeDirty=!1,r.insertBefore(n.spreadsheetTr=document.createElement("tr"),o),i.insertBefore(n.timeAxisTr=document.createElement("tr"),s),n}return l(r,e),r.prototype.destroy=function(){t.removeElement(this.spreadsheetTr),t.removeElement(this.timeAxisTr),e.prototype.destroy.call(this)},r.prototype.updateSize=function(e){this.isSizeDirty=!1},r}(t.Component);function d(e,t){var r=e.classList;t?(r.remove("fc-icon-plus-square"),r.add("fc-icon-minus-square")):(r.remove("fc-icon-minus-square"),r.add("fc-icon-plus-square"))}function p(e,t){e.setAttribute("data-resource-id",t)}var u=function(e){function r(){var r=null!==e&&e.apply(this,arguments)||this;return r._renderCells=t.memoizeRendering(r.renderCells,r.unrenderCells),r._updateExpanderIcon=t.memoizeRendering(r.updateExpanderIcon,null,[r._renderCells]),r.onExpanderClick=function(e){var t=r.props;r.calendar.dispatch({type:"SET_RESOURCE_ENTITY_EXPANDED",id:t.id,isExpanded:!t.isExpanded})},r}return l(r,e),r.prototype.render=function(e){this._renderCells(e.group,e.spreadsheetColCnt),this._updateExpanderIcon(e.isExpanded),this.isSizeDirty=!0},r.prototype.destroy=function(){e.prototype.destroy.call(this),this._renderCells.unrender()},r.prototype.renderCells=function(e,r){var o=this.renderSpreadsheetContent(e);this.spreadsheetTr.appendChild(t.createElement("td",{className:"fc-divider",colSpan:r},this.spreadsheetHeightEl=t.createElement("div",null,o))),this.expanderIconEl=o.querySelector(".fc-icon"),this.expanderIconEl.parentElement.addEventListener("click",this.onExpanderClick),this.timeAxisTr.appendChild(t.createElement("td",{className:"fc-divider"},this.timeAxisHeightEl=document.createElement("div")))},r.prototype.unrenderCells=function(){this.spreadsheetTr.innerHTML="",this.timeAxisTr.innerHTML=""},r.prototype.renderSpreadsheetContent=function(e){var r=this.renderCellText(e),o=t.htmlToElement('<div class="fc-cell-content"><span class="fc-expander"><span class="fc-icon"></span></span><span class="fc-cell-text">'+(r?t.htmlEscape(r):"&nbsp;")+"</span></div>"),i=e.spec.render;return"function"==typeof i&&(o=i(o,e.value)||o),o},r.prototype.renderCellText=function(e){var t=e.value||"",r=e.spec.text;return"function"==typeof r&&(t=r(t)||t),t},r.prototype.getHeightEls=function(){return[this.spreadsheetHeightEl,this.timeAxisHeightEl]},r.prototype.updateExpanderIcon=function(e){d(this.expanderIconEl,e)},r}(c);u.addEqualityFuncs({group:o.isGroupsEqual});var h=function(e){function r(r,o){var i=e.call(this,r)||this;return i._renderRow=t.memoizeRendering(i.renderRow,i.unrenderRow),i._updateTrResourceId=t.memoizeRendering(p,null,[i._renderRow]),i._updateExpanderIcon=t.memoizeRendering(i.updateExpanderIcon,null,[i._renderRow]),i.onExpanderClick=function(e){var t=i.props;i.calendar.dispatch({type:"SET_RESOURCE_ENTITY_EXPANDED",id:t.id,isExpanded:!t.isExpanded})},i.tr=o,i}return l(r,e),r.prototype.render=function(e){this._renderRow(e.resource,e.rowSpans,e.depth,e.colSpecs),this._updateTrResourceId(this.tr,e.resource.id),this._updateExpanderIcon(e.hasChildren,e.isExpanded)},r.prototype.destroy=function(){e.prototype.destroy.call(this),this._renderRow.unrender()},r.prototype.renderRow=function(e,r,i,s){for(var n,l=this.tr,a=this.theme,c=this.calendar,d=this.view,p=o.buildResourceFields(e),u=0;u<s.length;u++){var h=s[u],f=r[u];if(0!==f){null==f&&(f=1);var m=void 0;m=h.field?p[h.field]:o.buildResourceTextFunc(h.text,c)(e);var g=t.htmlToElement('<div class="fc-cell-content">'+(h.isMain?y(i):"")+'<span class="fc-cell-text">'+(m?t.htmlEscape(m):"&nbsp;")+"</span></div>");"function"==typeof h.render&&(g=h.render(new o.ResourceApi(c,e),g)||g),f>1&&g.classList.add("fc-sticky");var v=t.createElement("td",{className:a.getClass("widgetContent"),rowspan:f},g);h.isMain&&(v.appendChild(this.heightEl=t.createElement("div",null,v.childNodes)),n=v),l.appendChild(v)}}this.expanderIconEl=l.querySelector(".fc-expander-space .fc-icon"),d.publiclyTrigger("resourceRender",[{resource:new o.ResourceApi(c,e),el:n,view:d}])},r.prototype.unrenderRow=function(){this.tr.innerHTML=""},r.prototype.updateExpanderIcon=function(e,t){var r,o=this.expanderIconEl,i=o.parentElement;o&&i&&(e?(i.addEventListener("click",this.onExpanderClick),i.classList.add("fc-expander"),d(o,t)):(i.removeEventListener("click",this.onExpanderClick),i.classList.remove("fc-expander"),(r=o.classList).remove("fc-icon-minus-square"),r.remove("fc-icon-plus-square")))},r}(t.Component);function y(e){for(var t="",r=0;r<e;r++)t+='<span class="fc-icon"></span>';return t+='<span class="fc-expander-space"><span class="fc-icon"></span></span>'}var f=function(e){function o(o,i,s,n,l,a){var c=e.call(this,o,i,s,n,l)||this;return c._updateTrResourceId=t.memoizeRendering(p),c.spreadsheetRow=new h(o,c.spreadsheetTr),c.timeAxisTr.appendChild(t.createElement("td",{className:c.theme.getClass("widgetContent")},c.innerContainerEl=document.createElement("div"))),c.lane=new r.TimelineLane(o,c.innerContainerEl,c.innerContainerEl,a),c}return l(o,e),o.prototype.destroy=function(){this.spreadsheetRow.destroy(),this.lane.destroy(),e.prototype.destroy.call(this)},o.prototype.render=function(e){this.spreadsheetRow.receiveProps({colSpecs:e.colSpecs,id:e.id,rowSpans:e.rowSpans,depth:e.depth,isExpanded:e.isExpanded,hasChildren:e.hasChildren,resource:e.resource}),this._updateTrResourceId(this.timeAxisTr,e.resource.id),this.lane.receiveProps({dateProfile:e.dateProfile,nextDayThreshold:e.nextDayThreshold,businessHours:e.businessHours,eventStore:e.eventStore,eventUiBases:e.eventUiBases,dateSelection:e.dateSelection,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize}),this.isSizeDirty=!0},o.prototype.updateSize=function(t){e.prototype.updateSize.call(this,t),this.lane.updateSize(t)},o.prototype.getHeightEls=function(){return[this.spreadsheetRow.heightEl,this.innerContainerEl]},o}(c);f.addEqualityFuncs({rowSpans:t.isArraysEqual});var m=function(e){function r(r,o){var i=e.call(this,r)||this;return i.resizables=[],i.colWidths=[],i.emitter=new t.EmitterMixin,o.appendChild(i.tableEl=t.createElement("table",{className:i.theme.getClass("tableGrid")})),i}return l(r,e),r.prototype.destroy=function(){for(var r=0,o=this.resizables;r<o.length;r++){o[r].destroy()}t.removeElement(this.tableEl),e.prototype.destroy.call(this)},r.prototype.render=function(e){var r=this.theme,o=e.colSpecs,i="<colgroup>"+e.colTags+"</colgroup><tbody>";e.superHeaderText&&(i+='<tr class="fc-super"><th class="'+r.getClass("widgetHeader")+'" colspan="'+o.length+'"><div class="fc-cell-content"><span class="fc-cell-text">'+t.htmlEscape(e.superHeaderText)+"</span></div></th></tr>"),i+="<tr>";for(var s=0;s<o.length;s++){var n=o[s],l=s===o.length-1;i+='<th class="'+r.getClass("widgetHeader")+'"><div><div class="fc-cell-content">'+(n.isMain?'<span class="fc-expander-space"><span class="fc-icon"></span></span>':"")+'<span class="fc-cell-text">'+t.htmlEscape(n.labelText||"")+"</span></div>"+(l?"":'<div class="fc-col-resizer"></div>')+"</div></th>"}i+="</tr>",i+="</tbody>",this.tableEl.innerHTML=i,this.thEls=Array.prototype.slice.call(this.tableEl.querySelectorAll("th")),this.colEls=Array.prototype.slice.call(this.tableEl.querySelectorAll("col")),this.resizerEls=Array.prototype.slice.call(this.tableEl.querySelectorAll(".fc-col-resizer")),this.initColResizing()},r.prototype.initColResizing=function(){var e=this,t=this.calendar.pluginSystem.hooks.elementDraggingImpl;t&&(this.resizables=this.resizerEls.map(function(r,o){var i,s=new t(r);return s.emitter.on("dragstart",function(){"number"!=typeof(i=e.colWidths[o])&&(i=e.thEls[o].getBoundingClientRect().width)}),s.emitter.on("dragmove",function(t){e.colWidths[o]=Math.max(i+t.deltaX*(e.isRtl?-1:1),30),e.emitter.trigger("colwidthchange",e.colWidths)}),s.setAutoScrollEnabled(!1),s}))},r}(t.Component),g=function(e){function o(o,i,s){var n=e.call(this,o)||this;n._renderCells=t.memoizeRendering(n.renderCells,n.unrenderCells),n.layout=new r.HeaderBodyLayout(i,s,"clipped-scroll");var l=n.layout.headerScroller.enhancedScroll,a=n.layout.bodyScroller.enhancedScroll;return n.header=new m(o,l.canvas.contentEl),n.header.emitter.on("colwidthchange",function(e){n.applyColWidths(e)}),a.canvas.contentEl.appendChild(n.bodyContainerEl=t.createElement("div",{className:"fc-rows"},"<table><colgroup /><tbody /></table>")),n.bodyColGroup=n.bodyContainerEl.querySelector("colgroup"),n.bodyTbody=n.bodyContainerEl.querySelector("tbody"),n}return l(o,e),o.prototype.destroy=function(){this.header.destroy(),this.layout.destroy(),this._renderCells.unrender(),e.prototype.destroy.call(this)},o.prototype.render=function(e){this._renderCells(e.superHeaderText,e.colSpecs)},o.prototype.renderCells=function(e,t){var r=this.renderColTags(t);this.header.receiveProps({superHeaderText:e,colSpecs:t,colTags:r}),this.bodyColGroup.innerHTML=r,this.bodyColEls=Array.prototype.slice.call(this.bodyColGroup.querySelectorAll("col")),this.applyColWidths(t.map(function(e){return e.width}))},o.prototype.unrenderCells=function(){this.bodyColGroup.innerHTML=""},o.prototype.renderColTags=function(e){for(var t="",r=0,o=e;r<o.length;r++){o[r].isMain?t+='<col class="fc-main-col"/>':t+="<col/>"}return t},o.prototype.updateSize=function(e,t,r){this.layout.setHeight(t,r)},o.prototype.applyColWidths=function(e){var t=this;e.forEach(function(e,r){var o,i=t.header.colEls[r],s=t.bodyColEls[r];"number"==typeof e?o=e+"px":null==typeof e&&(o=""),i.style.width=s.style.width=o})},o}(t.Component),v=function(e){function i(i,s,n,l){var a=e.call(this,i,s,n,l)||this;a.isStickyScrollDirty=!1,a.rowNodes=[],a.rowComponents=[],a.rowComponentsById={},a.resourceAreaWidthDraggings=[],a.splitter=new o.ResourceSplitter,a.hasResourceBusinessHours=t.memoize(S),a.buildRowNodes=t.memoize(o.buildRowNodes),a.hasNesting=t.memoize(x),a._updateHasNesting=t.memoizeRendering(a.updateHasNesting);var c=a.opt("resourceColumns")||[],d=a.opt("resourceLabelText"),p=null;c.length?p=d:c.push({labelText:d||"Resources",text:o.buildResourceTextFunc(a.opt("resourceText"),a.calendar)});for(var u=[],h=[],y=[],f=!1,m=!1,v=0,E=c;v<E.length;v++){var C=E[v];C.group?h.push(C):u.push(C)}if(u[0].isMain=!0,h.length)y=h,f=!0;else{var w=a.opt("resourceGroupField");w&&(m=!0,y.push({field:w,text:a.opt("resourceGroupText"),render:a.opt("resourceGroupRender")}))}for(var b=[],R=0,T=t.parseFieldSpecs(a.opt("resourceOrder"));R<T.length;R++){for(var A=T[R],H=!1,z=0,I=y;z<I.length;z++){var D=I[z];if(D.field===A.field){D.order=A.order,H=!0;break}}H||b.push(A)}a.superHeaderText=p,a.isVGrouping=f,a.isHGrouping=m,a.groupSpecs=y,a.colSpecs=h.concat(u),a.orderSpecs=b,a.el.classList.add("fc-timeline"),!1===a.opt("eventOverlap")&&a.el.classList.add("fc-no-overlap"),a.el.innerHTML=a.renderSkeletonHtml(),a.resourceAreaHeadEl=a.el.querySelector("thead .fc-resource-area"),a.setResourceAreaWidth(a.opt("resourceAreaWidth")),a.initResourceAreaWidthDragging(),a.miscHeight=a.el.getBoundingClientRect().height,a.spreadsheet=new g(a.context,a.resourceAreaHeadEl,a.el.querySelector("tbody .fc-resource-area")),a.timeAxis=new r.TimeAxis(a.context,a.el.querySelector("thead .fc-time-area"),a.el.querySelector("tbody .fc-time-area"));var _=t.createElement("div",{className:"fc-rows"},"<table><tbody /></table>");return a.timeAxis.layout.bodyScroller.enhancedScroll.canvas.contentEl.appendChild(_),a.timeAxisTbody=_.querySelector("tbody"),a.lane=new r.TimelineLane(a.context,null,a.timeAxis.layout.bodyScroller.enhancedScroll.canvas.bgEl,a.timeAxis),a.bodyScrollJoiner=new r.ScrollJoiner("vertical",[a.spreadsheet.layout.bodyScroller,a.timeAxis.layout.bodyScroller]),a.spreadsheetBodyStickyScroller=new r.StickyScroller(a.spreadsheet.layout.bodyScroller.enhancedScroll,a.isRtl,!0),a.spreadsheet.receiveProps({superHeaderText:a.superHeaderText,colSpecs:a.colSpecs}),i.calendar.registerInteractiveComponent(a,{el:a.timeAxis.slats.el}),a}return l(i,e),i.prototype.renderSkeletonHtml=function(){var e=this.theme;return'<table class="'+e.getClass("tableGrid")+'"> <thead class="fc-head"> <tr> <td class="fc-resource-area '+e.getClass("widgetHeader")+'"></td> <td class="fc-divider fc-col-resizer '+e.getClass("widgetHeader")+'"></td> <td class="fc-time-area '+e.getClass("widgetHeader")+'"></td> </tr> </thead> <tbody class="fc-body"> <tr> <td class="fc-resource-area '+e.getClass("widgetContent")+'"></td> <td class="fc-divider fc-col-resizer '+e.getClass("widgetHeader")+'"></td> <td class="fc-time-area '+e.getClass("widgetContent")+'"></td> </tr> </tbody> </table>'},i.prototype.render=function(t){e.prototype.render.call(this,t);var r=this.splitter.splitProps(t),o=this.hasResourceBusinessHours(t.resourceStore);this.timeAxis.receiveProps({dateProfile:t.dateProfile}),this.lane.receiveProps(a({},r[""],{dateProfile:t.dateProfile,nextDayThreshold:this.nextDayThreshold,businessHours:o?null:t.businessHours}));var i=this.buildRowNodes(t.resourceStore,this.groupSpecs,this.orderSpecs,this.isVGrouping,t.resourceEntityExpansions,this.opt("resourcesInitiallyExpanded"));this._updateHasNesting(this.hasNesting(i)),this.diffRows(i),this.renderRows(t.dateProfile,o?t.businessHours:null,r)},i.prototype.updateHasNesting=function(e){var t=this.el.classList;e?t.remove("fc-flat"):t.add("fc-flat")},i.prototype.diffRows=function(e){var t=this.rowNodes,r=t.length,o={},i=0,s=0;for(i=0;i<r;i++)o[t[i].id]=i;for(i=0,s=0;s<e.length;s++){var n=e[s],l=o[n.id];null!=l&&l>=i?(this.removeRows(s,l-i,t),i=l+1):this.addRow(s,n)}this.removeRows(s,r-i,t),this.rowNodes=e},i.prototype.addRow=function(e,t){var r=this.rowComponents,o=this.rowComponentsById,i=r[e],s=this.buildChildComponent(t,this.spreadsheet.bodyTbody,i?i.spreadsheetTr:null,this.timeAxisTbody,i?i.timeAxisTr:null);r.splice(e,0,s),o[t.id]=s},i.prototype.removeRows=function(e,t,r){if(t){for(var o=this.rowComponents,i=this.rowComponentsById,s=0;s<t;s++){o[e+s].destroy(),delete i[r[s].id]}o.splice(e,t)}},i.prototype.buildChildComponent=function(e,t,r,o,i){return e.group?new u(this.context,t,r,o,i):e.resource?new f(this.context,t,r,o,i,this.timeAxis):void 0},i.prototype.renderRows=function(e,t,r){for(var o=this.rowNodes,i=this.rowComponents,s=0;s<o.length;s++){var n=o[s],l=i[s];if(n.group)l.receiveProps({spreadsheetColCnt:this.colSpecs.length,id:n.id,isExpanded:n.isExpanded,group:n.group});else{var c=n.resource;l.receiveProps(a({},r[c.id],{dateProfile:e,nextDayThreshold:this.nextDayThreshold,businessHours:c.businessHours||t,colSpecs:this.colSpecs,id:n.id,rowSpans:n.rowSpans,depth:n.depth,isExpanded:n.isExpanded,hasChildren:n.hasChildren,resource:n.resource}))}}},i.prototype.updateSize=function(e,r,o){var i=this.calendar,s=e||i.isViewUpdated||i.isDatesUpdated||i.isEventsUpdated;s&&(this.syncHeadHeights(),this.timeAxis.updateSize(e,r-this.miscHeight,o),this.spreadsheet.updateSize(e,r-this.miscHeight,o));var n=this.updateRowSizes(e);this.lane.updateSize(e),(s||n)&&(this.bodyScrollJoiner.update(),this.timeAxis.layout.scrollJoiner.update(),this.rowPositions=new t.PositionCache(this.timeAxis.slats.el,this.rowComponents.map(function(e){return e.timeAxisTr}),!1,!0),this.rowPositions.build(),this.isStickyScrollDirty=!0)},i.prototype.syncHeadHeights=function(){var e=this.spreadsheet.header.tableEl,t=this.timeAxis.header.tableEl;e.style.height="",t.style.height="";var r=Math.max(e.getBoundingClientRect().height,t.getBoundingClientRect().height);e.style.height=t.style.height=r+"px"},i.prototype.updateRowSizes=function(e){var t=this.rowComponents;e||(t=t.filter(function(e){return e.isSizeDirty}));for(var r=t.map(function(e){return e.getHeightEls()}),o=0,i=r;o<i.length;o++)for(var s=0,n=i[o];s<n.length;s++){n[s].style.height=""}for(var l=0,a=t;l<a.length;l++){a[l].updateSize(e)}for(var c=r.map(function(e){for(var t=null,r=0,o=e;r<o.length;r++){var i=o[r].getBoundingClientRect().height;(null===t||i>t)&&(t=i)}return t}),d=0;d<r.length;d++)for(var p=0,u=r[d];p<u.length;p++){u[p].style.height=c[d]+"px"}return t.length},i.prototype.destroy=function(){for(var t=0,r=this.rowComponents;t<r.length;t++){r[t].destroy()}this.rowNodes=[],this.rowComponents=[],this.spreadsheet.destroy(),this.timeAxis.destroy();for(var o=0,i=this.resourceAreaWidthDraggings;o<i.length;o++){i[o].destroy()}this.spreadsheetBodyStickyScroller.destroy(),e.prototype.destroy.call(this),this.calendar.unregisterInteractiveComponent(this)},i.prototype.getNowIndicatorUnit=function(e){return this.timeAxis.getNowIndicatorUnit(e)},i.prototype.renderNowIndicator=function(e){this.timeAxis.renderNowIndicator(e)},i.prototype.unrenderNowIndicator=function(){this.timeAxis.unrenderNowIndicator()},i.prototype.queryScroll=function(){var t=e.prototype.queryScroll.call(this);return this.props.resourceStore&&a(t,this.queryResourceScroll()),t},i.prototype.applyScroll=function(t,r){e.prototype.applyScroll.call(this,t,r),this.props.resourceStore&&this.applyResourceScroll(t),(r||this.isStickyScrollDirty)&&(this.isStickyScrollDirty=!1,this.spreadsheetBodyStickyScroller.updateSize(),this.timeAxis.updateStickyScrollers())},i.prototype.computeDateScroll=function(e){return this.timeAxis.computeDateScroll(e)},i.prototype.queryDateScroll=function(){return this.timeAxis.queryDateScroll()},i.prototype.applyDateScroll=function(e){this.timeAxis.applyDateScroll(e)},i.prototype.queryResourceScroll=function(){for(var e=this.rowComponents,t=this.rowNodes,r={},o=this.timeAxis.layout.bodyScroller.el.getBoundingClientRect().top,i=0;i<e.length;i++){var s=e[i],n=t[i],l=s.timeAxisTr.getBoundingClientRect().bottom;if(l>o){r.rowId=n.id,r.bottom=l-o;break}}return r},i.prototype.applyResourceScroll=function(e){var t=e.forcedRowId||e.rowId;if(t){var r=this.rowComponentsById[t];if(r){var o=r.timeAxisTr;if(o){var i=this.timeAxis.layout.bodyScroller.enhancedScroll.canvas.el.getBoundingClientRect().top,s=o.getBoundingClientRect(),n=(e.forcedRowId?s.top:s.bottom-e.bottom)-i;this.timeAxis.layout.bodyScroller.enhancedScroll.setScrollTop(n),this.spreadsheet.layout.bodyScroller.enhancedScroll.setScrollTop(n)}}}},i.prototype.buildPositionCaches=function(){this.timeAxis.slats.updateSize(),this.rowPositions.build()},i.prototype.queryHit=function(e,t){var r=this.rowPositions,o=this.timeAxis.slats,i=r.topToIndex(t);if(null!=i){var s=this.rowNodes[i].resource;if(s){var n=o.positionToHit(e);if(n)return{component:this,dateSpan:{range:n.dateSpan.range,allDay:n.dateSpan.allDay,resourceId:s.id},rect:{left:n.left,right:n.right,top:r.tops[i],bottom:r.bottoms[i]},dayEl:n.dayEl,layer:0}}}},i.prototype.setResourceAreaWidth=function(e){this.resourceAreaWidth=e,t.applyStyleProp(this.resourceAreaHeadEl,"width",e||"")},i.prototype.initResourceAreaWidthDragging=function(){var e=this,t=Array.prototype.slice.call(this.el.querySelectorAll(".fc-col-resizer")),r=this.calendar.pluginSystem.hooks.elementDraggingImpl;r&&(this.resourceAreaWidthDraggings=t.map(function(t){var o,i,s=new r(t);return s.emitter.on("dragstart",function(){"number"!=typeof(o=e.resourceAreaWidth)&&(o=e.resourceAreaHeadEl.getBoundingClientRect().width),i=e.el.getBoundingClientRect().width}),s.emitter.on("dragmove",function(t){var r=o+t.deltaX*(e.isRtl?-1:1);r=Math.max(r,30),r=Math.min(r,i-30),e.setResourceAreaWidth(r)}),s.setAutoScrollEnabled(!1),s}))},i.needsResourceData=!0,i}(t.View);function S(e){for(var t in e){if(e[t].businessHours)return!0}return!1}function x(e){for(var t=0,r=e;t<r.length;t++){var o=r[t];if(o.group)return!0;if(o.resource&&o.hasChildren)return!0}return!1}var E=t.createPlugin({deps:[s,i],defaultView:"resourceTimelineDay",views:{resourceTimeline:{class:v,resourceAreaWidth:"30%",resourcesInitiallyExpanded:!0,eventResizableFromStart:!0},resourceTimelineDay:{type:"resourceTimeline",duration:{days:1}},resourceTimelineWeek:{type:"resourceTimeline",duration:{weeks:1}},resourceTimelineMonth:{type:"resourceTimeline",duration:{months:1}},resourceTimelineYear:{type:"resourceTimeline",duration:{years:1}}}});e.ResourceTimelineView=v,e.default=E,Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
{
"name": "@fullcalendar/resource-timeline",
"version": "4.3.0",
"title": "FullCalendar Resource Timeline Plugin",
"description": "Display events and resources on a horizontal time axis",
"keywords": [
"calendar",
"event",
"full-sized"
],
"homepage": "https://fullcalendar.io/scheduler",
"docs": "https://fullcalendar.io/docs/timeline-view",
"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",
"dependencies": {
"@fullcalendar/resource-common": "~4.3.0",
"@fullcalendar/timeline": "~4.3.0"
},
"peerDependencies": {
"@fullcalendar/core": "~4.3.0"
},
"main": "main.js",
"module": "main.esm.js",
"unpkg": "main.min.js",
"types": "main.d.ts"
}
Copyright (c) 2019 Adam Shaw
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# FullCalendar RRule Plugin
A connector to the RRule library, for recurring events
[View the docs &raquo;](https://fullcalendar.io/docs/rrule-plugin)
This package was created from the [FullCalendar monorepo &raquo;](https://github.com/fullcalendar/fullcalendar)
// Generated by dts-bundle v0.7.3-fork.1
// Dependencies for this module:
// ../../../../../@fullcalendar/core
declare module '@fullcalendar/rrule' {
const _default: import("@fullcalendar/core").PluginDef;
export default _default;
}
/*!
FullCalendar RRule Plugin v4.3.0
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
import {RRule, rrulestr} from 'rrule';
import {createDuration, createPlugin, refineProps} 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.
***************************************************************************** */
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);
};
var EVENT_DEF_PROPS = {
rrule: null,
duration: createDuration
};
var recurring = {
parse: function (rawEvent, leftoverProps, dateEnv) {
if (rawEvent.rrule != null) {
var props = refineProps(rawEvent, EVENT_DEF_PROPS, {}, leftoverProps);
var parsed = parseRRule(props.rrule, dateEnv);
if (parsed) {
return {
typeData: parsed.rrule,
allDayGuess: parsed.allDayGuess,
duration: props.duration
};
}
}
return null;
},
expand: function (rrule, framingRange) {
// we WANT an inclusive start and in exclusive end, but the js rrule lib will only do either BOTH
// inclusive or BOTH exclusive, which is stupid: https://github.com/jakubroztocil/rrule/issues/84
// Workaround: make inclusive, which will generate extra occurences, and then trim.
return rrule.between(framingRange.start, framingRange.end, true)
.filter(function (date) {
return date.valueOf() < framingRange.end.valueOf();
});
}
};
var main = createPlugin({
recurringTypes: [recurring]
});
function parseRRule(input, dateEnv) {
var allDayGuess = null;
var rrule;
if (typeof input === 'string') {
rrule = rrulestr(input);
}
else if (typeof input === 'object' && input) { // non-null object
var refined = __assign({}, input); // copy
if (typeof refined.dtstart === 'string') {
var dtstartMeta = dateEnv.createMarkerMeta(refined.dtstart);
if (dtstartMeta) {
refined.dtstart = dtstartMeta.marker;
allDayGuess = dtstartMeta.isTimeUnspecified;
}
else {
delete refined.dtstart;
}
}
if (typeof refined.until === 'string') {
refined.until = dateEnv.createMarker(refined.until);
}
if (refined.freq != null) {
refined.freq = convertConstant(refined.freq);
}
if (refined.wkst != null) {
refined.wkst = convertConstant(refined.wkst);
}
else {
refined.wkst = (dateEnv.weekDow - 1 + 7) % 7; // convert Sunday-first to Monday-first
}
if (refined.byweekday != null) {
refined.byweekday = convertConstants(refined.byweekday); // the plural version
}
rrule = new RRule(refined);
}
if (rrule) {
return { rrule: rrule, allDayGuess: allDayGuess };
}
return null;
}
function convertConstants(input) {
if (Array.isArray(input)) {
return input.map(convertConstant);
}
return convertConstant(input);
}
function convertConstant(input) {
if (typeof input === 'string') {
return RRule[input.toUpperCase()];
}
return input;
}
export default main;
/*!
FullCalendar RRule Plugin v4.3.0
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rrule'), require('@fullcalendar/core')) :
typeof define === 'function' && define.amd ? define(['exports', 'rrule', '@fullcalendar/core'], factory) :
(global = global || self, factory(global.FullCalendarRrule = {}, global.rrule, global.FullCalendar));
}(this, function (exports, rrule, 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.
***************************************************************************** */
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);
};
var EVENT_DEF_PROPS = {
rrule: null,
duration: core.createDuration
};
var recurring = {
parse: function (rawEvent, leftoverProps, dateEnv) {
if (rawEvent.rrule != null) {
var props = core.refineProps(rawEvent, EVENT_DEF_PROPS, {}, leftoverProps);
var parsed = parseRRule(props.rrule, dateEnv);
if (parsed) {
return {
typeData: parsed.rrule,
allDayGuess: parsed.allDayGuess,
duration: props.duration
};
}
}
return null;
},
expand: function (rrule, framingRange) {
// we WANT an inclusive start and in exclusive end, but the js rrule lib will only do either BOTH
// inclusive or BOTH exclusive, which is stupid: https://github.com/jakubroztocil/rrule/issues/84
// Workaround: make inclusive, which will generate extra occurences, and then trim.
return rrule.between(framingRange.start, framingRange.end, true)
.filter(function (date) {
return date.valueOf() < framingRange.end.valueOf();
});
}
};
var main = core.createPlugin({
recurringTypes: [recurring]
});
function parseRRule(input, dateEnv) {
var allDayGuess = null;
var rrule$1;
if (typeof input === 'string') {
rrule$1 = rrule.rrulestr(input);
}
else if (typeof input === 'object' && input) { // non-null object
var refined = __assign({}, input); // copy
if (typeof refined.dtstart === 'string') {
var dtstartMeta = dateEnv.createMarkerMeta(refined.dtstart);
if (dtstartMeta) {
refined.dtstart = dtstartMeta.marker;
allDayGuess = dtstartMeta.isTimeUnspecified;
}
else {
delete refined.dtstart;
}
}
if (typeof refined.until === 'string') {
refined.until = dateEnv.createMarker(refined.until);
}
if (refined.freq != null) {
refined.freq = convertConstant(refined.freq);
}
if (refined.wkst != null) {
refined.wkst = convertConstant(refined.wkst);
}
else {
refined.wkst = (dateEnv.weekDow - 1 + 7) % 7; // convert Sunday-first to Monday-first
}
if (refined.byweekday != null) {
refined.byweekday = convertConstants(refined.byweekday); // the plural version
}
rrule$1 = new rrule.RRule(refined);
}
if (rrule$1) {
return { rrule: rrule$1, allDayGuess: allDayGuess };
}
return null;
}
function convertConstants(input) {
if (Array.isArray(input)) {
return input.map(convertConstant);
}
return convertConstant(input);
}
function convertConstant(input) {
if (typeof input === 'string') {
return rrule.RRule[input.toUpperCase()];
}
return input;
}
exports.default = main;
Object.defineProperty(exports, '__esModule', { value: true });
}));
/*!
FullCalendar RRule Plugin v4.3.0
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("rrule"),require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","rrule","@fullcalendar/core"],r):r((e=e||self).FullCalendarRrule={},e.rrule,e.FullCalendar)}(this,function(e,r,t){"use strict";var n=function(){return(n=Object.assign||function(e){for(var r,t=1,n=arguments.length;t<n;t++)for(var u in r=arguments[t])Object.prototype.hasOwnProperty.call(r,u)&&(e[u]=r[u]);return e}).apply(this,arguments)},u={rrule:null,duration:t.createDuration},l={parse:function(e,l,a){if(null!=e.rrule){var f=t.refineProps(e,u,{},l),o=function(e,t){var u,l=null;if("string"==typeof e)u=r.rrulestr(e);else if("object"==typeof e&&e){var a=n({},e);if("string"==typeof a.dtstart){var f=t.createMarkerMeta(a.dtstart);f?(a.dtstart=f.marker,l=f.isTimeUnspecified):delete a.dtstart}"string"==typeof a.until&&(a.until=t.createMarker(a.until)),null!=a.freq&&(a.freq=i(a.freq)),null!=a.wkst?a.wkst=i(a.wkst):a.wkst=(t.weekDow-1+7)%7,null!=a.byweekday&&(a.byweekday=function(e){if(Array.isArray(e))return e.map(i);return i(e)}(a.byweekday)),u=new r.RRule(a)}if(u)return{rrule:u,allDayGuess:l};return null}(f.rrule,a);if(o)return{typeData:o.rrule,allDayGuess:o.allDayGuess,duration:f.duration}}return null},expand:function(e,r){return e.between(r.start,r.end,!0).filter(function(e){return e.valueOf()<r.end.valueOf()})}},a=t.createPlugin({recurringTypes:[l]});function i(e){return"string"==typeof e?r.RRule[e.toUpperCase()]:e}e.default=a,Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
{
"name": "@fullcalendar/rrule",
"version": "4.3.0",
"title": "FullCalendar RRule Plugin",
"description": "A connector to the RRule library, for recurring events",
"keywords": [
"calendar",
"event",
"full-sized"
],
"homepage": "https://fullcalendar.io/",
"docs": "https://fullcalendar.io/docs/rrule-plugin",
"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",
"peerDependencies": {
"@fullcalendar/core": "~4.3.0",
"rrule": "^2.6.0"
},
"main": "main.js",
"module": "main.esm.js",
"unpkg": "main.min.js",
"types": "main.d.ts"
}
Copyright (c) 2019 Adam Shaw
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# FullCalendar Time Grid Plugin
Display your events on a grid of time slots
[View the docs &raquo;](https://fullcalendar.io/docs/timegrid-view)
This package was created from the [FullCalendar monorepo &raquo;](https://github.com/fullcalendar/fullcalendar)
@charset "UTF-8";
/* TimeGridView all-day area
--------------------------------------------------------------------------------------------------*/
.fc-timeGrid-view .fc-day-grid {
position: relative;
z-index: 2;
/* so the "more.." popover will be over the time grid */
}
.fc-timeGrid-view .fc-day-grid .fc-row {
min-height: 3em;
/* all-day section will never get shorter than this */
}
.fc-timeGrid-view .fc-day-grid .fc-row .fc-content-skeleton {
padding-bottom: 1em;
/* give space underneath events for clicking/selecting days */
}
/* TimeGrid axis running down the side (for both the all-day area and the slot area)
--------------------------------------------------------------------------------------------------*/
.fc .fc-axis {
/* .fc to overcome default cell styles */
vertical-align: middle;
padding: 0 4px;
white-space: nowrap;
}
.fc-ltr .fc-axis {
text-align: right;
}
.fc-rtl .fc-axis {
text-align: left;
}
/* TimeGrid Structure
--------------------------------------------------------------------------------------------------*/
.fc-time-grid-container,
.fc-time-grid {
/* so slats/bg/content/etc positions get scoped within here */
position: relative;
z-index: 1;
}
.fc-time-grid {
min-height: 100%;
/* so if height setting is 'auto', .fc-bg stretches to fill height */
}
.fc-time-grid table {
/* don't put outer borders on slats/bg/content/etc */
border: 0 hidden transparent;
}
.fc-time-grid > .fc-bg {
z-index: 1;
}
.fc-time-grid .fc-slats,
.fc-time-grid > hr {
/* the <hr> TimeGridView injects when grid is shorter than scroller */
position: relative;
z-index: 2;
}
.fc-time-grid .fc-content-col {
position: relative;
/* because now-indicator lives directly inside */
}
.fc-time-grid .fc-content-skeleton {
position: absolute;
z-index: 3;
top: 0;
left: 0;
right: 0;
}
/* divs within a cell within the fc-content-skeleton */
.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 {
position: relative;
z-index: 3;
}
.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 {
/* also is fc-event-container */
position: relative;
z-index: 6;
}
/* TimeGrid Slats (lines that run horizontally)
--------------------------------------------------------------------------------------------------*/
.fc-time-grid .fc-slats td {
height: 1.5em;
border-bottom: 0;
/* each cell is responsible for its top border */
}
.fc-time-grid .fc-slats .fc-minor td {
border-top-style: dotted;
}
/* TimeGrid Highlighting Slots
--------------------------------------------------------------------------------------------------*/
.fc-time-grid .fc-highlight-container {
/* a div within a cell within the fc-highlight-skeleton */
position: relative;
/* scopes the left/right of the fc-highlight to be in the column */
}
.fc-time-grid .fc-highlight {
position: absolute;
left: 0;
right: 0;
/* top and bottom will be in by JS */
}
/* TimeGrid Event Containment
--------------------------------------------------------------------------------------------------*/
.fc-ltr .fc-time-grid .fc-event-container {
/* space on the sides of events for LTR (default) */
margin: 0 2.5% 0 2px;
}
.fc-rtl .fc-time-grid .fc-event-container {
/* space on the sides of events for RTL */
margin: 0 2px 0 2.5%;
}
.fc-time-grid .fc-event,
.fc-time-grid .fc-bgevent {
position: absolute;
z-index: 1;
/* scope inner z-index's */
}
.fc-time-grid .fc-bgevent {
/* background events always span full width */
left: 0;
right: 0;
}
/* TimeGrid Event Styling
----------------------------------------------------------------------------------------------------
We use the full "fc-time-grid-event" class instead of using descendants because the event won't
be a descendant of the grid when it is being dragged.
*/
.fc-time-grid-event {
margin-bottom: 1px;
}
.fc-time-grid-event-inset {
-webkit-box-shadow: 0px 0px 0px 1px #fff;
box-shadow: 0px 0px 0px 1px #fff;
}
.fc-time-grid-event.fc-not-start {
/* events that are continuing from another day */
/* replace space made by the top border with padding */
border-top-width: 0;
padding-top: 1px;
/* remove top rounded corners */
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.fc-time-grid-event.fc-not-end {
/* replace space made by the top border with padding */
border-bottom-width: 0;
padding-bottom: 1px;
/* remove bottom rounded corners */
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: 0.85em;
white-space: nowrap;
}
/* short mode, where time and title are on the same line */
.fc-time-grid-event.fc-short .fc-content {
/* don't wrap to second line (now that contents will be inline) */
white-space: nowrap;
}
.fc-time-grid-event.fc-short .fc-time,
.fc-time-grid-event.fc-short .fc-title {
/* put the time and title on the same line */
display: inline-block;
vertical-align: top;
}
.fc-time-grid-event.fc-short .fc-time span {
display: none;
/* don't display the full time text... */
}
.fc-time-grid-event.fc-short .fc-time:before {
content: attr(data-start);
/* ...instead, display only the start time */
}
.fc-time-grid-event.fc-short .fc-time:after {
content: " - ";
/* seperate with a dash, wrapped in nbsp's */
}
.fc-time-grid-event.fc-short .fc-title {
font-size: 0.85em;
/* make the title text the same size as the time */
padding: 0;
/* undo padding from above */
}
/* resizer (cursor device) */
.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: "=";
}
/* resizer (touch device) */
.fc-time-grid-event.fc-selected .fc-resizer {
/* 10x10 dot */
border-radius: 5px;
border-width: 1px;
width: 8px;
height: 8px;
border-style: solid;
border-color: inherit;
background: #fff;
/* horizontally center */
left: 50%;
margin-left: -5px;
/* center on the bottom edge */
bottom: -5px;
}
/* Now Indicator
--------------------------------------------------------------------------------------------------*/
.fc-time-grid .fc-now-indicator-line {
border-top-width: 1px;
left: 0;
right: 0;
}
/* arrow on axis */
.fc-time-grid .fc-now-indicator-arrow {
margin-top: -5px;
/* vertically center on top coordinate */
}
.fc-ltr .fc-time-grid .fc-now-indicator-arrow {
left: 0;
/* triangle pointing right... */
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;
/* triangle pointing left... */
border-width: 5px 6px 5px 0;
border-top-color: transparent;
border-bottom-color: transparent;
}
// Generated by dts-bundle v0.7.3-fork.1
// Dependencies for this module:
// ../../../../../@fullcalendar/core
// ../../../../../@fullcalendar/daygrid
declare module '@fullcalendar/timegrid' {
import AbstractTimeGridView from '@fullcalendar/timegrid/AbstractTimeGridView';
import TimeGridView, {buildDayTable} from '@fullcalendar/timegrid/TimeGridView';
import {TimeGridSeg} from '@fullcalendar/timegrid/TimeGrid';
import {buildDayRanges, TimeGridSlicer} from '@fullcalendar/timegrid/SimpleTimeGrid';
export {TimeGridView, AbstractTimeGridView, buildDayTable, buildDayRanges, TimeGridSlicer, TimeGridSeg};
export {default as TimeGrid} from '@fullcalendar/timegrid/TimeGrid';
const _default: import("@fullcalendar/core").PluginDef;
export default _default;
}
declare module '@fullcalendar/timegrid/AbstractTimeGridView' {
import {
ComponentContext,
DateProfileGenerator,
Duration,
ScrollComponent,
View,
ViewSpec
} from '@fullcalendar/core';
import {DayGrid} from '@fullcalendar/daygrid';
import TimeGrid from '@fullcalendar/timegrid/TimeGrid';
import AllDaySplitter from '@fullcalendar/timegrid/AllDaySplitter';
export {TimeGridView as default, TimeGridView};
abstract class TimeGridView extends View {
timeGrid: TimeGrid;
dayGrid: DayGrid;
scroller: ScrollComponent;
axisWidth: any;
protected splitter: AllDaySplitter;
constructor(context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement);
destroy(): void;
renderSkeletonHtml(): string;
getNowIndicatorUnit(): string;
unrenderNowIndicator(): void;
updateSize(isResize: boolean, viewHeight: number, isAuto: boolean): void;
updateBaseSize(isResize: any, viewHeight: any, isAuto: any): void;
computeScrollerHeight(viewHeight: any): number;
computeDateScroll(duration: Duration): {
top: any;
};
queryDateScroll(): {
top: number;
};
applyDateScroll(scroll: any): void;
renderHeadIntroHtml: () => string;
axisStyleAttr(): string;
renderTimeGridBgIntroHtml: () => string;
renderTimeGridIntroHtml: () => string;
renderDayGridBgIntroHtml: () => string;
renderDayGridIntroHtml: () => string;
}
}
declare module '@fullcalendar/timegrid/TimeGridView' {
import {
ComponentContext,
DateProfile,
DateProfileGenerator,
DayHeader,
DayTable,
ViewProps,
ViewSpec
} from '@fullcalendar/core';
import {SimpleDayGrid} from '@fullcalendar/daygrid';
import SimpleTimeGrid from '@fullcalendar/timegrid/SimpleTimeGrid';
import AbstractTimeGridView from '@fullcalendar/timegrid/AbstractTimeGridView';
export {TimeGridView as default, TimeGridView};
class TimeGridView extends AbstractTimeGridView {
header: DayHeader;
simpleDayGrid: SimpleDayGrid;
simpleTimeGrid: SimpleTimeGrid;
constructor(_context: ComponentContext, viewSpec: ViewSpec, dateProfileGenerator: DateProfileGenerator, parentEl: HTMLElement);
destroy(): void;
render(props: ViewProps): void;
renderNowIndicator(date: any): void;
}
export function buildDayTable(dateProfile: DateProfile, dateProfileGenerator: DateProfileGenerator): DayTable;
}
declare module '@fullcalendar/timegrid/TimeGrid' {
import {
ComponentContext,
DateComponent,
DateFormatter,
DateMarker,
DateProfile,
Duration,
EventSegUiInteractionState,
PositionCache,
Seg
} from '@fullcalendar/core';
export interface RenderProps {
renderBgIntroHtml: () => string;
renderIntroHtml: () => string;
}
export interface TimeGridSeg extends Seg {
col: number;
start: DateMarker;
end: DateMarker;
}
export interface TimeGridCell {
date: DateMarker;
htmlAttrs?: string;
}
export interface TimeGridProps {
dateProfile: DateProfile;
cells: TimeGridCell[];
businessHourSegs: TimeGridSeg[];
bgEventSegs: TimeGridSeg[];
fgEventSegs: TimeGridSeg[];
dateSelectionSegs: TimeGridSeg[];
eventSelection: string;
eventDrag: EventSegUiInteractionState | null;
eventResize: EventSegUiInteractionState | null;
}
export { TimeGrid as default, TimeGrid };
class TimeGrid extends DateComponent<TimeGridProps> {
renderProps: RenderProps;
slotDuration: Duration;
snapDuration: Duration;
snapsPerSlot: any;
labelFormat: DateFormatter;
labelInterval: Duration;
colCnt: number;
colEls: HTMLElement[];
slatContainerEl: HTMLElement;
slatEls: HTMLElement[];
nowIndicatorEls: HTMLElement[];
colPositions: PositionCache;
slatPositions: PositionCache;
isSlatSizesDirty: boolean;
isColSizesDirty: boolean;
rootBgContainerEl: HTMLElement;
bottomRuleEl: HTMLElement;
contentSkeletonEl: HTMLElement;
colContainerEls: HTMLElement[];
fgContainerEls: HTMLElement[];
bgContainerEls: HTMLElement[];
mirrorContainerEls: HTMLElement[];
highlightContainerEls: HTMLElement[];
businessContainerEls: HTMLElement[];
constructor(context: ComponentContext, el: HTMLElement, renderProps: RenderProps);
processOptions(): void;
computeLabelInterval(slotDuration: any): any;
render(props: TimeGridProps): void;
destroy(): void;
updateSize(isResize: boolean): void;
_renderSlats(dateProfile: DateProfile): void;
renderSlatRowHtml(dateProfile: DateProfile): string;
_renderColumns(cells: TimeGridCell[], dateProfile: DateProfile): void;
_unrenderColumns(): void;
renderContentSkeleton(): void;
unrenderContentSkeleton(): void;
groupSegsByCol(segs: any): any[];
attachSegsByCol(segsByCol: any, containerEls: HTMLElement[]): void;
getNowIndicatorUnit(): string;
renderNowIndicator(segs: TimeGridSeg[], date: any): void;
unrenderNowIndicator(): void;
getTotalSlatHeight(): number;
computeDateTop(when: DateMarker, startOfDayDate?: DateMarker): any;
computeTimeTop(duration: Duration): any;
computeSegVerticals(segs: any): void;
assignSegVerticals(segs: any): void;
generateSegVerticalCss(seg: any): {
top: any;
bottom: number;
};
buildPositionCaches(): void;
buildColPositions(): void;
buildSlatPositions(): void;
positionToHit(positionLeft: any, positionTop: any): {
col: any;
dateSpan: {
range: {
start: Date;
end: Date;
};
allDay: boolean;
};
dayEl: HTMLElement;
relativeRect: {
left: any;
right: any;
top: any;
bottom: any;
};
};
_renderEventDrag(state: EventSegUiInteractionState): void;
_unrenderEventDrag(state: EventSegUiInteractionState): void;
_renderEventResize(state: EventSegUiInteractionState): void;
_unrenderEventResize(state: EventSegUiInteractionState): void;
_renderDateSelection(segs: Seg[]): void;
_unrenderDateSelection(segs: Seg[]): void;
}
}
declare module '@fullcalendar/timegrid/SimpleTimeGrid' {
import {
ComponentContext,
DateComponent,
DateEnv,
DateMarker,
DateProfile,
DateRange,
DateSpan,
DayTable,
EventInteractionState,
EventStore,
EventUiHash,
Hit,
Slicer
} from '@fullcalendar/core';
import TimeGrid, {TimeGridSeg} from '@fullcalendar/timegrid/TimeGrid';
export interface SimpleTimeGridProps {
dateProfile: DateProfile | null;
dayTable: DayTable;
businessHours: EventStore;
eventStore: EventStore;
eventUiBases: EventUiHash;
dateSelection: DateSpan | null;
eventSelection: string;
eventDrag: EventInteractionState | null;
eventResize: EventInteractionState | null;
}
export { SimpleTimeGrid as default, SimpleTimeGrid };
class SimpleTimeGrid extends DateComponent<SimpleTimeGridProps> {
timeGrid: TimeGrid;
constructor(context: ComponentContext, timeGrid: TimeGrid);
destroy(): void;
render(props: SimpleTimeGridProps): void;
renderNowIndicator(date: DateMarker): void;
buildPositionCaches(): void;
queryHit(positionLeft: number, positionTop: number): Hit;
}
export function buildDayRanges(dayTable: DayTable, dateProfile: DateProfile, dateEnv: DateEnv): DateRange[];
export class TimeGridSlicer extends Slicer<TimeGridSeg, [DateRange[]]> {
sliceRange(range: DateRange, dayRanges: DateRange[]): TimeGridSeg[];
}
}
declare module '@fullcalendar/timegrid/AllDaySplitter' {
import {DateSpan, EventDef, Splitter} from '@fullcalendar/core';
export { AllDaySplitter as default, AllDaySplitter };
class AllDaySplitter extends Splitter {
getKeyInfo(): {
allDay: {};
timed: {};
};
getKeysForDateSpan(dateSpan: DateSpan): string[];
getKeysForEventDef(eventDef: EventDef): string[];
}
}
/*!
FullCalendar Time Grid Plugin v4.3.0
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
import {
addDurations,
applyStyle,
asRoughMs,
buildGotoAnchorHtml,
buildSegCompareObj,
compareByFieldSpecs,
compensateScroll,
createDuration,
createElement,
createFormatter,
createPlugin,
cssToStr,
DateComponent,
DayHeader,
DaySeries,
DayTable,
diffDays,
FgEventRenderer,
FillRenderer,
findElements,
formatIsoTimeString,
getAllDayHtml,
hasBgRendering,
htmlEscape,
htmlToElement,
intersectRanges,
isMultiDayRange,
matchCellWidths,
memoize,
memoizeRendering,
multiplyDuration,
PositionCache,
removeElement,
ScrollComponent,
Slicer,
Splitter,
startOfDay,
subtractInnerElHeight,
uncompensateScroll,
View,
wholeDivideDurations
} from '@fullcalendar/core';
import {DayBgRow, DayGrid, SimpleDayGrid} from '@fullcalendar/daygrid';
/*! *****************************************************************************
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);
};
/*
Only handles foreground segs.
Does not own rendering. Use for low-level util methods by TimeGrid.
*/
var TimeGridEventRenderer = /** @class */ (function (_super) {
__extends(TimeGridEventRenderer, _super);
function TimeGridEventRenderer(timeGrid) {
var _this = _super.call(this, timeGrid.context) || this;
_this.timeGrid = timeGrid;
_this.fullTimeFormat = createFormatter({
hour: 'numeric',
minute: '2-digit',
separator: _this.context.options.defaultRangeSeparator
});
return _this;
}
// Given an array of foreground segments, render a DOM element for each, computes position,
// and attaches to the column inner-container elements.
TimeGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
var segsByCol = this.timeGrid.groupSegsByCol(segs);
// order the segs within each column
// TODO: have groupSegsByCol do this?
for (var col = 0; col < segsByCol.length; col++) {
segsByCol[col] = this.sortEventSegs(segsByCol[col]);
}
this.segsByCol = segsByCol;
this.timeGrid.attachSegsByCol(segsByCol, this.timeGrid.fgContainerEls);
};
TimeGridEventRenderer.prototype.detachSegs = function (segs) {
segs.forEach(function (seg) {
removeElement(seg.el);
});
this.segsByCol = null;
};
TimeGridEventRenderer.prototype.computeSegSizes = function (allSegs) {
var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol;
var colCnt = timeGrid.colCnt;
timeGrid.computeSegVerticals(allSegs); // horizontals relies on this
if (segsByCol) {
for (var col = 0; col < colCnt; col++) {
this.computeSegHorizontals(segsByCol[col]); // compute horizontal coordinates, z-index's, and reorder the array
}
}
};
TimeGridEventRenderer.prototype.assignSegSizes = function (allSegs) {
var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol;
var colCnt = timeGrid.colCnt;
timeGrid.assignSegVerticals(allSegs); // horizontals relies on this
if (segsByCol) {
for (var col = 0; col < colCnt; col++) {
this.assignSegCss(segsByCol[col]);
}
}
};
// Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
TimeGridEventRenderer.prototype.computeEventTimeFormat = function () {
return {
hour: 'numeric',
minute: '2-digit',
meridiem: false
};
};
// Computes a default `displayEventEnd` value if one is not expliclty defined
TimeGridEventRenderer.prototype.computeDisplayEventEnd = function () {
return true;
};
// Renders the HTML for a single event segment's default rendering
TimeGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
var view = this.context.view;
var eventRange = seg.eventRange;
var eventDef = eventRange.def;
var eventUi = eventRange.ui;
var allDay = eventDef.allDay;
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);
var skinCss = cssToStr(this.getSkinCss(eventUi));
var timeText;
var fullTimeText; // more verbose time text. for the print stylesheet
var startTimeText; // just the start time text
classes.unshift('fc-time-grid-event');
// if the event appears to span more than one day...
if (isMultiDayRange(eventRange.range)) {
// Don't display time text on segments that run entirely through a day.
// That would appear as midnight-midnight and would look dumb.
// Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am)
if (seg.isStart || seg.isEnd) {
var unzonedStart = seg.start;
var unzonedEnd = seg.end;
timeText = this._getTimeText(unzonedStart, unzonedEnd, allDay); // TODO: give the timezones
fullTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, this.fullTimeFormat);
startTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, null, false); // displayEnd=false
}
}
else {
// Display the normal time text for the *event's* times
timeText = this.getTimeText(eventRange);
fullTimeText = this.getTimeText(eventRange, this.fullTimeFormat);
startTimeText = this.getTimeText(eventRange, null, false); // displayEnd=false
}
return '<a class="' + classes.join(' ') + '"' +
(eventDef.url ?
' href="' + htmlEscape(eventDef.url) + '"' :
'') +
(skinCss ?
' style="' + skinCss + '"' :
'') +
'>' +
'<div class="fc-content">' +
(timeText ?
'<div class="fc-time"' +
' data-start="' + htmlEscape(startTimeText) + '"' +
' data-full="' + htmlEscape(fullTimeText) + '"' +
'>' +
'<span>' + htmlEscape(timeText) + '</span>' +
'</div>' :
'') +
(eventDef.title ?
'<div class="fc-title">' +
htmlEscape(eventDef.title) +
'</div>' :
'') +
'</div>' +
/* TODO: write CSS for this
(isResizableFromStart ?
'<div class="fc-resizer fc-start-resizer"></div>' :
''
) +
*/
(isResizableFromEnd ?
'<div class="fc-resizer fc-end-resizer"></div>' :
'') +
'</a>';
};
// Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
// Assumed the segs are already ordered.
// NOTE: Also reorders the given array by date!
TimeGridEventRenderer.prototype.computeSegHorizontals = function (segs) {
var levels;
var level0;
var i;
levels = buildSlotSegLevels(segs);
computeForwardSlotSegs(levels);
if ((level0 = levels[0])) {
for (i = 0; i < level0.length; i++) {
computeSlotSegPressures(level0[i]);
}
for (i = 0; i < level0.length; i++) {
this.computeSegForwardBack(level0[i], 0, 0);
}
}
};
// Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
// from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
// seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
//
// The segment might be part of a "series", which means consecutive segments with the same pressure
// who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
// segments behind this one in the current series, and `seriesBackwardCoord` is the starting
// coordinate of the first segment in the series.
TimeGridEventRenderer.prototype.computeSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) {
var forwardSegs = seg.forwardSegs;
var i;
if (seg.forwardCoord === undefined) { // not already computed
if (!forwardSegs.length) {
// if there are no forward segments, this segment should butt up against the edge
seg.forwardCoord = 1;
}
else {
// sort highest pressure first
this.sortForwardSegs(forwardSegs);
// this segment's forwardCoord will be calculated from the backwardCoord of the
// highest-pressure forward segment.
this.computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
seg.forwardCoord = forwardSegs[0].backwardCoord;
}
// calculate the backwardCoord from the forwardCoord. consider the series
seg.backwardCoord = seg.forwardCoord -
(seg.forwardCoord - seriesBackwardCoord) / // available width for series
(seriesBackwardPressure + 1); // # of segments in the series
// use this segment's coordinates to computed the coordinates of the less-pressurized
// forward segments
for (i = 0; i < forwardSegs.length; i++) {
this.computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
}
}
};
TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) {
var objs = forwardSegs.map(buildTimeGridSegCompareObj);
var specs = [
// put higher-pressure first
{ field: 'forwardPressure', order: -1 },
// put segments that are closer to initial edge first (and favor ones with no coords yet)
{ field: 'backwardCoord', order: 1 }
].concat(this.context.view.eventOrderSpecs);
objs.sort(function (obj0, obj1) {
return compareByFieldSpecs(obj0, obj1, specs);
});
return objs.map(function (c) {
return c._seg;
});
};
// Given foreground event segments that have already had their position coordinates computed,
// assigns position-related CSS values to their elements.
TimeGridEventRenderer.prototype.assignSegCss = function (segs) {
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
applyStyle(seg.el, this.generateSegCss(seg));
if (seg.level > 0) {
seg.el.classList.add('fc-time-grid-event-inset');
}
// if the event is short that the title will be cut off,
// attach a className that condenses the title into the time area.
if (seg.eventRange.def.title && seg.bottom - seg.top < 30) {
seg.el.classList.add('fc-short'); // TODO: "condensed" is a better name
}
}
};
// Generates an object with CSS properties/values that should be applied to an event segment element.
// Contains important positioning-related properties that should be applied to any event element, customized or not.
TimeGridEventRenderer.prototype.generateSegCss = function (seg) {
var shouldOverlap = this.context.options.slotEventOverlap;
var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first
var isRtl = this.timeGrid.isRtl;
var left; // amount of space from left edge, a fraction of the total width
var right; // amount of space from right edge, a fraction of the total width
if (shouldOverlap) {
// double the width, but don't go beyond the maximum forward coordinate (1.0)
forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
}
if (isRtl) {
left = 1 - forwardCoord;
right = backwardCoord;
}
else {
left = backwardCoord;
right = 1 - forwardCoord;
}
props.zIndex = seg.level + 1; // convert from 0-base to 1-based
props.left = left * 100 + '%';
props.right = right * 100 + '%';
if (shouldOverlap && seg.forwardPressure) {
// add padding to the edge so that forward stacked events don't cover the resizer's icon
props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
}
return props;
};
return TimeGridEventRenderer;
}(FgEventRenderer));
// Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is
// left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date.
function buildSlotSegLevels(segs) {
var levels = [];
var i;
var seg;
var j;
for (i = 0; i < segs.length; i++) {
seg = segs[i];
// go through all the levels and stop on the first level where there are no collisions
for (j = 0; j < levels.length; j++) {
if (!computeSlotSegCollisions(seg, levels[j]).length) {
break;
}
}
seg.level = j;
(levels[j] || (levels[j] = [])).push(seg);
}
return levels;
}
// For every segment, figure out the other segments that are in subsequent
// levels that also occupy the same vertical space. Accumulate in seg.forwardSegs
function computeForwardSlotSegs(levels) {
var i;
var level;
var j;
var seg;
var k;
for (i = 0; i < levels.length; i++) {
level = levels[i];
for (j = 0; j < level.length; j++) {
seg = level[j];
seg.forwardSegs = [];
for (k = i + 1; k < levels.length; k++) {
computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
}
}
}
}
// Figure out which path forward (via seg.forwardSegs) results in the longest path until
// the furthest edge is reached. The number of segments in this path will be seg.forwardPressure
function computeSlotSegPressures(seg) {
var forwardSegs = seg.forwardSegs;
var forwardPressure = 0;
var i;
var forwardSeg;
if (seg.forwardPressure === undefined) { // not already computed
for (i = 0; i < forwardSegs.length; i++) {
forwardSeg = forwardSegs[i];
// figure out the child's maximum forward path
computeSlotSegPressures(forwardSeg);
// either use the existing maximum, or use the child's forward pressure
// plus one (for the forwardSeg itself)
forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure);
}
seg.forwardPressure = forwardPressure;
}
}
// Find all the segments in `otherSegs` that vertically collide with `seg`.
// Append into an optionally-supplied `results` array and return.
function computeSlotSegCollisions(seg, otherSegs, results) {
if (results === void 0) { results = []; }
for (var i = 0; i < otherSegs.length; i++) {
if (isSlotSegCollision(seg, otherSegs[i])) {
results.push(otherSegs[i]);
}
}
return results;
}
// Do these segments occupy the same vertical space?
function isSlotSegCollision(seg1, seg2) {
return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
}
function buildTimeGridSegCompareObj(seg) {
var obj = buildSegCompareObj(seg);
obj.forwardPressure = seg.forwardPressure;
obj.backwardCoord = seg.backwardCoord;
return obj;
}
var TimeGridMirrorRenderer = /** @class */ (function (_super) {
__extends(TimeGridMirrorRenderer, _super);
function TimeGridMirrorRenderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
TimeGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
this.segsByCol = this.timeGrid.groupSegsByCol(segs);
this.timeGrid.attachSegsByCol(this.segsByCol, this.timeGrid.mirrorContainerEls);
this.sourceSeg = mirrorInfo.sourceSeg;
};
TimeGridMirrorRenderer.prototype.generateSegCss = function (seg) {
var props = _super.prototype.generateSegCss.call(this, seg);
var sourceSeg = this.sourceSeg;
if (sourceSeg && sourceSeg.col === seg.col) {
var sourceSegProps = _super.prototype.generateSegCss.call(this, sourceSeg);
props.left = sourceSegProps.left;
props.right = sourceSegProps.right;
props.marginLeft = sourceSegProps.marginLeft;
props.marginRight = sourceSegProps.marginRight;
}
return props;
};
return TimeGridMirrorRenderer;
}(TimeGridEventRenderer));
var TimeGridFillRenderer = /** @class */ (function (_super) {
__extends(TimeGridFillRenderer, _super);
function TimeGridFillRenderer(timeGrid) {
var _this = _super.call(this, timeGrid.context) || this;
_this.timeGrid = timeGrid;
return _this;
}
TimeGridFillRenderer.prototype.attachSegs = function (type, segs) {
var timeGrid = this.timeGrid;
var containerEls;
// TODO: more efficient lookup
if (type === 'bgEvent') {
containerEls = timeGrid.bgContainerEls;
}
else if (type === 'businessHours') {
containerEls = timeGrid.businessContainerEls;
}
else if (type === 'highlight') {
containerEls = timeGrid.highlightContainerEls;
}
timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls);
return segs.map(function (seg) {
return seg.el;
});
};
TimeGridFillRenderer.prototype.computeSegSizes = function (segs) {
this.timeGrid.computeSegVerticals(segs);
};
TimeGridFillRenderer.prototype.assignSegSizes = function (segs) {
this.timeGrid.assignSegVerticals(segs);
};
return TimeGridFillRenderer;
}(FillRenderer));
/* A component that renders one or more columns of vertical time slots
----------------------------------------------------------------------------------------------------------------------*/
// potential nice values for the slot-duration and interval-duration
// from largest to smallest
var AGENDA_STOCK_SUB_DURATIONS = [
{ hours: 1 },
{ minutes: 30 },
{ minutes: 15 },
{ seconds: 30 },
{ seconds: 15 }
];
var TimeGrid = /** @class */ (function (_super) {
__extends(TimeGrid, _super);
function TimeGrid(context, el, renderProps) {
var _this = _super.call(this, context, el) || this;
_this.isSlatSizesDirty = false;
_this.isColSizesDirty = false;
_this.renderSlats = memoizeRendering(_this._renderSlats);
var eventRenderer = _this.eventRenderer = new TimeGridEventRenderer(_this);
var fillRenderer = _this.fillRenderer = new TimeGridFillRenderer(_this);
_this.mirrorRenderer = new TimeGridMirrorRenderer(_this);
var renderColumns = _this.renderColumns = memoizeRendering(_this._renderColumns, _this._unrenderColumns);
_this.renderBusinessHours = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderColumns]);
_this.renderDateSelection = memoizeRendering(_this._renderDateSelection, _this._unrenderDateSelection, [renderColumns]);
_this.renderFgEvents = memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderColumns]);
_this.renderBgEvents = memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderColumns]);
_this.renderEventSelection = memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
_this.renderEventDrag = memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderColumns]);
_this.renderEventResize = memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderColumns]);
_this.processOptions();
el.innerHTML =
'<div class="fc-bg"></div>' +
'<div class="fc-slats"></div>' +
'<hr class="fc-divider ' + _this.theme.getClass('widgetHeader') + '" style="display:none" />';
_this.rootBgContainerEl = el.querySelector('.fc-bg');
_this.slatContainerEl = el.querySelector('.fc-slats');
_this.bottomRuleEl = el.querySelector('.fc-divider');
_this.renderProps = renderProps;
return _this;
}
/* Options
------------------------------------------------------------------------------------------------------------------*/
// Parses various options into properties of this object
TimeGrid.prototype.processOptions = function () {
var slotDuration = this.opt('slotDuration');
var snapDuration = this.opt('snapDuration');
var snapsPerSlot;
var input;
slotDuration = createDuration(slotDuration);
snapDuration = snapDuration ? createDuration(snapDuration) : slotDuration;
snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration);
if (snapsPerSlot === null) {
snapDuration = slotDuration;
snapsPerSlot = 1;
// TODO: say warning?
}
this.slotDuration = slotDuration;
this.snapDuration = snapDuration;
this.snapsPerSlot = snapsPerSlot;
// might be an array value (for TimelineView).
// if so, getting the most granular entry (the last one probably).
input = this.opt('slotLabelFormat');
if (Array.isArray(input)) {
input = input[input.length - 1];
}
this.labelFormat = createFormatter(input || {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'short'
});
input = this.opt('slotLabelInterval');
this.labelInterval = input ?
createDuration(input) :
this.computeLabelInterval(slotDuration);
};
// Computes an automatic value for slotLabelInterval
TimeGrid.prototype.computeLabelInterval = function (slotDuration) {
var i;
var labelInterval;
var slotsPerLabel;
// find the smallest stock label interval that results in more than one slots-per-label
for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
labelInterval = createDuration(AGENDA_STOCK_SUB_DURATIONS[i]);
slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
if (slotsPerLabel !== null && slotsPerLabel > 1) {
return labelInterval;
}
}
return slotDuration; // fall back
};
/* Rendering
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.render = function (props) {
var cells = props.cells;
this.colCnt = cells.length;
this.renderSlats(props.dateProfile);
this.renderColumns(props.cells, props.dateProfile);
this.renderBusinessHours(props.businessHourSegs);
this.renderDateSelection(props.dateSelectionSegs);
this.renderFgEvents(props.fgEventSegs);
this.renderBgEvents(props.bgEventSegs);
this.renderEventSelection(props.eventSelection);
this.renderEventDrag(props.eventDrag);
this.renderEventResize(props.eventResize);
};
TimeGrid.prototype.destroy = function () {
_super.prototype.destroy.call(this);
// should unrender everything else too
this.renderSlats.unrender();
this.renderColumns.unrender();
};
TimeGrid.prototype.updateSize = function (isResize) {
var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
if (isResize || this.isSlatSizesDirty) {
this.buildSlatPositions();
this.isSlatSizesDirty = false;
}
if (isResize || this.isColSizesDirty) {
this.buildColPositions();
this.isColSizesDirty = false;
}
fillRenderer.computeSizes(isResize);
eventRenderer.computeSizes(isResize);
mirrorRenderer.computeSizes(isResize);
fillRenderer.assignSizes(isResize);
eventRenderer.assignSizes(isResize);
mirrorRenderer.assignSizes(isResize);
};
TimeGrid.prototype._renderSlats = function (dateProfile) {
var theme = this.theme;
this.slatContainerEl.innerHTML =
'<table class="' + theme.getClass('tableGrid') + '">' +
this.renderSlatRowHtml(dateProfile) +
'</table>';
this.slatEls = findElements(this.slatContainerEl, 'tr');
this.slatPositions = new PositionCache(this.el, this.slatEls, false, true // vertical
);
this.isSlatSizesDirty = true;
};
// Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
TimeGrid.prototype.renderSlatRowHtml = function (dateProfile) {
var _a = this, dateEnv = _a.dateEnv, theme = _a.theme, isRtl = _a.isRtl;
var html = '';
var dayStart = startOfDay(dateProfile.renderRange.start);
var slotTime = dateProfile.minTime;
var slotIterator = createDuration(0);
var slotDate; // will be on the view's first day, but we only care about its time
var isLabeled;
var axisHtml;
// Calculate the time for each slot
while (asRoughMs(slotTime) < asRoughMs(dateProfile.maxTime)) {
slotDate = dateEnv.add(dayStart, slotTime);
isLabeled = wholeDivideDurations(slotIterator, this.labelInterval) !== null;
axisHtml =
'<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '">' +
(isLabeled ?
'<span>' + // for matchCellWidths
htmlEscape(dateEnv.format(slotDate, this.labelFormat)) +
'</span>' :
'') +
'</td>';
html +=
'<tr data-time="' + formatIsoTimeString(slotDate) + '"' +
(isLabeled ? '' : ' class="fc-minor"') +
'>' +
(!isRtl ? axisHtml : '') +
'<td class="' + theme.getClass('widgetContent') + '"></td>' +
(isRtl ? axisHtml : '') +
'</tr>';
slotTime = addDurations(slotTime, this.slotDuration);
slotIterator = addDurations(slotIterator, this.slotDuration);
}
return html;
};
TimeGrid.prototype._renderColumns = function (cells, dateProfile) {
var _a = this, theme = _a.theme, dateEnv = _a.dateEnv, view = _a.view;
var bgRow = new DayBgRow(this.context);
this.rootBgContainerEl.innerHTML =
'<table class="' + theme.getClass('tableGrid') + '">' +
bgRow.renderHtml({
cells: cells,
dateProfile: dateProfile,
renderIntroHtml: this.renderProps.renderBgIntroHtml
}) +
'</table>';
this.colEls = findElements(this.el, '.fc-day, .fc-disabled-day');
for (var col = 0; col < this.colCnt; col++) {
this.publiclyTrigger('dayRender', [
{
date: dateEnv.toDate(cells[col].date),
el: this.colEls[col],
view: view
}
]);
}
if (this.isRtl) {
this.colEls.reverse();
}
this.colPositions = new PositionCache(this.el, this.colEls, true, // horizontal
false);
this.renderContentSkeleton();
this.isColSizesDirty = true;
};
TimeGrid.prototype._unrenderColumns = function () {
this.unrenderContentSkeleton();
};
/* Content Skeleton
------------------------------------------------------------------------------------------------------------------*/
// Renders the DOM that the view's content will live in
TimeGrid.prototype.renderContentSkeleton = function () {
var parts = [];
var skeletonEl;
parts.push(this.renderProps.renderIntroHtml());
for (var i = 0; i < this.colCnt; i++) {
parts.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>');
}
if (this.isRtl) {
parts.reverse();
}
skeletonEl = this.contentSkeletonEl = htmlToElement('<div class="fc-content-skeleton">' +
'<table>' +
'<tr>' + parts.join('') + '</tr>' +
'</table>' +
'</div>');
this.colContainerEls = findElements(skeletonEl, '.fc-content-col');
this.mirrorContainerEls = findElements(skeletonEl, '.fc-mirror-container');
this.fgContainerEls = findElements(skeletonEl, '.fc-event-container:not(.fc-mirror-container)');
this.bgContainerEls = findElements(skeletonEl, '.fc-bgevent-container');
this.highlightContainerEls = findElements(skeletonEl, '.fc-highlight-container');
this.businessContainerEls = findElements(skeletonEl, '.fc-business-container');
if (this.isRtl) {
this.colContainerEls.reverse();
this.mirrorContainerEls.reverse();
this.fgContainerEls.reverse();
this.bgContainerEls.reverse();
this.highlightContainerEls.reverse();
this.businessContainerEls.reverse();
}
this.el.appendChild(skeletonEl);
};
TimeGrid.prototype.unrenderContentSkeleton = function () {
removeElement(this.contentSkeletonEl);
};
// Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col
TimeGrid.prototype.groupSegsByCol = function (segs) {
var segsByCol = [];
var i;
for (i = 0; i < this.colCnt; i++) {
segsByCol.push([]);
}
for (i = 0; i < segs.length; i++) {
segsByCol[segs[i].col].push(segs[i]);
}
return segsByCol;
};
// Given segments grouped by column, insert the segments' elements into a parallel array of container
// elements, each living within a column.
TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) {
var col;
var segs;
var i;
for (col = 0; col < this.colCnt; col++) { // iterate each column grouping
segs = segsByCol[col];
for (i = 0; i < segs.length; i++) {
containerEls[col].appendChild(segs[i].el);
}
}
};
/* Now Indicator
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.getNowIndicatorUnit = function () {
return 'minute'; // will refresh on the minute
};
TimeGrid.prototype.renderNowIndicator = function (segs, date) {
// HACK: if date columns not ready for some reason (scheduler)
if (!this.colContainerEls) {
return;
}
var top = this.computeDateTop(date);
var nodes = [];
var i;
// render lines within the columns
for (i = 0; i < segs.length; i++) {
var lineEl = createElement('div', { className: 'fc-now-indicator fc-now-indicator-line' });
lineEl.style.top = top + 'px';
this.colContainerEls[segs[i].col].appendChild(lineEl);
nodes.push(lineEl);
}
// render an arrow over the axis
if (segs.length > 0) { // is the current time in view?
var arrowEl = createElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' });
arrowEl.style.top = top + 'px';
this.contentSkeletonEl.appendChild(arrowEl);
nodes.push(arrowEl);
}
this.nowIndicatorEls = nodes;
};
TimeGrid.prototype.unrenderNowIndicator = function () {
if (this.nowIndicatorEls) {
this.nowIndicatorEls.forEach(removeElement);
this.nowIndicatorEls = null;
}
};
/* Coordinates
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.getTotalSlatHeight = function () {
return this.slatContainerEl.getBoundingClientRect().height;
};
// Computes the top coordinate, relative to the bounds of the grid, of the given date.
// A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
TimeGrid.prototype.computeDateTop = function (when, startOfDayDate) {
if (!startOfDayDate) {
startOfDayDate = startOfDay(when);
}
return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf()));
};
// Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
TimeGrid.prototype.computeTimeTop = function (duration) {
var len = this.slatEls.length;
var dateProfile = this.props.dateProfile;
var slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.minTime)) / asRoughMs(this.slotDuration); // floating-point value of # of slots covered
var slatIndex;
var slatRemainder;
// compute a floating-point number for how many slats should be progressed through.
// from 0 to number of slats (inclusive)
// constrained because minTime/maxTime might be customized.
slatCoverage = Math.max(0, slatCoverage);
slatCoverage = Math.min(len, slatCoverage);
// an integer index of the furthest whole slat
// from 0 to number slats (*exclusive*, so len-1)
slatIndex = Math.floor(slatCoverage);
slatIndex = Math.min(slatIndex, len - 1);
// how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
// could be 1.0 if slatCoverage is covering *all* the slots
slatRemainder = slatCoverage - slatIndex;
return this.slatPositions.tops[slatIndex] +
this.slatPositions.getHeight(slatIndex) * slatRemainder;
};
// For each segment in an array, computes and assigns its top and bottom properties
TimeGrid.prototype.computeSegVerticals = function (segs) {
var eventMinHeight = this.opt('timeGridEventMinHeight');
var i;
var seg;
var dayDate;
for (i = 0; i < segs.length; i++) {
seg = segs[i];
dayDate = this.props.cells[seg.col].date;
seg.top = this.computeDateTop(seg.start, dayDate);
seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.end, dayDate));
}
};
// Given segments that already have their top/bottom properties computed, applies those values to
// the segments' elements.
TimeGrid.prototype.assignSegVerticals = function (segs) {
var i;
var seg;
for (i = 0; i < segs.length; i++) {
seg = segs[i];
applyStyle(seg.el, this.generateSegVerticalCss(seg));
}
};
// Generates an object with CSS properties for the top/bottom coordinates of a segment element
TimeGrid.prototype.generateSegVerticalCss = function (seg) {
return {
top: seg.top,
bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container
};
};
/* Sizing
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.buildPositionCaches = function () {
this.buildColPositions();
this.buildSlatPositions();
};
TimeGrid.prototype.buildColPositions = function () {
this.colPositions.build();
};
TimeGrid.prototype.buildSlatPositions = function () {
this.slatPositions.build();
};
/* Hit System
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.positionToHit = function (positionLeft, positionTop) {
var _a = this, dateEnv = _a.dateEnv, snapsPerSlot = _a.snapsPerSlot, slatPositions = _a.slatPositions, colPositions = _a.colPositions;
var colIndex = colPositions.leftToIndex(positionLeft);
var slatIndex = slatPositions.topToIndex(positionTop);
if (colIndex != null && slatIndex != null) {
var slatTop = slatPositions.tops[slatIndex];
var slatHeight = slatPositions.getHeight(slatIndex);
var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
var snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
var dayDate = this.props.cells[colIndex].date;
var time = addDurations(this.props.dateProfile.minTime, multiplyDuration(this.snapDuration, snapIndex));
var start = dateEnv.add(dayDate, time);
var end = dateEnv.add(start, this.snapDuration);
return {
col: colIndex,
dateSpan: {
range: { start: start, end: end },
allDay: false
},
dayEl: this.colEls[colIndex],
relativeRect: {
left: colPositions.lefts[colIndex],
right: colPositions.rights[colIndex],
top: slatTop,
bottom: slatTop + slatHeight
}
};
}
};
/* Event Drag Visualization
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype._renderEventDrag = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
if (state.isEvent) {
this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
else {
this.fillRenderer.renderSegs('highlight', state.segs);
}
}
};
TimeGrid.prototype._unrenderEventDrag = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
this.fillRenderer.unrender('highlight');
}
};
/* Event Resize Visualization
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype._renderEventResize = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
}
};
TimeGrid.prototype._unrenderEventResize = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
}
};
/* Selection
------------------------------------------------------------------------------------------------------------------*/
// Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
TimeGrid.prototype._renderDateSelection = function (segs) {
if (segs) {
if (this.opt('selectMirror')) {
this.mirrorRenderer.renderSegs(segs, { isSelecting: true });
}
else {
this.fillRenderer.renderSegs('highlight', segs);
}
}
};
TimeGrid.prototype._unrenderDateSelection = function (segs) {
this.mirrorRenderer.unrender(segs, { isSelecting: true });
this.fillRenderer.unrender('highlight');
};
return TimeGrid;
}(DateComponent));
var AllDaySplitter = /** @class */ (function (_super) {
__extends(AllDaySplitter, _super);
function AllDaySplitter() {
return _super !== null && _super.apply(this, arguments) || this;
}
AllDaySplitter.prototype.getKeyInfo = function () {
return {
allDay: {},
timed: {}
};
};
AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) {
if (dateSpan.allDay) {
return ['allDay'];
}
else {
return ['timed'];
}
};
AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) {
if (!eventDef.allDay) {
return ['timed'];
}
else if (hasBgRendering(eventDef)) {
return ['timed', 'allDay'];
}
else {
return ['allDay'];
}
};
return AllDaySplitter;
}(Splitter));
var TIMEGRID_ALL_DAY_EVENT_LIMIT = 5;
var WEEK_HEADER_FORMAT = createFormatter({ week: 'short' });
/* An abstract class for all timegrid-related views. Displays one more columns with time slots running vertically.
----------------------------------------------------------------------------------------------------------------------*/
// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
// Responsible for managing width/height.
var TimeGridView = /** @class */ (function (_super) {
__extends(TimeGridView, _super);
function TimeGridView(context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.splitter = new AllDaySplitter();
/* Header Render Methods
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that will go before the day-of week header cells
_this.renderHeadIntroHtml = function () {
var _a = _this, theme = _a.theme, dateEnv = _a.dateEnv;
var range = _this.props.dateProfile.renderRange;
var dayCnt = diffDays(range.start, range.end);
var weekText;
if (_this.opt('weekNumbers')) {
weekText = dateEnv.format(range.start, WEEK_HEADER_FORMAT);
return '' +
'<th class="fc-axis fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '>' +
buildGotoAnchorHtml(// aside from link, important for matchCellWidths
_this, { date: range.start, type: 'week', forceOff: dayCnt > 1 }, htmlEscape(weekText) // inner HTML
) +
'</th>';
}
else {
return '<th class="fc-axis ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '></th>';
}
};
/* Time Grid Render Methods
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
_this.renderTimeGridBgIntroHtml = function () {
var theme = _this.theme;
return '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '></td>';
};
// Generates the HTML that goes before all other types of cells.
// Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
_this.renderTimeGridIntroHtml = function () {
return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>';
};
/* Day Grid Render Methods
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that goes before the all-day cells
_this.renderDayGridBgIntroHtml = function () {
var theme = _this.theme;
return '' +
'<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '>' +
'<span>' + // needed for matchCellWidths
getAllDayHtml(_this) +
'</span>' +
'</td>';
};
// Generates the HTML that goes before all other types of cells.
// Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
_this.renderDayGridIntroHtml = function () {
return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>';
};
_this.el.classList.add('fc-timeGrid-view');
_this.el.innerHTML = _this.renderSkeletonHtml();
_this.scroller = new ScrollComponent('hidden', // overflow x
'auto' // overflow y
);
var timeGridWrapEl = _this.scroller.el;
_this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl);
timeGridWrapEl.classList.add('fc-time-grid-container');
var timeGridEl = createElement('div', { className: 'fc-time-grid' });
timeGridWrapEl.appendChild(timeGridEl);
_this.timeGrid = new TimeGrid(_this.context, timeGridEl, {
renderBgIntroHtml: _this.renderTimeGridBgIntroHtml,
renderIntroHtml: _this.renderTimeGridIntroHtml
});
if (_this.opt('allDaySlot')) { // should we display the "all-day" area?
_this.dayGrid = new DayGrid(// the all-day subcomponent of this view
_this.context, _this.el.querySelector('.fc-day-grid'), {
renderNumberIntroHtml: _this.renderDayGridIntroHtml,
renderBgIntroHtml: _this.renderDayGridBgIntroHtml,
renderIntroHtml: _this.renderDayGridIntroHtml,
colWeekNumbersVisible: false,
cellWeekNumbersVisible: false
});
// have the day-grid extend it's coordinate area over the <hr> dividing the two grids
var dividerEl = _this.el.querySelector('.fc-divider');
_this.dayGrid.bottomCoordPadding = dividerEl.getBoundingClientRect().height;
}
return _this;
}
TimeGridView.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.timeGrid.destroy();
if (this.dayGrid) {
this.dayGrid.destroy();
}
this.scroller.destroy();
};
/* Rendering
------------------------------------------------------------------------------------------------------------------*/
// Builds the HTML skeleton for the view.
// The day-grid and time-grid components will render inside containers defined by this HTML.
TimeGridView.prototype.renderSkeletonHtml = function () {
var theme = this.theme;
return '' +
'<table class="' + theme.getClass('tableGrid') + '">' +
(this.opt('columnHeader') ?
'<thead class="fc-head">' +
'<tr>' +
'<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
'</tr>' +
'</thead>' :
'') +
'<tbody class="fc-body">' +
'<tr>' +
'<td class="' + theme.getClass('widgetContent') + '">' +
(this.opt('allDaySlot') ?
'<div class="fc-day-grid"></div>' +
'<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" />' :
'') +
'</td>' +
'</tr>' +
'</tbody>' +
'</table>';
};
/* Now Indicator
------------------------------------------------------------------------------------------------------------------*/
TimeGridView.prototype.getNowIndicatorUnit = function () {
return this.timeGrid.getNowIndicatorUnit();
};
// subclasses should implement
// renderNowIndicator(date: DateMarker) {
// }
TimeGridView.prototype.unrenderNowIndicator = function () {
this.timeGrid.unrenderNowIndicator();
};
/* Dimensions
------------------------------------------------------------------------------------------------------------------*/
TimeGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
_super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first
this.timeGrid.updateSize(isResize);
if (this.dayGrid) {
this.dayGrid.updateSize(isResize);
}
};
// Adjusts the vertical dimensions of the view to the specified values
TimeGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
var _this = this;
var eventLimit;
var scrollerHeight;
var scrollbarWidths;
// make all axis cells line up
this.axisWidth = matchCellWidths(findElements(this.el, '.fc-axis'));
// hack to give the view some height prior to timeGrid's columns being rendered
// TODO: separate setting height from scroller VS timeGrid.
if (!this.timeGrid.colEls) {
if (!isAuto) {
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
}
return;
}
// set of fake row elements that must compensate when scroller has scrollbars
var noScrollRowEls = findElements(this.el, '.fc-row').filter(function (node) {
return !_this.scroller.el.contains(node);
});
// reset all dimensions back to the original state
this.timeGrid.bottomRuleEl.style.display = 'none'; // will be shown later if this <hr> is necessary
this.scroller.clear(); // sets height to 'auto' and clears overflow
noScrollRowEls.forEach(uncompensateScroll);
// limit number of events in the all-day area
if (this.dayGrid) {
this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed
eventLimit = this.opt('eventLimit');
if (eventLimit && typeof eventLimit !== 'number') {
eventLimit = TIMEGRID_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number
}
if (eventLimit) {
this.dayGrid.limitRows(eventLimit);
}
}
if (!isAuto) { // should we force dimensions of the scroll container?
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
scrollbarWidths = this.scroller.getScrollbarWidths();
if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
// make the all-day and header rows lines up
noScrollRowEls.forEach(function (rowEl) {
compensateScroll(rowEl, scrollbarWidths);
});
// the scrollbar compensation might have changed text flow, which might affect height, so recalculate
// and reapply the desired height to the scroller.
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
}
// guarantees the same scrollbar widths
this.scroller.lockOverflow(scrollbarWidths);
// if there's any space below the slats, show the horizontal rule.
// this won't cause any new overflow, because lockOverflow already called.
if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {
this.timeGrid.bottomRuleEl.style.display = '';
}
}
};
// given a desired total height of the view, returns what the height of the scroller should be
TimeGridView.prototype.computeScrollerHeight = function (viewHeight) {
return viewHeight -
subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
};
/* Scroll
------------------------------------------------------------------------------------------------------------------*/
// Computes the initial pre-configured scroll state prior to allowing the user to change it
TimeGridView.prototype.computeDateScroll = function (duration) {
var top = this.timeGrid.computeTimeTop(duration);
// zoom can give weird floating-point values. rather scroll a little bit further
top = Math.ceil(top);
if (top) {
top++; // to overcome top border that slots beyond the first have. looks better
}
return { top: top };
};
TimeGridView.prototype.queryDateScroll = function () {
return { top: this.scroller.getScrollTop() };
};
TimeGridView.prototype.applyDateScroll = function (scroll) {
if (scroll.top !== undefined) {
this.scroller.setScrollTop(scroll.top);
}
};
// Generates an HTML attribute string for setting the width of the axis, if it is known
TimeGridView.prototype.axisStyleAttr = function () {
if (this.axisWidth != null) {
return 'style="width:' + this.axisWidth + 'px"';
}
return '';
};
return TimeGridView;
}(View));
TimeGridView.prototype.usesMinMaxTime = true; // indicates that minTime/maxTime affects rendering
var SimpleTimeGrid = /** @class */ (function (_super) {
__extends(SimpleTimeGrid, _super);
function SimpleTimeGrid(context, timeGrid) {
var _this = _super.call(this, context, timeGrid.el) || this;
_this.buildDayRanges = memoize(buildDayRanges);
_this.slicer = new TimeGridSlicer();
_this.timeGrid = timeGrid;
context.calendar.registerInteractiveComponent(_this, {
el: _this.timeGrid.el
});
return _this;
}
SimpleTimeGrid.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.calendar.unregisterInteractiveComponent(this);
};
SimpleTimeGrid.prototype.render = function (props) {
var dateProfile = props.dateProfile, dayTable = props.dayTable;
var dayRanges = this.dayRanges = this.buildDayRanges(dayTable, dateProfile, this.dateEnv);
this.timeGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, null, this.timeGrid, dayRanges), { dateProfile: dateProfile, cells: dayTable.cells[0] }));
};
SimpleTimeGrid.prototype.renderNowIndicator = function (date) {
this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(date, this.timeGrid, this.dayRanges), date);
};
SimpleTimeGrid.prototype.buildPositionCaches = function () {
this.timeGrid.buildPositionCaches();
};
SimpleTimeGrid.prototype.queryHit = function (positionLeft, positionTop) {
var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop);
if (rawHit) {
return {
component: this.timeGrid,
dateSpan: rawHit.dateSpan,
dayEl: rawHit.dayEl,
rect: {
left: rawHit.relativeRect.left,
right: rawHit.relativeRect.right,
top: rawHit.relativeRect.top,
bottom: rawHit.relativeRect.bottom
},
layer: 0
};
}
};
return SimpleTimeGrid;
}(DateComponent));
function buildDayRanges(dayTable, dateProfile, dateEnv) {
var ranges = [];
for (var _i = 0, _a = dayTable.headerDates; _i < _a.length; _i++) {
var date = _a[_i];
ranges.push({
start: dateEnv.add(date, dateProfile.minTime),
end: dateEnv.add(date, dateProfile.maxTime)
});
}
return ranges;
}
var TimeGridSlicer = /** @class */ (function (_super) {
__extends(TimeGridSlicer, _super);
function TimeGridSlicer() {
return _super !== null && _super.apply(this, arguments) || this;
}
TimeGridSlicer.prototype.sliceRange = function (range, dayRanges) {
var segs = [];
for (var col = 0; col < dayRanges.length; col++) {
var segRange = intersectRanges(range, dayRanges[col]);
if (segRange) {
segs.push({
start: segRange.start,
end: segRange.end,
isStart: segRange.start.valueOf() === range.start.valueOf(),
isEnd: segRange.end.valueOf() === range.end.valueOf(),
col: col
});
}
}
return segs;
};
return TimeGridSlicer;
}(Slicer));
var TimeGridView$1 = /** @class */ (function (_super) {
__extends(TimeGridView, _super);
function TimeGridView(_context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.buildDayTable = memoize(buildDayTable);
if (_this.opt('columnHeader')) {
_this.header = new DayHeader(_this.context, _this.el.querySelector('.fc-head-container'));
}
_this.simpleTimeGrid = new SimpleTimeGrid(_this.context, _this.timeGrid);
if (_this.dayGrid) {
_this.simpleDayGrid = new SimpleDayGrid(_this.context, _this.dayGrid);
}
return _this;
}
TimeGridView.prototype.destroy = function () {
_super.prototype.destroy.call(this);
if (this.header) {
this.header.destroy();
}
this.simpleTimeGrid.destroy();
if (this.simpleDayGrid) {
this.simpleDayGrid.destroy();
}
};
TimeGridView.prototype.render = function (props) {
_super.prototype.render.call(this, props); // for flags for updateSize
var dateProfile = this.props.dateProfile;
var dayTable = this.buildDayTable(dateProfile, this.dateProfileGenerator);
var splitProps = this.splitter.splitProps(props);
if (this.header) {
this.header.receiveProps({
dateProfile: dateProfile,
dates: dayTable.headerDates,
datesRepDistinctDays: true,
renderIntroHtml: this.renderHeadIntroHtml
});
}
this.simpleTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: dateProfile,
dayTable: dayTable }));
if (this.simpleDayGrid) {
this.simpleDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: dateProfile,
dayTable: dayTable, nextDayThreshold: this.nextDayThreshold, isRigid: false }));
}
};
TimeGridView.prototype.renderNowIndicator = function (date) {
this.simpleTimeGrid.renderNowIndicator(date);
};
return TimeGridView;
}(TimeGridView));
function buildDayTable(dateProfile, dateProfileGenerator) {
var daySeries = new DaySeries(dateProfile.renderRange, dateProfileGenerator);
return new DayTable(daySeries, false);
}
var main = createPlugin({
defaultView: 'timeGridWeek',
views: {
timeGrid: {
class: TimeGridView$1,
allDaySlot: true,
slotDuration: '00:30:00',
slotEventOverlap: true // a bad name. confused with overlap/constraint system
},
timeGridDay: {
type: 'timeGrid',
duration: { days: 1 }
},
timeGridWeek: {
type: 'timeGrid',
duration: { weeks: 1 }
}
}
});
export default main;
export { TimeGridView as AbstractTimeGridView, TimeGrid, TimeGridSlicer, TimeGridView$1 as TimeGridView, buildDayRanges, buildDayTable };
/*!
FullCalendar Time Grid Plugin v4.3.0
Docs & License: https://fullcalendar.io/
(c) 2019 Adam Shaw
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core'), require('@fullcalendar/daygrid')) :
typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core', '@fullcalendar/daygrid'], factory) :
(global = global || self, factory(global.FullCalendarTimeGrid = {}, global.FullCalendar, global.FullCalendarDayGrid));
}(this, function (exports, core, daygrid) { '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);
};
/*
Only handles foreground segs.
Does not own rendering. Use for low-level util methods by TimeGrid.
*/
var TimeGridEventRenderer = /** @class */ (function (_super) {
__extends(TimeGridEventRenderer, _super);
function TimeGridEventRenderer(timeGrid) {
var _this = _super.call(this, timeGrid.context) || this;
_this.timeGrid = timeGrid;
_this.fullTimeFormat = core.createFormatter({
hour: 'numeric',
minute: '2-digit',
separator: _this.context.options.defaultRangeSeparator
});
return _this;
}
// Given an array of foreground segments, render a DOM element for each, computes position,
// and attaches to the column inner-container elements.
TimeGridEventRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
var segsByCol = this.timeGrid.groupSegsByCol(segs);
// order the segs within each column
// TODO: have groupSegsByCol do this?
for (var col = 0; col < segsByCol.length; col++) {
segsByCol[col] = this.sortEventSegs(segsByCol[col]);
}
this.segsByCol = segsByCol;
this.timeGrid.attachSegsByCol(segsByCol, this.timeGrid.fgContainerEls);
};
TimeGridEventRenderer.prototype.detachSegs = function (segs) {
segs.forEach(function (seg) {
core.removeElement(seg.el);
});
this.segsByCol = null;
};
TimeGridEventRenderer.prototype.computeSegSizes = function (allSegs) {
var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol;
var colCnt = timeGrid.colCnt;
timeGrid.computeSegVerticals(allSegs); // horizontals relies on this
if (segsByCol) {
for (var col = 0; col < colCnt; col++) {
this.computeSegHorizontals(segsByCol[col]); // compute horizontal coordinates, z-index's, and reorder the array
}
}
};
TimeGridEventRenderer.prototype.assignSegSizes = function (allSegs) {
var _a = this, timeGrid = _a.timeGrid, segsByCol = _a.segsByCol;
var colCnt = timeGrid.colCnt;
timeGrid.assignSegVerticals(allSegs); // horizontals relies on this
if (segsByCol) {
for (var col = 0; col < colCnt; col++) {
this.assignSegCss(segsByCol[col]);
}
}
};
// Computes a default event time formatting string if `eventTimeFormat` is not explicitly defined
TimeGridEventRenderer.prototype.computeEventTimeFormat = function () {
return {
hour: 'numeric',
minute: '2-digit',
meridiem: false
};
};
// Computes a default `displayEventEnd` value if one is not expliclty defined
TimeGridEventRenderer.prototype.computeDisplayEventEnd = function () {
return true;
};
// Renders the HTML for a single event segment's default rendering
TimeGridEventRenderer.prototype.renderSegHtml = function (seg, mirrorInfo) {
var view = this.context.view;
var eventRange = seg.eventRange;
var eventDef = eventRange.def;
var eventUi = eventRange.ui;
var allDay = eventDef.allDay;
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);
var skinCss = core.cssToStr(this.getSkinCss(eventUi));
var timeText;
var fullTimeText; // more verbose time text. for the print stylesheet
var startTimeText; // just the start time text
classes.unshift('fc-time-grid-event');
// if the event appears to span more than one day...
if (core.isMultiDayRange(eventRange.range)) {
// Don't display time text on segments that run entirely through a day.
// That would appear as midnight-midnight and would look dumb.
// Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am)
if (seg.isStart || seg.isEnd) {
var unzonedStart = seg.start;
var unzonedEnd = seg.end;
timeText = this._getTimeText(unzonedStart, unzonedEnd, allDay); // TODO: give the timezones
fullTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, this.fullTimeFormat);
startTimeText = this._getTimeText(unzonedStart, unzonedEnd, allDay, null, false); // displayEnd=false
}
}
else {
// Display the normal time text for the *event's* times
timeText = this.getTimeText(eventRange);
fullTimeText = this.getTimeText(eventRange, this.fullTimeFormat);
startTimeText = this.getTimeText(eventRange, null, false); // displayEnd=false
}
return '<a class="' + classes.join(' ') + '"' +
(eventDef.url ?
' href="' + core.htmlEscape(eventDef.url) + '"' :
'') +
(skinCss ?
' style="' + skinCss + '"' :
'') +
'>' +
'<div class="fc-content">' +
(timeText ?
'<div class="fc-time"' +
' data-start="' + core.htmlEscape(startTimeText) + '"' +
' data-full="' + core.htmlEscape(fullTimeText) + '"' +
'>' +
'<span>' + core.htmlEscape(timeText) + '</span>' +
'</div>' :
'') +
(eventDef.title ?
'<div class="fc-title">' +
core.htmlEscape(eventDef.title) +
'</div>' :
'') +
'</div>' +
/* TODO: write CSS for this
(isResizableFromStart ?
'<div class="fc-resizer fc-start-resizer"></div>' :
''
) +
*/
(isResizableFromEnd ?
'<div class="fc-resizer fc-end-resizer"></div>' :
'') +
'</a>';
};
// Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.
// Assumed the segs are already ordered.
// NOTE: Also reorders the given array by date!
TimeGridEventRenderer.prototype.computeSegHorizontals = function (segs) {
var levels;
var level0;
var i;
levels = buildSlotSegLevels(segs);
computeForwardSlotSegs(levels);
if ((level0 = levels[0])) {
for (i = 0; i < level0.length; i++) {
computeSlotSegPressures(level0[i]);
}
for (i = 0; i < level0.length; i++) {
this.computeSegForwardBack(level0[i], 0, 0);
}
}
};
// Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range
// from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and
// seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left.
//
// The segment might be part of a "series", which means consecutive segments with the same pressure
// who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of
// segments behind this one in the current series, and `seriesBackwardCoord` is the starting
// coordinate of the first segment in the series.
TimeGridEventRenderer.prototype.computeSegForwardBack = function (seg, seriesBackwardPressure, seriesBackwardCoord) {
var forwardSegs = seg.forwardSegs;
var i;
if (seg.forwardCoord === undefined) { // not already computed
if (!forwardSegs.length) {
// if there are no forward segments, this segment should butt up against the edge
seg.forwardCoord = 1;
}
else {
// sort highest pressure first
this.sortForwardSegs(forwardSegs);
// this segment's forwardCoord will be calculated from the backwardCoord of the
// highest-pressure forward segment.
this.computeSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
seg.forwardCoord = forwardSegs[0].backwardCoord;
}
// calculate the backwardCoord from the forwardCoord. consider the series
seg.backwardCoord = seg.forwardCoord -
(seg.forwardCoord - seriesBackwardCoord) / // available width for series
(seriesBackwardPressure + 1); // # of segments in the series
// use this segment's coordinates to computed the coordinates of the less-pressurized
// forward segments
for (i = 0; i < forwardSegs.length; i++) {
this.computeSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
}
}
};
TimeGridEventRenderer.prototype.sortForwardSegs = function (forwardSegs) {
var objs = forwardSegs.map(buildTimeGridSegCompareObj);
var specs = [
// put higher-pressure first
{ field: 'forwardPressure', order: -1 },
// put segments that are closer to initial edge first (and favor ones with no coords yet)
{ field: 'backwardCoord', order: 1 }
].concat(this.context.view.eventOrderSpecs);
objs.sort(function (obj0, obj1) {
return core.compareByFieldSpecs(obj0, obj1, specs);
});
return objs.map(function (c) {
return c._seg;
});
};
// Given foreground event segments that have already had their position coordinates computed,
// assigns position-related CSS values to their elements.
TimeGridEventRenderer.prototype.assignSegCss = function (segs) {
for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
var seg = segs_1[_i];
core.applyStyle(seg.el, this.generateSegCss(seg));
if (seg.level > 0) {
seg.el.classList.add('fc-time-grid-event-inset');
}
// if the event is short that the title will be cut off,
// attach a className that condenses the title into the time area.
if (seg.eventRange.def.title && seg.bottom - seg.top < 30) {
seg.el.classList.add('fc-short'); // TODO: "condensed" is a better name
}
}
};
// Generates an object with CSS properties/values that should be applied to an event segment element.
// Contains important positioning-related properties that should be applied to any event element, customized or not.
TimeGridEventRenderer.prototype.generateSegCss = function (seg) {
var shouldOverlap = this.context.options.slotEventOverlap;
var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point
var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point
var props = this.timeGrid.generateSegVerticalCss(seg); // get top/bottom first
var isRtl = this.timeGrid.isRtl;
var left; // amount of space from left edge, a fraction of the total width
var right; // amount of space from right edge, a fraction of the total width
if (shouldOverlap) {
// double the width, but don't go beyond the maximum forward coordinate (1.0)
forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
}
if (isRtl) {
left = 1 - forwardCoord;
right = backwardCoord;
}
else {
left = backwardCoord;
right = 1 - forwardCoord;
}
props.zIndex = seg.level + 1; // convert from 0-base to 1-based
props.left = left * 100 + '%';
props.right = right * 100 + '%';
if (shouldOverlap && seg.forwardPressure) {
// add padding to the edge so that forward stacked events don't cover the resizer's icon
props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
}
return props;
};
return TimeGridEventRenderer;
}(core.FgEventRenderer));
// Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is
// left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date.
function buildSlotSegLevels(segs) {
var levels = [];
var i;
var seg;
var j;
for (i = 0; i < segs.length; i++) {
seg = segs[i];
// go through all the levels and stop on the first level where there are no collisions
for (j = 0; j < levels.length; j++) {
if (!computeSlotSegCollisions(seg, levels[j]).length) {
break;
}
}
seg.level = j;
(levels[j] || (levels[j] = [])).push(seg);
}
return levels;
}
// For every segment, figure out the other segments that are in subsequent
// levels that also occupy the same vertical space. Accumulate in seg.forwardSegs
function computeForwardSlotSegs(levels) {
var i;
var level;
var j;
var seg;
var k;
for (i = 0; i < levels.length; i++) {
level = levels[i];
for (j = 0; j < level.length; j++) {
seg = level[j];
seg.forwardSegs = [];
for (k = i + 1; k < levels.length; k++) {
computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
}
}
}
}
// Figure out which path forward (via seg.forwardSegs) results in the longest path until
// the furthest edge is reached. The number of segments in this path will be seg.forwardPressure
function computeSlotSegPressures(seg) {
var forwardSegs = seg.forwardSegs;
var forwardPressure = 0;
var i;
var forwardSeg;
if (seg.forwardPressure === undefined) { // not already computed
for (i = 0; i < forwardSegs.length; i++) {
forwardSeg = forwardSegs[i];
// figure out the child's maximum forward path
computeSlotSegPressures(forwardSeg);
// either use the existing maximum, or use the child's forward pressure
// plus one (for the forwardSeg itself)
forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure);
}
seg.forwardPressure = forwardPressure;
}
}
// Find all the segments in `otherSegs` that vertically collide with `seg`.
// Append into an optionally-supplied `results` array and return.
function computeSlotSegCollisions(seg, otherSegs, results) {
if (results === void 0) { results = []; }
for (var i = 0; i < otherSegs.length; i++) {
if (isSlotSegCollision(seg, otherSegs[i])) {
results.push(otherSegs[i]);
}
}
return results;
}
// Do these segments occupy the same vertical space?
function isSlotSegCollision(seg1, seg2) {
return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
}
function buildTimeGridSegCompareObj(seg) {
var obj = core.buildSegCompareObj(seg);
obj.forwardPressure = seg.forwardPressure;
obj.backwardCoord = seg.backwardCoord;
return obj;
}
var TimeGridMirrorRenderer = /** @class */ (function (_super) {
__extends(TimeGridMirrorRenderer, _super);
function TimeGridMirrorRenderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
TimeGridMirrorRenderer.prototype.attachSegs = function (segs, mirrorInfo) {
this.segsByCol = this.timeGrid.groupSegsByCol(segs);
this.timeGrid.attachSegsByCol(this.segsByCol, this.timeGrid.mirrorContainerEls);
this.sourceSeg = mirrorInfo.sourceSeg;
};
TimeGridMirrorRenderer.prototype.generateSegCss = function (seg) {
var props = _super.prototype.generateSegCss.call(this, seg);
var sourceSeg = this.sourceSeg;
if (sourceSeg && sourceSeg.col === seg.col) {
var sourceSegProps = _super.prototype.generateSegCss.call(this, sourceSeg);
props.left = sourceSegProps.left;
props.right = sourceSegProps.right;
props.marginLeft = sourceSegProps.marginLeft;
props.marginRight = sourceSegProps.marginRight;
}
return props;
};
return TimeGridMirrorRenderer;
}(TimeGridEventRenderer));
var TimeGridFillRenderer = /** @class */ (function (_super) {
__extends(TimeGridFillRenderer, _super);
function TimeGridFillRenderer(timeGrid) {
var _this = _super.call(this, timeGrid.context) || this;
_this.timeGrid = timeGrid;
return _this;
}
TimeGridFillRenderer.prototype.attachSegs = function (type, segs) {
var timeGrid = this.timeGrid;
var containerEls;
// TODO: more efficient lookup
if (type === 'bgEvent') {
containerEls = timeGrid.bgContainerEls;
}
else if (type === 'businessHours') {
containerEls = timeGrid.businessContainerEls;
}
else if (type === 'highlight') {
containerEls = timeGrid.highlightContainerEls;
}
timeGrid.attachSegsByCol(timeGrid.groupSegsByCol(segs), containerEls);
return segs.map(function (seg) {
return seg.el;
});
};
TimeGridFillRenderer.prototype.computeSegSizes = function (segs) {
this.timeGrid.computeSegVerticals(segs);
};
TimeGridFillRenderer.prototype.assignSegSizes = function (segs) {
this.timeGrid.assignSegVerticals(segs);
};
return TimeGridFillRenderer;
}(core.FillRenderer));
/* A component that renders one or more columns of vertical time slots
----------------------------------------------------------------------------------------------------------------------*/
// potential nice values for the slot-duration and interval-duration
// from largest to smallest
var AGENDA_STOCK_SUB_DURATIONS = [
{ hours: 1 },
{ minutes: 30 },
{ minutes: 15 },
{ seconds: 30 },
{ seconds: 15 }
];
var TimeGrid = /** @class */ (function (_super) {
__extends(TimeGrid, _super);
function TimeGrid(context, el, renderProps) {
var _this = _super.call(this, context, el) || this;
_this.isSlatSizesDirty = false;
_this.isColSizesDirty = false;
_this.renderSlats = core.memoizeRendering(_this._renderSlats);
var eventRenderer = _this.eventRenderer = new TimeGridEventRenderer(_this);
var fillRenderer = _this.fillRenderer = new TimeGridFillRenderer(_this);
_this.mirrorRenderer = new TimeGridMirrorRenderer(_this);
var renderColumns = _this.renderColumns = core.memoizeRendering(_this._renderColumns, _this._unrenderColumns);
_this.renderBusinessHours = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'businessHours'), fillRenderer.unrender.bind(fillRenderer, 'businessHours'), [renderColumns]);
_this.renderDateSelection = core.memoizeRendering(_this._renderDateSelection, _this._unrenderDateSelection, [renderColumns]);
_this.renderFgEvents = core.memoizeRendering(eventRenderer.renderSegs.bind(eventRenderer), eventRenderer.unrender.bind(eventRenderer), [renderColumns]);
_this.renderBgEvents = core.memoizeRendering(fillRenderer.renderSegs.bind(fillRenderer, 'bgEvent'), fillRenderer.unrender.bind(fillRenderer, 'bgEvent'), [renderColumns]);
_this.renderEventSelection = core.memoizeRendering(eventRenderer.selectByInstanceId.bind(eventRenderer), eventRenderer.unselectByInstanceId.bind(eventRenderer), [_this.renderFgEvents]);
_this.renderEventDrag = core.memoizeRendering(_this._renderEventDrag, _this._unrenderEventDrag, [renderColumns]);
_this.renderEventResize = core.memoizeRendering(_this._renderEventResize, _this._unrenderEventResize, [renderColumns]);
_this.processOptions();
el.innerHTML =
'<div class="fc-bg"></div>' +
'<div class="fc-slats"></div>' +
'<hr class="fc-divider ' + _this.theme.getClass('widgetHeader') + '" style="display:none" />';
_this.rootBgContainerEl = el.querySelector('.fc-bg');
_this.slatContainerEl = el.querySelector('.fc-slats');
_this.bottomRuleEl = el.querySelector('.fc-divider');
_this.renderProps = renderProps;
return _this;
}
/* Options
------------------------------------------------------------------------------------------------------------------*/
// Parses various options into properties of this object
TimeGrid.prototype.processOptions = function () {
var slotDuration = this.opt('slotDuration');
var snapDuration = this.opt('snapDuration');
var snapsPerSlot;
var input;
slotDuration = core.createDuration(slotDuration);
snapDuration = snapDuration ? core.createDuration(snapDuration) : slotDuration;
snapsPerSlot = core.wholeDivideDurations(slotDuration, snapDuration);
if (snapsPerSlot === null) {
snapDuration = slotDuration;
snapsPerSlot = 1;
// TODO: say warning?
}
this.slotDuration = slotDuration;
this.snapDuration = snapDuration;
this.snapsPerSlot = snapsPerSlot;
// might be an array value (for TimelineView).
// if so, getting the most granular entry (the last one probably).
input = this.opt('slotLabelFormat');
if (Array.isArray(input)) {
input = input[input.length - 1];
}
this.labelFormat = core.createFormatter(input || {
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'short'
});
input = this.opt('slotLabelInterval');
this.labelInterval = input ?
core.createDuration(input) :
this.computeLabelInterval(slotDuration);
};
// Computes an automatic value for slotLabelInterval
TimeGrid.prototype.computeLabelInterval = function (slotDuration) {
var i;
var labelInterval;
var slotsPerLabel;
// find the smallest stock label interval that results in more than one slots-per-label
for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
labelInterval = core.createDuration(AGENDA_STOCK_SUB_DURATIONS[i]);
slotsPerLabel = core.wholeDivideDurations(labelInterval, slotDuration);
if (slotsPerLabel !== null && slotsPerLabel > 1) {
return labelInterval;
}
}
return slotDuration; // fall back
};
/* Rendering
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.render = function (props) {
var cells = props.cells;
this.colCnt = cells.length;
this.renderSlats(props.dateProfile);
this.renderColumns(props.cells, props.dateProfile);
this.renderBusinessHours(props.businessHourSegs);
this.renderDateSelection(props.dateSelectionSegs);
this.renderFgEvents(props.fgEventSegs);
this.renderBgEvents(props.bgEventSegs);
this.renderEventSelection(props.eventSelection);
this.renderEventDrag(props.eventDrag);
this.renderEventResize(props.eventResize);
};
TimeGrid.prototype.destroy = function () {
_super.prototype.destroy.call(this);
// should unrender everything else too
this.renderSlats.unrender();
this.renderColumns.unrender();
};
TimeGrid.prototype.updateSize = function (isResize) {
var _a = this, fillRenderer = _a.fillRenderer, eventRenderer = _a.eventRenderer, mirrorRenderer = _a.mirrorRenderer;
if (isResize || this.isSlatSizesDirty) {
this.buildSlatPositions();
this.isSlatSizesDirty = false;
}
if (isResize || this.isColSizesDirty) {
this.buildColPositions();
this.isColSizesDirty = false;
}
fillRenderer.computeSizes(isResize);
eventRenderer.computeSizes(isResize);
mirrorRenderer.computeSizes(isResize);
fillRenderer.assignSizes(isResize);
eventRenderer.assignSizes(isResize);
mirrorRenderer.assignSizes(isResize);
};
TimeGrid.prototype._renderSlats = function (dateProfile) {
var theme = this.theme;
this.slatContainerEl.innerHTML =
'<table class="' + theme.getClass('tableGrid') + '">' +
this.renderSlatRowHtml(dateProfile) +
'</table>';
this.slatEls = core.findElements(this.slatContainerEl, 'tr');
this.slatPositions = new core.PositionCache(this.el, this.slatEls, false, true // vertical
);
this.isSlatSizesDirty = true;
};
// Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
TimeGrid.prototype.renderSlatRowHtml = function (dateProfile) {
var _a = this, dateEnv = _a.dateEnv, theme = _a.theme, isRtl = _a.isRtl;
var html = '';
var dayStart = core.startOfDay(dateProfile.renderRange.start);
var slotTime = dateProfile.minTime;
var slotIterator = core.createDuration(0);
var slotDate; // will be on the view's first day, but we only care about its time
var isLabeled;
var axisHtml;
// Calculate the time for each slot
while (core.asRoughMs(slotTime) < core.asRoughMs(dateProfile.maxTime)) {
slotDate = dateEnv.add(dayStart, slotTime);
isLabeled = core.wholeDivideDurations(slotIterator, this.labelInterval) !== null;
axisHtml =
'<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '">' +
(isLabeled ?
'<span>' + // for matchCellWidths
core.htmlEscape(dateEnv.format(slotDate, this.labelFormat)) +
'</span>' :
'') +
'</td>';
html +=
'<tr data-time="' + core.formatIsoTimeString(slotDate) + '"' +
(isLabeled ? '' : ' class="fc-minor"') +
'>' +
(!isRtl ? axisHtml : '') +
'<td class="' + theme.getClass('widgetContent') + '"></td>' +
(isRtl ? axisHtml : '') +
'</tr>';
slotTime = core.addDurations(slotTime, this.slotDuration);
slotIterator = core.addDurations(slotIterator, this.slotDuration);
}
return html;
};
TimeGrid.prototype._renderColumns = function (cells, dateProfile) {
var _a = this, theme = _a.theme, dateEnv = _a.dateEnv, view = _a.view;
var bgRow = new daygrid.DayBgRow(this.context);
this.rootBgContainerEl.innerHTML =
'<table class="' + theme.getClass('tableGrid') + '">' +
bgRow.renderHtml({
cells: cells,
dateProfile: dateProfile,
renderIntroHtml: this.renderProps.renderBgIntroHtml
}) +
'</table>';
this.colEls = core.findElements(this.el, '.fc-day, .fc-disabled-day');
for (var col = 0; col < this.colCnt; col++) {
this.publiclyTrigger('dayRender', [
{
date: dateEnv.toDate(cells[col].date),
el: this.colEls[col],
view: view
}
]);
}
if (this.isRtl) {
this.colEls.reverse();
}
this.colPositions = new core.PositionCache(this.el, this.colEls, true, // horizontal
false);
this.renderContentSkeleton();
this.isColSizesDirty = true;
};
TimeGrid.prototype._unrenderColumns = function () {
this.unrenderContentSkeleton();
};
/* Content Skeleton
------------------------------------------------------------------------------------------------------------------*/
// Renders the DOM that the view's content will live in
TimeGrid.prototype.renderContentSkeleton = function () {
var parts = [];
var skeletonEl;
parts.push(this.renderProps.renderIntroHtml());
for (var i = 0; i < this.colCnt; i++) {
parts.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>');
}
if (this.isRtl) {
parts.reverse();
}
skeletonEl = this.contentSkeletonEl = core.htmlToElement('<div class="fc-content-skeleton">' +
'<table>' +
'<tr>' + parts.join('') + '</tr>' +
'</table>' +
'</div>');
this.colContainerEls = core.findElements(skeletonEl, '.fc-content-col');
this.mirrorContainerEls = core.findElements(skeletonEl, '.fc-mirror-container');
this.fgContainerEls = core.findElements(skeletonEl, '.fc-event-container:not(.fc-mirror-container)');
this.bgContainerEls = core.findElements(skeletonEl, '.fc-bgevent-container');
this.highlightContainerEls = core.findElements(skeletonEl, '.fc-highlight-container');
this.businessContainerEls = core.findElements(skeletonEl, '.fc-business-container');
if (this.isRtl) {
this.colContainerEls.reverse();
this.mirrorContainerEls.reverse();
this.fgContainerEls.reverse();
this.bgContainerEls.reverse();
this.highlightContainerEls.reverse();
this.businessContainerEls.reverse();
}
this.el.appendChild(skeletonEl);
};
TimeGrid.prototype.unrenderContentSkeleton = function () {
core.removeElement(this.contentSkeletonEl);
};
// Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col
TimeGrid.prototype.groupSegsByCol = function (segs) {
var segsByCol = [];
var i;
for (i = 0; i < this.colCnt; i++) {
segsByCol.push([]);
}
for (i = 0; i < segs.length; i++) {
segsByCol[segs[i].col].push(segs[i]);
}
return segsByCol;
};
// Given segments grouped by column, insert the segments' elements into a parallel array of container
// elements, each living within a column.
TimeGrid.prototype.attachSegsByCol = function (segsByCol, containerEls) {
var col;
var segs;
var i;
for (col = 0; col < this.colCnt; col++) { // iterate each column grouping
segs = segsByCol[col];
for (i = 0; i < segs.length; i++) {
containerEls[col].appendChild(segs[i].el);
}
}
};
/* Now Indicator
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.getNowIndicatorUnit = function () {
return 'minute'; // will refresh on the minute
};
TimeGrid.prototype.renderNowIndicator = function (segs, date) {
// HACK: if date columns not ready for some reason (scheduler)
if (!this.colContainerEls) {
return;
}
var top = this.computeDateTop(date);
var nodes = [];
var i;
// render lines within the columns
for (i = 0; i < segs.length; i++) {
var lineEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-line' });
lineEl.style.top = top + 'px';
this.colContainerEls[segs[i].col].appendChild(lineEl);
nodes.push(lineEl);
}
// render an arrow over the axis
if (segs.length > 0) { // is the current time in view?
var arrowEl = core.createElement('div', { className: 'fc-now-indicator fc-now-indicator-arrow' });
arrowEl.style.top = top + 'px';
this.contentSkeletonEl.appendChild(arrowEl);
nodes.push(arrowEl);
}
this.nowIndicatorEls = nodes;
};
TimeGrid.prototype.unrenderNowIndicator = function () {
if (this.nowIndicatorEls) {
this.nowIndicatorEls.forEach(core.removeElement);
this.nowIndicatorEls = null;
}
};
/* Coordinates
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.getTotalSlatHeight = function () {
return this.slatContainerEl.getBoundingClientRect().height;
};
// Computes the top coordinate, relative to the bounds of the grid, of the given date.
// A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
TimeGrid.prototype.computeDateTop = function (when, startOfDayDate) {
if (!startOfDayDate) {
startOfDayDate = core.startOfDay(when);
}
return this.computeTimeTop(core.createDuration(when.valueOf() - startOfDayDate.valueOf()));
};
// Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
TimeGrid.prototype.computeTimeTop = function (duration) {
var len = this.slatEls.length;
var dateProfile = this.props.dateProfile;
var slatCoverage = (duration.milliseconds - core.asRoughMs(dateProfile.minTime)) / core.asRoughMs(this.slotDuration); // floating-point value of # of slots covered
var slatIndex;
var slatRemainder;
// compute a floating-point number for how many slats should be progressed through.
// from 0 to number of slats (inclusive)
// constrained because minTime/maxTime might be customized.
slatCoverage = Math.max(0, slatCoverage);
slatCoverage = Math.min(len, slatCoverage);
// an integer index of the furthest whole slat
// from 0 to number slats (*exclusive*, so len-1)
slatIndex = Math.floor(slatCoverage);
slatIndex = Math.min(slatIndex, len - 1);
// how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
// could be 1.0 if slatCoverage is covering *all* the slots
slatRemainder = slatCoverage - slatIndex;
return this.slatPositions.tops[slatIndex] +
this.slatPositions.getHeight(slatIndex) * slatRemainder;
};
// For each segment in an array, computes and assigns its top and bottom properties
TimeGrid.prototype.computeSegVerticals = function (segs) {
var eventMinHeight = this.opt('timeGridEventMinHeight');
var i;
var seg;
var dayDate;
for (i = 0; i < segs.length; i++) {
seg = segs[i];
dayDate = this.props.cells[seg.col].date;
seg.top = this.computeDateTop(seg.start, dayDate);
seg.bottom = Math.max(seg.top + eventMinHeight, this.computeDateTop(seg.end, dayDate));
}
};
// Given segments that already have their top/bottom properties computed, applies those values to
// the segments' elements.
TimeGrid.prototype.assignSegVerticals = function (segs) {
var i;
var seg;
for (i = 0; i < segs.length; i++) {
seg = segs[i];
core.applyStyle(seg.el, this.generateSegVerticalCss(seg));
}
};
// Generates an object with CSS properties for the top/bottom coordinates of a segment element
TimeGrid.prototype.generateSegVerticalCss = function (seg) {
return {
top: seg.top,
bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container
};
};
/* Sizing
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.buildPositionCaches = function () {
this.buildColPositions();
this.buildSlatPositions();
};
TimeGrid.prototype.buildColPositions = function () {
this.colPositions.build();
};
TimeGrid.prototype.buildSlatPositions = function () {
this.slatPositions.build();
};
/* Hit System
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype.positionToHit = function (positionLeft, positionTop) {
var _a = this, dateEnv = _a.dateEnv, snapsPerSlot = _a.snapsPerSlot, slatPositions = _a.slatPositions, colPositions = _a.colPositions;
var colIndex = colPositions.leftToIndex(positionLeft);
var slatIndex = slatPositions.topToIndex(positionTop);
if (colIndex != null && slatIndex != null) {
var slatTop = slatPositions.tops[slatIndex];
var slatHeight = slatPositions.getHeight(slatIndex);
var partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
var snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
var dayDate = this.props.cells[colIndex].date;
var time = core.addDurations(this.props.dateProfile.minTime, core.multiplyDuration(this.snapDuration, snapIndex));
var start = dateEnv.add(dayDate, time);
var end = dateEnv.add(start, this.snapDuration);
return {
col: colIndex,
dateSpan: {
range: { start: start, end: end },
allDay: false
},
dayEl: this.colEls[colIndex],
relativeRect: {
left: colPositions.lefts[colIndex],
right: colPositions.rights[colIndex],
top: slatTop,
bottom: slatTop + slatHeight
}
};
}
};
/* Event Drag Visualization
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype._renderEventDrag = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
if (state.isEvent) {
this.mirrorRenderer.renderSegs(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
}
else {
this.fillRenderer.renderSegs('highlight', state.segs);
}
}
};
TimeGrid.prototype._unrenderEventDrag = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.mirrorRenderer.unrender(state.segs, { isDragging: true, sourceSeg: state.sourceSeg });
this.fillRenderer.unrender('highlight');
}
};
/* Event Resize Visualization
------------------------------------------------------------------------------------------------------------------*/
TimeGrid.prototype._renderEventResize = function (state) {
if (state) {
this.eventRenderer.hideByHash(state.affectedInstances);
this.mirrorRenderer.renderSegs(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
}
};
TimeGrid.prototype._unrenderEventResize = function (state) {
if (state) {
this.eventRenderer.showByHash(state.affectedInstances);
this.mirrorRenderer.unrender(state.segs, { isResizing: true, sourceSeg: state.sourceSeg });
}
};
/* Selection
------------------------------------------------------------------------------------------------------------------*/
// Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.
TimeGrid.prototype._renderDateSelection = function (segs) {
if (segs) {
if (this.opt('selectMirror')) {
this.mirrorRenderer.renderSegs(segs, { isSelecting: true });
}
else {
this.fillRenderer.renderSegs('highlight', segs);
}
}
};
TimeGrid.prototype._unrenderDateSelection = function (segs) {
this.mirrorRenderer.unrender(segs, { isSelecting: true });
this.fillRenderer.unrender('highlight');
};
return TimeGrid;
}(core.DateComponent));
var AllDaySplitter = /** @class */ (function (_super) {
__extends(AllDaySplitter, _super);
function AllDaySplitter() {
return _super !== null && _super.apply(this, arguments) || this;
}
AllDaySplitter.prototype.getKeyInfo = function () {
return {
allDay: {},
timed: {}
};
};
AllDaySplitter.prototype.getKeysForDateSpan = function (dateSpan) {
if (dateSpan.allDay) {
return ['allDay'];
}
else {
return ['timed'];
}
};
AllDaySplitter.prototype.getKeysForEventDef = function (eventDef) {
if (!eventDef.allDay) {
return ['timed'];
}
else if (core.hasBgRendering(eventDef)) {
return ['timed', 'allDay'];
}
else {
return ['allDay'];
}
};
return AllDaySplitter;
}(core.Splitter));
var TIMEGRID_ALL_DAY_EVENT_LIMIT = 5;
var WEEK_HEADER_FORMAT = core.createFormatter({ week: 'short' });
/* An abstract class for all timegrid-related views. Displays one more columns with time slots running vertically.
----------------------------------------------------------------------------------------------------------------------*/
// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).
// Responsible for managing width/height.
var TimeGridView = /** @class */ (function (_super) {
__extends(TimeGridView, _super);
function TimeGridView(context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.splitter = new AllDaySplitter();
/* Header Render Methods
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that will go before the day-of week header cells
_this.renderHeadIntroHtml = function () {
var _a = _this, theme = _a.theme, dateEnv = _a.dateEnv;
var range = _this.props.dateProfile.renderRange;
var dayCnt = core.diffDays(range.start, range.end);
var weekText;
if (_this.opt('weekNumbers')) {
weekText = dateEnv.format(range.start, WEEK_HEADER_FORMAT);
return '' +
'<th class="fc-axis fc-week-number ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '>' +
core.buildGotoAnchorHtml(// aside from link, important for matchCellWidths
_this, { date: range.start, type: 'week', forceOff: dayCnt > 1 }, core.htmlEscape(weekText) // inner HTML
) +
'</th>';
}
else {
return '<th class="fc-axis ' + theme.getClass('widgetHeader') + '" ' + _this.axisStyleAttr() + '></th>';
}
};
/* Time Grid Render Methods
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.
_this.renderTimeGridBgIntroHtml = function () {
var theme = _this.theme;
return '<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '></td>';
};
// Generates the HTML that goes before all other types of cells.
// Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
_this.renderTimeGridIntroHtml = function () {
return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>';
};
/* Day Grid Render Methods
------------------------------------------------------------------------------------------------------------------*/
// Generates the HTML that goes before the all-day cells
_this.renderDayGridBgIntroHtml = function () {
var theme = _this.theme;
return '' +
'<td class="fc-axis ' + theme.getClass('widgetContent') + '" ' + _this.axisStyleAttr() + '>' +
'<span>' + // needed for matchCellWidths
core.getAllDayHtml(_this) +
'</span>' +
'</td>';
};
// Generates the HTML that goes before all other types of cells.
// Affects content-skeleton, mirror-skeleton, highlight-skeleton for both the time-grid and day-grid.
_this.renderDayGridIntroHtml = function () {
return '<td class="fc-axis" ' + _this.axisStyleAttr() + '></td>';
};
_this.el.classList.add('fc-timeGrid-view');
_this.el.innerHTML = _this.renderSkeletonHtml();
_this.scroller = new core.ScrollComponent('hidden', // overflow x
'auto' // overflow y
);
var timeGridWrapEl = _this.scroller.el;
_this.el.querySelector('.fc-body > tr > td').appendChild(timeGridWrapEl);
timeGridWrapEl.classList.add('fc-time-grid-container');
var timeGridEl = core.createElement('div', { className: 'fc-time-grid' });
timeGridWrapEl.appendChild(timeGridEl);
_this.timeGrid = new TimeGrid(_this.context, timeGridEl, {
renderBgIntroHtml: _this.renderTimeGridBgIntroHtml,
renderIntroHtml: _this.renderTimeGridIntroHtml
});
if (_this.opt('allDaySlot')) { // should we display the "all-day" area?
_this.dayGrid = new daygrid.DayGrid(// the all-day subcomponent of this view
_this.context, _this.el.querySelector('.fc-day-grid'), {
renderNumberIntroHtml: _this.renderDayGridIntroHtml,
renderBgIntroHtml: _this.renderDayGridBgIntroHtml,
renderIntroHtml: _this.renderDayGridIntroHtml,
colWeekNumbersVisible: false,
cellWeekNumbersVisible: false
});
// have the day-grid extend it's coordinate area over the <hr> dividing the two grids
var dividerEl = _this.el.querySelector('.fc-divider');
_this.dayGrid.bottomCoordPadding = dividerEl.getBoundingClientRect().height;
}
return _this;
}
TimeGridView.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.timeGrid.destroy();
if (this.dayGrid) {
this.dayGrid.destroy();
}
this.scroller.destroy();
};
/* Rendering
------------------------------------------------------------------------------------------------------------------*/
// Builds the HTML skeleton for the view.
// The day-grid and time-grid components will render inside containers defined by this HTML.
TimeGridView.prototype.renderSkeletonHtml = function () {
var theme = this.theme;
return '' +
'<table class="' + theme.getClass('tableGrid') + '">' +
(this.opt('columnHeader') ?
'<thead class="fc-head">' +
'<tr>' +
'<td class="fc-head-container ' + theme.getClass('widgetHeader') + '">&nbsp;</td>' +
'</tr>' +
'</thead>' :
'') +
'<tbody class="fc-body">' +
'<tr>' +
'<td class="' + theme.getClass('widgetContent') + '">' +
(this.opt('allDaySlot') ?
'<div class="fc-day-grid"></div>' +
'<hr class="fc-divider ' + theme.getClass('widgetHeader') + '" />' :
'') +
'</td>' +
'</tr>' +
'</tbody>' +
'</table>';
};
/* Now Indicator
------------------------------------------------------------------------------------------------------------------*/
TimeGridView.prototype.getNowIndicatorUnit = function () {
return this.timeGrid.getNowIndicatorUnit();
};
// subclasses should implement
// renderNowIndicator(date: DateMarker) {
// }
TimeGridView.prototype.unrenderNowIndicator = function () {
this.timeGrid.unrenderNowIndicator();
};
/* Dimensions
------------------------------------------------------------------------------------------------------------------*/
TimeGridView.prototype.updateSize = function (isResize, viewHeight, isAuto) {
_super.prototype.updateSize.call(this, isResize, viewHeight, isAuto); // will call updateBaseSize. important that executes first
this.timeGrid.updateSize(isResize);
if (this.dayGrid) {
this.dayGrid.updateSize(isResize);
}
};
// Adjusts the vertical dimensions of the view to the specified values
TimeGridView.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
var _this = this;
var eventLimit;
var scrollerHeight;
var scrollbarWidths;
// make all axis cells line up
this.axisWidth = core.matchCellWidths(core.findElements(this.el, '.fc-axis'));
// hack to give the view some height prior to timeGrid's columns being rendered
// TODO: separate setting height from scroller VS timeGrid.
if (!this.timeGrid.colEls) {
if (!isAuto) {
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
}
return;
}
// set of fake row elements that must compensate when scroller has scrollbars
var noScrollRowEls = core.findElements(this.el, '.fc-row').filter(function (node) {
return !_this.scroller.el.contains(node);
});
// reset all dimensions back to the original state
this.timeGrid.bottomRuleEl.style.display = 'none'; // will be shown later if this <hr> is necessary
this.scroller.clear(); // sets height to 'auto' and clears overflow
noScrollRowEls.forEach(core.uncompensateScroll);
// limit number of events in the all-day area
if (this.dayGrid) {
this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed
eventLimit = this.opt('eventLimit');
if (eventLimit && typeof eventLimit !== 'number') {
eventLimit = TIMEGRID_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number
}
if (eventLimit) {
this.dayGrid.limitRows(eventLimit);
}
}
if (!isAuto) { // should we force dimensions of the scroll container?
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
scrollbarWidths = this.scroller.getScrollbarWidths();
if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
// make the all-day and header rows lines up
noScrollRowEls.forEach(function (rowEl) {
core.compensateScroll(rowEl, scrollbarWidths);
});
// the scrollbar compensation might have changed text flow, which might affect height, so recalculate
// and reapply the desired height to the scroller.
scrollerHeight = this.computeScrollerHeight(viewHeight);
this.scroller.setHeight(scrollerHeight);
}
// guarantees the same scrollbar widths
this.scroller.lockOverflow(scrollbarWidths);
// if there's any space below the slats, show the horizontal rule.
// this won't cause any new overflow, because lockOverflow already called.
if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {
this.timeGrid.bottomRuleEl.style.display = '';
}
}
};
// given a desired total height of the view, returns what the height of the scroller should be
TimeGridView.prototype.computeScrollerHeight = function (viewHeight) {
return viewHeight -
core.subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
};
/* Scroll
------------------------------------------------------------------------------------------------------------------*/
// Computes the initial pre-configured scroll state prior to allowing the user to change it
TimeGridView.prototype.computeDateScroll = function (duration) {
var top = this.timeGrid.computeTimeTop(duration);
// zoom can give weird floating-point values. rather scroll a little bit further
top = Math.ceil(top);
if (top) {
top++; // to overcome top border that slots beyond the first have. looks better
}
return { top: top };
};
TimeGridView.prototype.queryDateScroll = function () {
return { top: this.scroller.getScrollTop() };
};
TimeGridView.prototype.applyDateScroll = function (scroll) {
if (scroll.top !== undefined) {
this.scroller.setScrollTop(scroll.top);
}
};
// Generates an HTML attribute string for setting the width of the axis, if it is known
TimeGridView.prototype.axisStyleAttr = function () {
if (this.axisWidth != null) {
return 'style="width:' + this.axisWidth + 'px"';
}
return '';
};
return TimeGridView;
}(core.View));
TimeGridView.prototype.usesMinMaxTime = true; // indicates that minTime/maxTime affects rendering
var SimpleTimeGrid = /** @class */ (function (_super) {
__extends(SimpleTimeGrid, _super);
function SimpleTimeGrid(context, timeGrid) {
var _this = _super.call(this, context, timeGrid.el) || this;
_this.buildDayRanges = core.memoize(buildDayRanges);
_this.slicer = new TimeGridSlicer();
_this.timeGrid = timeGrid;
context.calendar.registerInteractiveComponent(_this, {
el: _this.timeGrid.el
});
return _this;
}
SimpleTimeGrid.prototype.destroy = function () {
_super.prototype.destroy.call(this);
this.calendar.unregisterInteractiveComponent(this);
};
SimpleTimeGrid.prototype.render = function (props) {
var dateProfile = props.dateProfile, dayTable = props.dayTable;
var dayRanges = this.dayRanges = this.buildDayRanges(dayTable, dateProfile, this.dateEnv);
this.timeGrid.receiveProps(__assign({}, this.slicer.sliceProps(props, dateProfile, null, this.timeGrid, dayRanges), { dateProfile: dateProfile, cells: dayTable.cells[0] }));
};
SimpleTimeGrid.prototype.renderNowIndicator = function (date) {
this.timeGrid.renderNowIndicator(this.slicer.sliceNowDate(date, this.timeGrid, this.dayRanges), date);
};
SimpleTimeGrid.prototype.buildPositionCaches = function () {
this.timeGrid.buildPositionCaches();
};
SimpleTimeGrid.prototype.queryHit = function (positionLeft, positionTop) {
var rawHit = this.timeGrid.positionToHit(positionLeft, positionTop);
if (rawHit) {
return {
component: this.timeGrid,
dateSpan: rawHit.dateSpan,
dayEl: rawHit.dayEl,
rect: {
left: rawHit.relativeRect.left,
right: rawHit.relativeRect.right,
top: rawHit.relativeRect.top,
bottom: rawHit.relativeRect.bottom
},
layer: 0
};
}
};
return SimpleTimeGrid;
}(core.DateComponent));
function buildDayRanges(dayTable, dateProfile, dateEnv) {
var ranges = [];
for (var _i = 0, _a = dayTable.headerDates; _i < _a.length; _i++) {
var date = _a[_i];
ranges.push({
start: dateEnv.add(date, dateProfile.minTime),
end: dateEnv.add(date, dateProfile.maxTime)
});
}
return ranges;
}
var TimeGridSlicer = /** @class */ (function (_super) {
__extends(TimeGridSlicer, _super);
function TimeGridSlicer() {
return _super !== null && _super.apply(this, arguments) || this;
}
TimeGridSlicer.prototype.sliceRange = function (range, dayRanges) {
var segs = [];
for (var col = 0; col < dayRanges.length; col++) {
var segRange = core.intersectRanges(range, dayRanges[col]);
if (segRange) {
segs.push({
start: segRange.start,
end: segRange.end,
isStart: segRange.start.valueOf() === range.start.valueOf(),
isEnd: segRange.end.valueOf() === range.end.valueOf(),
col: col
});
}
}
return segs;
};
return TimeGridSlicer;
}(core.Slicer));
var TimeGridView$1 = /** @class */ (function (_super) {
__extends(TimeGridView, _super);
function TimeGridView(_context, viewSpec, dateProfileGenerator, parentEl) {
var _this = _super.call(this, _context, viewSpec, dateProfileGenerator, parentEl) || this;
_this.buildDayTable = core.memoize(buildDayTable);
if (_this.opt('columnHeader')) {
_this.header = new core.DayHeader(_this.context, _this.el.querySelector('.fc-head-container'));
}
_this.simpleTimeGrid = new SimpleTimeGrid(_this.context, _this.timeGrid);
if (_this.dayGrid) {
_this.simpleDayGrid = new daygrid.SimpleDayGrid(_this.context, _this.dayGrid);
}
return _this;
}
TimeGridView.prototype.destroy = function () {
_super.prototype.destroy.call(this);
if (this.header) {
this.header.destroy();
}
this.simpleTimeGrid.destroy();
if (this.simpleDayGrid) {
this.simpleDayGrid.destroy();
}
};
TimeGridView.prototype.render = function (props) {
_super.prototype.render.call(this, props); // for flags for updateSize
var dateProfile = this.props.dateProfile;
var dayTable = this.buildDayTable(dateProfile, this.dateProfileGenerator);
var splitProps = this.splitter.splitProps(props);
if (this.header) {
this.header.receiveProps({
dateProfile: dateProfile,
dates: dayTable.headerDates,
datesRepDistinctDays: true,
renderIntroHtml: this.renderHeadIntroHtml
});
}
this.simpleTimeGrid.receiveProps(__assign({}, splitProps['timed'], { dateProfile: dateProfile,
dayTable: dayTable }));
if (this.simpleDayGrid) {
this.simpleDayGrid.receiveProps(__assign({}, splitProps['allDay'], { dateProfile: dateProfile,
dayTable: dayTable, nextDayThreshold: this.nextDayThreshold, isRigid: false }));
}
};
TimeGridView.prototype.renderNowIndicator = function (date) {
this.simpleTimeGrid.renderNowIndicator(date);
};
return TimeGridView;
}(TimeGridView));
function buildDayTable(dateProfile, dateProfileGenerator) {
var daySeries = new core.DaySeries(dateProfile.renderRange, dateProfileGenerator);
return new core.DayTable(daySeries, false);
}
var main = core.createPlugin({
defaultView: 'timeGridWeek',
views: {
timeGrid: {
class: TimeGridView$1,
allDaySlot: true,
slotDuration: '00:30:00',
slotEventOverlap: true // a bad name. confused with overlap/constraint system
},
timeGridDay: {
type: 'timeGrid',
duration: { days: 1 }
},
timeGridWeek: {
type: 'timeGrid',
duration: { weeks: 1 }
}
}
});
exports.AbstractTimeGridView = TimeGridView;
exports.TimeGrid = TimeGrid;
exports.TimeGridSlicer = TimeGridSlicer;
exports.TimeGridView = TimeGridView$1;
exports.buildDayRanges = buildDayRanges;
exports.buildDayTable = buildDayTable;
exports.default = main;
Object.defineProperty(exports, '__esModule', { value: true });
}));